// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import {Script, console} from "forge-std/Script.sol";
import {MockLinkToken} from "../contracts/tokens/MockLinkToken.sol";
import {CREATE2Factory} from "../contracts/utils/CREATE2Factory.sol";

/**
 * @title DeployLinkToCanonicalAddress
 * @notice Attempt to deploy LINK token to canonical Ethereum Mainnet address using CREATE2
 * @dev This attempts to find a salt that produces the canonical address 0x514910771AF9Ca656af840dff83E8264EcF986CA
 * 
 * WARNING: This may not succeed if:
 * 1. The bytecode doesn't match the original LINK token bytecode
 * 2. The salt cannot be brute-forced within gas limits
 * 3. A different CREATE2 factory was used on mainnet
 */
contract DeployLinkToCanonicalAddress is Script {
    // Canonical Ethereum Mainnet LINK token address
    address constant CANONICAL_LINK = 0x514910771AF9Ca656af840dff83E8264EcF986CA;
    
    // Maximum salt iterations to try (brute force limit)
    uint256 constant MAX_SALT_ITERATIONS = 1000000;
    
    function run() external {
        uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
        address deployer = vm.addr(deployerPrivateKey);
        
        console.log("=== Deploy LINK Token to Canonical Address ===");
        console.log("Target Address:", vm.toString(CANONICAL_LINK));
        console.log("Deployer:", vm.toString(deployer));
        console.log("");
        
        vm.startBroadcast(deployerPrivateKey);
        
        // Step 1: Deploy CREATE2Factory (if not already deployed)
        // For this attempt, we'll deploy a new factory
        // In production, you might want to use a known factory address
        CREATE2Factory factory = new CREATE2Factory();
        address factoryAddress = address(factory);
        console.log("CREATE2Factory deployed at:", vm.toString(factoryAddress));
        console.log("");
        
        // Step 2: Get LINK token bytecode (creation code)
        bytes memory linkBytecode = type(MockLinkToken).creationCode;
        bytes32 bytecodeHash = keccak256(linkBytecode);
        console.log("LINK Token bytecode hash:", vm.toString(bytes32(bytecodeHash)));
        console.log("");
        
        // Step 3: Try to find salt that produces canonical address
        console.log("Searching for salt to match canonical address...");
        console.log("This may take some time (max iterations:", MAX_SALT_ITERATIONS, ")");
        console.log("");
        
        uint256 foundSalt = 0;
        bool saltFound = false;
        
        // Try different salt values
        for (uint256 salt = 0; salt < MAX_SALT_ITERATIONS; salt++) {
            // Compute address for this salt
            address predictedAddress = factory.computeAddress(linkBytecode, salt);
            
            if (predictedAddress == CANONICAL_LINK) {
                foundSalt = salt;
                saltFound = true;
                console.log("SALT FOUND!");
                console.log("Salt:", vm.toString(salt));
                console.log("Predicted Address:", vm.toString(predictedAddress));
                console.log("Target Address:", vm.toString(CANONICAL_LINK));
                break;
            }
            
            // Progress indicator every 10000 iterations
            if (salt > 0 && salt % 10000 == 0) {
                console.log("  Tried", vm.toString(salt), "salts...");
            }
        }
        
        if (!saltFound) {
            console.log("");
            console.log("WARNING: Could not find salt within", MAX_SALT_ITERATIONS, "iterations");
            console.log("This means one of the following:");
            console.log("  1. The bytecode doesn't match the original LINK token bytecode");
            console.log("  2. The CREATE2 factory address is different from mainnet");
            console.log("  3. The canonical LINK was deployed using CREATE, not CREATE2");
            console.log("  4. A higher salt value is needed (increase MAX_SALT_ITERATIONS)");
            console.log("");
            console.log("Recommendation: Use the existing LINK token at different address");
            console.log("or verify the original deployment method on Ethereum Mainnet");
            vm.stopBroadcast();
            return;
        }
        
        // Step 4: Deploy using the found salt
        console.log("");
        console.log("Deploying LINK token using CREATE2...");
        address deployedAddress = factory.deploy(linkBytecode, foundSalt);
        
        require(deployedAddress == CANONICAL_LINK, "Deployed address doesn't match target");
        
        console.log("LINK token deployed at:", vm.toString(deployedAddress));
        console.log("");
        
        // Step 5: Verify the deployment
        MockLinkToken linkToken = MockLinkToken(deployedAddress);
        console.log("Verifying deployment...");
        console.log("  Name:", linkToken.name());
        console.log("  Symbol:", linkToken.symbol());
        console.log("  Decimals:", linkToken.decimals());
        
        // Mint initial supply to deployer
        uint256 initialSupply = 1000000e18; // 1M LINK
        linkToken.mint(deployer, initialSupply);
        console.log("  Minted", initialSupply / 1e18, "LINK to deployer");
        
        vm.stopBroadcast();
        
        console.log("");
        console.log("=== Deployment Summary ===");
        console.log("LINK Token Address:", vm.toString(deployedAddress));
        console.log("CREATE2Factory:", vm.toString(factoryAddress));
        console.log("Salt Used:", vm.toString(foundSalt));
        console.log("Deployer:", vm.toString(deployer));
        console.log("Initial Supply:", initialSupply / 1e18, "LINK");
        console.log("");
        console.log("SUCCESS: LINK token deployed at canonical address!");
    }
}
