'use client';

import { useState, useEffect, useCallback } from 'react';
import { paymentService, type PriceInfo, type TokenInfo, type MAOSDiscountTier, type UserUploadStats } from '@/lib/payment';
import {
  connectWallet, switchToChain270, getInjectedProvider,
  formatWeiToETH, formatBytes, type WalletProvider,
} from '@/lib/wallet';
import {
  Wallet, Coins, Loader2, CheckCircle, XCircle,
  Zap, Shield, Tag, ArrowRight, ExternalLink, Copy,
} from 'lucide-react';

/* ── Token icons ── */
const TOKEN_ICONS: Record<string, string> = {
  ETH: '⟠',
  MAOS: 'Ⓜ',
  USDC: '⬡',
};

interface PaymentPanelProps {
  fileSize: number;          // bytes
  fileName?: string;
  onPaid: (paymentInfo: { cid: string; txHash?: string; method: 'free' | 'eth' | 'token' }) => void;
  onUpload: () => Promise<{ cid: string; size: number }>;
  contractAddress?: string;
}

export default function PaymentPanel({
  fileSize,
  fileName,
  onPaid,
  onUpload,
  contractAddress,
}: PaymentPanelProps) {
  // Wallet state
  const [address, setAddress] = useState<string | null>(null);
  const [provider, setProvider] = useState<WalletProvider | null>(null);
  const [connecting, setConnecting] = useState(false);
  const [walletType, setWalletType] = useState<string | null>(null);
  const [wrongChain, setWrongChain] = useState(false);

  // Contract state
  const [deployed, setDeployed] = useState(false);
  const [price, setPrice] = useState<PriceInfo | null>(null);
  const [userStats, setUserStats] = useState<UserUploadStats | null>(null);
  const [tokens, setTokens] = useState<TokenInfo[]>([]);
  const [discountTiers, setDiscountTiers] = useState<MAOSDiscountTier[]>([]);
  const [selectedToken, setSelectedToken] = useState('ETH');
  const [freeTierBytes, setFreeTierBytes] = useState<bigint>(BigInt(0));

  // Upload state
  const [uploading, setUploading] = useState(false);
  const [paying, setPaying] = useState(false);
  const [status, setStatus] = useState<'idle' | 'paying' | 'uploading' | 'complete' | 'error'>('idle');
  const [error, setError] = useState<string | null>(null);
  const [txHash, setTxHash] = useState<string | null>(null);
  const [uploadResult, setUploadResult] = useState<{ cid: string; size: number } | null>(null);
  const [copied, setCopied] = useState(false);

  // Init
  useEffect(() => {
    if (contractAddress) {
      paymentService.setContractAddress(contractAddress);
    }
    paymentService.isDeployed().then(setDeployed);
  }, [contractAddress]);

  // Refresh price + stats when address or fileSize changes
  const refreshPricing = useCallback(async (addr: string, size: number) => {
    if (!deployed) return;
    try {
      const [p, stats, t, tiers, freeBytes] = await Promise.all([
        paymentService.getPrice(size, addr as `0x${string}`),
        paymentService.getUserStats(addr as `0x${string}`),
        paymentService.getSupportedTokens(),
        paymentService.getMAOSDiscountTiers(),
        paymentService.getFreeTierBytes(),
      ]);
      setPrice(p);
      setUserStats(stats);
      setTokens(t.filter(tk => tk.enabled || tk.symbol === 'ETH'));
      setDiscountTiers(tiers);
      setFreeTierBytes(freeBytes);
    } catch (e) {
      console.warn('Payment contract read failed:', e);
    }
  }, [deployed]);

  // Connect wallet
  async function handleConnect() {
    setConnecting(true);
    setError(null);
    try {
      const result = await connectWallet();
      const prov = getInjectedProvider();
      setAddress(result.address);
      setProvider(prov);

      // Detect wallet type
      // @ts-expect-error
      if (window.maosv6) setWalletType('MAOS Wallet');
      // @ts-expect-error
      else if (window.ethereum?.isRabby) setWalletType('Rabby');
      // @ts-expect-error
      else if (window.ethereum?.isMetaMask) setWalletType('MetaMask');
      else setWalletType('Wallet');

      // Check chain
      if (result.chainId !== 270) {
        setWrongChain(true);
        const switched = await switchToChain270(prov || undefined);
        if (switched) setWrongChain(false);
      }

      await refreshPricing(result.address, fileSize);
    } catch (e: any) {
      setError(e.message || 'Failed to connect wallet');
    } finally {
      setConnecting(false);
    }
  }

  // Refresh when fileSize changes
  useEffect(() => {
    if (address && deployed) {
      refreshPricing(address, fileSize);
    }
  }, [fileSize, address, deployed, refreshPricing]);

  // Pay + Upload flow
  async function handlePayAndUpload() {
    if (!provider || !address) return;
    setPaying(true);
    setError(null);
    setStatus('paying');

    try {
      // Step 1: Upload to IPFS
      setStatus('uploading');
      const upload = await onUpload();
      setUploadResult(upload);

      // Step 2: Pay (if not free)
      if (price && !price.isFree && price.finalWei > BigInt(0)) {
        if (selectedToken === 'ETH') {
          const hash = await paymentService.payWithETH(provider, upload.cid, fileSize, price.finalWei);
          setTxHash(hash);
          onPaid({ cid: upload.cid, txHash: hash, method: 'eth' });
        } else {
          // Token payment — need to find token address
          const token = tokens.find(t => t.symbol === selectedToken);
          if (!token || token.address === '0x0000000000000000000000000000000000000000') {
            throw new Error(`${selectedToken} not configured on contract`);
          }
          // Calculate token amount
          const tokenAmount = (price.finalWei * BigInt(10 ** token.decimals)) / token.weiPerToken;
          const result = await paymentService.approveAndPayWithToken(
            provider, token.address as `0x${string}`,
            upload.cid, fileSize, tokenAmount, selectedToken
          );
          setTxHash(result.payHash);
          onPaid({ cid: upload.cid, txHash: result.payHash, method: 'token' });
        }
      } else {
        // Free upload
        onPaid({ cid: upload.cid, method: 'free' });
      }

      setStatus('complete');
    } catch (e: any) {
      setError(e.message || 'Payment/upload failed');
      setStatus('error');
    } finally {
      setPaying(false);
    }
  }

  async function copyCID() {
    if (!uploadResult) return;
    try {
      await navigator.clipboard.writeText(uploadResult.cid);
      setCopied(true);
      setTimeout(() => setCopied(false), 2000);
    } catch { /* ignore */ }
  }

  /* ── Render ── */
  return (
    <div className="glass rounded-xl p-5 space-y-5">
      {/* ── Header ── */}
      <div className="flex items-center justify-between">
        <div className="flex items-center gap-2">
          <Wallet className="w-4 h-4 text-brand-400" />
          <h3 className="text-sm font-semibold text-white">Crypto Payment</h3>
        </div>
        {address && walletType && (
          <span className="text-[10px] px-2 py-0.5 rounded-full bg-surface-700 text-surface-400">
            {walletType}
          </span>
        )}
      </div>

      {!deployed ? (
        /* ── Not deployed ── */
        <div className="flex items-center gap-2 px-3 py-2 rounded-lg bg-surface-800/50 text-surface-400 text-xs">
          <Shield className="w-3.5 h-3.5" />
          Payment contract not deployed — uploads are free
        </div>
      ) : !address ? (
        /* ── Connect wallet ── */
        <button
          onClick={handleConnect}
          disabled={connecting}
          className="w-full flex items-center justify-center gap-2 px-4 py-2.5 rounded-lg bg-brand-500 hover:bg-brand-400 disabled:opacity-50 text-white text-sm font-medium transition-colors"
        >
          {connecting ? (
            <><Loader2 className="w-4 h-4 animate-spin" /> Connecting...</>
          ) : (
            <><Wallet className="w-4 h-4" /> Connect Wallet</>
          )}
        </button>
      ) : wrongChain ? (
        /* ── Wrong chain ── */
        <div className="flex items-center gap-2 px-3 py-2 rounded-lg bg-amber-500/10 border border-amber-500/20 text-amber-400 text-xs">
          <XCircle className="w-3.5 h-3.5 shrink-0" />
          Please switch to zkSync Local (chain 270)
        </div>
      ) : (
        /* ── Connected — show pricing ── */
        <div className="space-y-4">
          {/* Wallet address */}
          <div className="flex items-center justify-between px-3 py-2 rounded-lg bg-surface-800/50">
            <span className="text-xs text-surface-400">Connected</span>
            <span className="text-xs font-mono text-surface-200">
              {address.slice(0, 6)}...{address.slice(-4)}
            </span>
          </div>

          {/* Free tier info */}
          {userStats && (
            <div className="flex items-center justify-between px-3 py-2 rounded-lg bg-surface-800/50">
              <div className="flex items-center gap-2">
                <Zap className="w-3.5 h-3.5 text-accent-cyan" />
                <span className="text-xs text-surface-400">Free tier</span>
              </div>
              <span className="text-xs text-surface-300">
                {formatBytes(userStats.remainingFree)} / {formatBytes(freeTierBytes)} remaining
              </span>
            </div>
          )}

          {/* Price info */}
          {price && (
            <div className="space-y-2">
              <div className="flex items-center justify-between px-3 py-2 rounded-lg bg-surface-800/50">
                <span className="text-xs text-surface-400">File size</span>
                <span className="text-xs text-surface-200">{formatBytes(fileSize)}</span>
              </div>

              {price.isFree ? (
                <div className="flex items-center gap-2 px-3 py-2 rounded-lg bg-accent-green/10 border border-accent-green/20 text-accent-green text-xs">
                  <CheckCircle className="w-3.5 h-3.5" />
                  Free upload (within free tier)
                </div>
              ) : (
                <>
                  <div className="flex items-center justify-between px-3 py-2 rounded-lg bg-surface-800/50">
                    <span className="text-xs text-surface-400">Price</span>
                    <span className="text-xs text-surface-200">{formatWeiToETH(price.totalWei, 6)} ETH</span>
                  </div>

                  {price.discountBps > 0 && (
                    <div className="flex items-center justify-between px-3 py-2 rounded-lg bg-accent-cyan/10 border border-accent-cyan/20">
                      <div className="flex items-center gap-2">
                        <Tag className="w-3 h-3 text-accent-cyan" />
                        <span className="text-xs text-accent-cyan">MAOS discount</span>
                      </div>
                      <span className="text-xs text-accent-cyan font-medium">-{price.discountBps / 100}%</span>
                    </div>
                  )}

                  <div className="flex items-center justify-between px-3 py-2 rounded-lg bg-brand-500/10 border border-brand-500/20">
                    <span className="text-xs font-medium text-surface-300">Final</span>
                    <span className="text-sm font-bold text-brand-400">
                      {formatWeiToETH(price.finalWei, 6)} ETH
                    </span>
                  </div>

                  {/* Token selector */}
                  {tokens.length > 1 && (
                    <div>
                      <label className="text-xs text-surface-400 mb-1.5 block">Pay with</label>
                      <div className="flex gap-1.5">
                        {tokens.filter(t => t.enabled || t.symbol === 'ETH').map(token => (
                          <button
                            key={token.symbol}
                            onClick={() => setSelectedToken(token.symbol)}
                            className={`flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-medium transition-colors ${
                              selectedToken === token.symbol
                                ? 'bg-brand-500/20 text-brand-400 border border-brand-500/30'
                                : 'bg-surface-800 text-surface-400 border border-surface-700 hover:border-surface-500'
                            }`}
                          >
                            <span>{TOKEN_ICONS[token.symbol] || '●'}</span>
                            {token.symbol}
                          </button>
                        ))}
                      </div>
                    </div>
                  )}
                </>
              )}
            </div>
          )}

          {/* Action button */}
          <button
            onClick={handlePayAndUpload}
            disabled={paying || uploading || status === 'complete'}
            className="w-full flex items-center justify-center gap-2 px-4 py-2.5 rounded-lg bg-brand-500 hover:bg-brand-400 disabled:opacity-50 text-white text-sm font-medium transition-colors"
          >
            {paying ? (
              <><Loader2 className="w-4 h-4 animate-spin" /> Processing payment...</>
            ) : uploading ? (
              <><Loader2 className="w-4 h-4 animate-spin" /> Uploading to IPFS...</>
            ) : status === 'complete' ? (
              <><CheckCircle className="w-4 h-4" /> Complete</>
            ) : (
              <><ArrowRight className="w-4 h-4" /> {price?.isFree ? 'Upload Free' : `Pay & Upload`}</>
            )}
          </button>
        </div>
      )}

      {/* ── Result ── */}
      {uploadResult && status === 'complete' && (
        <div className="space-y-2 p-3 rounded-lg bg-accent-green/10 border border-accent-green/20 animate-fade-in">
          <div className="flex items-center gap-2 text-accent-green">
            <CheckCircle className="w-4 h-4" />
            <span className="text-xs font-medium">Upload + Payment successful</span>
          </div>
          <div className="flex items-center justify-between text-xs">
            <span className="text-surface-400">CID</span>
            <button onClick={copyCID} className="flex items-center gap-1 text-surface-300 hover:text-surface-100 font-mono">
              {uploadResult.cid.slice(0, 12)}...
              {copied ? <CheckCircle className="w-3 h-3 text-accent-green" /> : <Copy className="w-3 h-3" />}
            </button>
          </div>
          {txHash && (
            <div className="flex items-center justify-between text-xs">
              <span className="text-surface-400">Tx</span>
              <a
                href={`http://tom1687.no-ip.org:3050/tx/${txHash}`}
                target="_blank"
                rel="noopener noreferrer"
                className="flex items-center gap-1 text-brand-400 hover:text-brand-300 font-mono"
              >
                {txHash.slice(0, 10)}...
                <ExternalLink className="w-3 h-3" />
              </a>
            </div>
          )}
        </div>
      )}

      {/* ── Error ── */}
      {error && (
        <div className="flex items-center gap-2 px-3 py-2 rounded-lg bg-accent-rose/10 border border-accent-rose/20 text-accent-rose text-xs animate-fade-in">
          <XCircle className="w-3.5 h-3.5 shrink-0" />
          {error}
        </div>
      )}

      {/* ── MAOS Discount tiers ── */}
      {address && discountTiers.length > 0 && (
        <details className="text-xs text-surface-500">
          <summary className="cursor-pointer hover:text-surface-400 transition-colors">
            MAOS discount tiers
          </summary>
          <div className="mt-2 space-y-1">
            {discountTiers.map((tier, i) => (
              <div key={i} className="flex justify-between px-2 py-1 rounded bg-surface-800/30">
                <span>{formatWeiToETH(tier.minBalance, 0)} MAOS</span>
                <span className="text-accent-cyan">{tier.discountBps / 100}% off</span>
              </div>
            ))}
          </div>
        </details>
      )}
    </div>
  );
}
