'use client';

import { useState, useEffect, useCallback } from 'react';
import { usePaymentService, type PriceInfo, type TokenInfo, type MAOSDiscountTier, type UserUploadStats } from '@/lib/payment';
import {
  connectWallet, switchToChain270, getInjectedProvider,
  type WalletProvider,
} from '@/lib/wallet';
import PaymentHeader from './PaymentHeader';
import PricingDisplay from './PricingDisplay';
import PaymentResult from './PaymentResult';

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) {
  const paymentService = usePaymentService();
  // 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);

  // Init
  useEffect(() => {
    if (contractAddress) {
      paymentService.setContractAddress(contractAddress);
    }
    paymentService.isDeployed().then(setDeployed).catch((err) => { console.error('[PaymentPanel] Deploy check failed:', err); setDeployed(false); });
  }, [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
      if (window.maosv6) setWalletType('MAOS Wallet');
      else if (window.ethereum?.isRabby) setWalletType('Rabby');
      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: unknown) {
      setError(e instanceof Error ? 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) ** BigInt(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: unknown) {
      setError(e instanceof Error ? e.message : 'Payment/upload failed');
      setStatus('error');
    } finally {
      setPaying(false);
    }
  }

  /* ── Render ── */
  return (
    <div className="glass rounded-xl p-5 space-y-5">
      <PaymentHeader
        deployed={deployed}
        address={address}
        walletType={walletType}
        connecting={connecting}
        wrongChain={wrongChain}
        onConnect={handleConnect}
      />

      {deployed && address && !wrongChain && (
        <PricingDisplay
          price={price}
          userStats={userStats}
          tokens={tokens}
          discountTiers={discountTiers}
          selectedToken={selectedToken}
          freeTierBytes={freeTierBytes}
          fileSize={fileSize}
          status={status}
          paying={paying}
          uploading={uploading}
          address={address}
          onSelectToken={setSelectedToken}
          onPayAndUpload={handlePayAndUpload}
        />
      )}

      <PaymentResult
        uploadResult={uploadResult}
        txHash={txHash}
        status={status}
        error={error}
      />
    </div>
  );
}
