import { Contract, JsonRpcProvider, Wallet, parseUnits } from 'ethers';

function rpcUrl(): string | undefined {
  return process.env.RPC_URL_138 || process.env.CHAIN_138_RPC_URL;
}

function operatorKey(): string | undefined {
  return process.env.OMNL_MINT_OPERATOR_PRIVATE_KEY?.trim();
}

function chainExecuteEnabled(): boolean {
  return (
    process.env.SETTLEMENT_ALLOW_CHAIN_MINT_EXECUTE === '1' ||
    process.env.OMNL_ALLOW_CHAIN_MINT_EXECUTE === '1'
  );
}

async function tokenDecimals(token: Contract, fallback = 18): Promise<number> {
  try {
    return Number(await token.decimals());
  } catch {
    return fallback;
  }
}

/** Mint M2 compliant token to recipient wallet (Chain 138). */
export async function executeM2TokenMint(params: {
  tokenAddress: string;
  recipient: string;
  amount: string;
  decimals?: number;
}): Promise<{ txHash: string }> {
  const pk = operatorKey();
  const rpc = rpcUrl();
  if (!chainExecuteEnabled()) {
    throw new Error('Chain mint execute disabled — set SETTLEMENT_ALLOW_CHAIN_MINT_EXECUTE=1');
  }
  if (!pk || !rpc) {
    throw new Error('OMNL_MINT_OPERATOR_PRIVATE_KEY and RPC_URL_138 required for on-chain mint');
  }
  if (!params.tokenAddress?.startsWith('0x')) {
    throw new Error('tokenAddress required for on-chain mint');
  }

  const provider = new JsonRpcProvider(rpc);
  const wallet = new Wallet(pk, provider);
  const abi = [
    'function mint(address to, uint256 amount)',
    'function decimals() view returns (uint8)',
  ];
  const token = new Contract(params.tokenAddress, abi, wallet);
  const decimals = await tokenDecimals(token, params.decimals ?? 18);
  const wei = parseUnits(params.amount, decimals);
  const tx = await token.mint(params.recipient, wei);
  const receipt = await tx.wait(1);
  return { txHash: receipt?.hash ?? tx.hash };
}

/** Transfer ERC-20 from operator treasury to recipient (internal / web3 wallet). */
export async function executeErc20Transfer(params: {
  tokenAddress: string;
  recipient: string;
  amount: string;
  decimals?: number;
}): Promise<{ txHash: string }> {
  const pk = operatorKey();
  const rpc = rpcUrl();
  if (!chainExecuteEnabled()) {
    throw new Error('Chain transfer execute disabled — set SETTLEMENT_ALLOW_CHAIN_MINT_EXECUTE=1');
  }
  if (!pk || !rpc) {
    throw new Error('OMNL_MINT_OPERATOR_PRIVATE_KEY and RPC_URL_138 required for on-chain transfer');
  }
  if (!params.tokenAddress?.startsWith('0x')) {
    throw new Error('tokenAddress required for on-chain transfer');
  }

  const provider = new JsonRpcProvider(rpc);
  const wallet = new Wallet(pk, provider);
  const abi = [
    'function transfer(address to, uint256 amount) returns (bool)',
    'function decimals() view returns (uint8)',
  ];
  const token = new Contract(params.tokenAddress, abi, wallet);
  const decimals = await tokenDecimals(token, params.decimals ?? 18);
  const wei = parseUnits(params.amount, decimals);
  const tx = await token.transfer(params.recipient, wei);
  const receipt = await tx.wait(1);
  return { txHash: receipt?.hash ?? tx.hash };
}

export function chainRailConfigured(): boolean {
  return Boolean(operatorKey() && rpcUrl() && chainExecuteEnabled());
}
