"use client";

import { useState, useEffect, useMemo } from "react";
import Image from "next/image";
import { useApp } from "@/contexts/AppContext";
import { Tabs, Tab, Button } from "@heroui/react";
import ReviewModal from "@/components/common/ReviewModal";
import WithdrawModal from "@/components/common/WithdrawModal";
import { buttonStyles } from "@/lib/buttonStyles";
import { useAccount, useReadContract } from 'wagmi';
import { useQuery } from '@tanstack/react-query';
import { fetchContracts } from '@/lib/api/contracts';
import { abis } from '@/lib/contracts';
import { useUSDCBalance, useTokenBalance } from '@/hooks/useBalance';
import { useDeposit } from '@/hooks/useDeposit';
import { useWithdraw } from '@/hooks/useWithdraw';
import { getTxUrl } from '@/lib/contracts';
import { useTokenBySymbol } from '@/hooks/useTokenBySymbol';
import { toast } from "sonner";
import TokenSelector from '@/components/common/TokenSelector';
import { Token } from '@/lib/api/tokens';
import { useAppKit } from "@reown/appkit/react";

interface MintSwapPanelProps {
  tokenType?: string;
  decimals?: number;
  onVaultRefresh?: () => void;
}

export default function MintSwapPanel({ tokenType = 'YT-A', decimals, onVaultRefresh }: MintSwapPanelProps) {
  const { t } = useApp();
  const [activeAction, setActiveAction] = useState<"deposit" | "withdraw">("deposit");
  const [amount, setAmount] = useState<string>("");
  const [selectedToken, setSelectedToken] = useState<Token | undefined>();
  const [isReviewModalOpen, setIsReviewModalOpen] = useState(false);
  const [isWithdrawModalOpen, setIsWithdrawModalOpen] = useState(false);
  const [mounted, setMounted] = useState(false);

  // 避免 hydration 错误
  useEffect(() => {
    setMounted(true);
  }, []);

  // Web3 集成
  const { isConnected } = useAccount();
  const { open } = useAppKit();
  const { formattedBalance: usdcBalance, isLoading: isBalanceLoading, refetch: refetchBalance } = useUSDCBalance();
  const ytToken = useTokenBySymbol(tokenType ?? '');
  const { formattedBalance: ytBalance, refetch: refetchYT } = useTokenBalance(
    ytToken?.contractAddress,
    ytToken?.decimals ?? decimals ?? 18
  );
  const {
    status: depositStatus,
    error: depositError,
    isLoading: isDepositLoading,
    approveHash,
    depositHash,
    executeApproveAndDeposit,
    reset: resetDeposit,
  } = useDeposit(ytToken);

  const {
    status: withdrawStatus,
    error: withdrawError,
    isLoading: isWithdrawLoading,
    approveHash: withdrawApproveHash,
    withdrawHash,
    executeApproveAndWithdraw,
    reset: resetWithdraw,
  } = useWithdraw(ytToken);

  // 从合约读取 nextRedemptionTime，复用 contract-registry 缓存
  const { data: contractConfigs = [] } = useQuery({
    queryKey: ['contract-registry'],
    queryFn: fetchContracts,
    staleTime: 5 * 60 * 1000,
  });
  const vaultChainId = ytToken?.chainId ?? 97;
  const factoryAddress = useMemo(() => {
    const c = contractConfigs.find(c => c.name === 'YTAssetFactory' && c.chain_id === vaultChainId);
    return c?.address as `0x${string}` | undefined;
  }, [contractConfigs, vaultChainId]);

  const priceFeedAddress = useMemo(() => {
    const c = contractConfigs.find(c => c.name === 'YTPriceFeed' && c.chain_id === vaultChainId);
    return c?.address as `0x${string}` | undefined;
  }, [contractConfigs, vaultChainId]);

  // Read selected token price from YTPriceFeed (30 dec precision)
  const { data: tokenPriceRaw } = useReadContract({
    address: priceFeedAddress,
    abi: abis.YTPriceFeed as any,
    functionName: 'getPrice',
    args: selectedToken?.contractAddress
      ? [selectedToken.contractAddress as `0x${string}`, false]
      : undefined,
    chainId: vaultChainId,
    query: { enabled: !!priceFeedAddress && !!selectedToken?.contractAddress },
  });
  const selectedTokenUSDPrice = tokenPriceRaw && (tokenPriceRaw as bigint) > 0n
    ? Number(tokenPriceRaw as bigint) / 1e30
    : null; // null = price not yet loaded

  const { data: vaultInfo, isLoading: isVaultInfoLoading } = useReadContract({
    address: factoryAddress,
    abi: abis.YTAssetFactory as any,
    functionName: 'getVaultInfo',
    args: ytToken?.contractAddress ? [ytToken.contractAddress as `0x${string}`] : undefined,
    chainId: vaultChainId,
    query: { enabled: !!factoryAddress && !!ytToken?.contractAddress },
  });

  // 超时 3 秒后不再等合约数据
  const [vaultInfoTimedOut, setVaultInfoTimedOut] = useState(false);
  useEffect(() => {
    if (!factoryAddress || !ytToken?.contractAddress) return;
    setVaultInfoTimedOut(false);
    const t = setTimeout(() => setVaultInfoTimedOut(true), 3000);
    return () => clearTimeout(t);
  }, [factoryAddress, ytToken?.contractAddress]);

  // nextRedemptionTime: getVaultInfo 返回值 index[8]
  const nextRedemptionTime = vaultInfo ? Number((vaultInfo as any[])[8]) : 0;
  const isMatured = nextRedemptionTime > 0 && nextRedemptionTime * 1000 < Date.now();

  // isFull: totalSupply[4] >= hardCap[5]
  const vaultTotalSupply: bigint = vaultInfo ? ((vaultInfo as any[])[4] as bigint) ?? 0n : 0n;
  const vaultHardCap: bigint     = vaultInfo ? ((vaultInfo as any[])[5] as bigint) ?? 0n : 0n;
  const isFull = vaultHardCap > 0n && vaultTotalSupply >= vaultHardCap;
  const maturityDateStr = nextRedemptionTime > 0
    ? new Date(nextRedemptionTime * 1000).toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' })
    : '';

  // ytPrice: getVaultInfo 返回值 index[7]，30 位小数
  const ytPriceRaw: bigint = vaultInfo ? ((vaultInfo as any[])[7] as bigint) ?? 0n : 0n;
  const ytPriceDisplay = (() => {
    if (!ytPriceRaw || ytPriceRaw <= 0n) return '--';
    const divisor = 10n ** 30n;
    const intPart = ytPriceRaw / divisor;
    const fracScaled = ((ytPriceRaw % divisor) * 1_000_000n) / divisor;
    return `$${intPart}.${fracScaled.toString().padStart(6, '0')}`;
  })();
  const usdcToken = useTokenBySymbol('USDC');
  const usdcDecimals = usdcToken?.onChainDecimals ?? usdcToken?.decimals ?? 18;
  const ytDecimals = ytToken?.onChainDecimals ?? ytToken?.decimals ?? decimals ?? 18;
  const inputDecimals = activeAction === 'deposit' ? usdcDecimals : ytDecimals;
  const displayDecimals = Math.min(inputDecimals, 6);

  const truncateDecimals = (s: string, d: number) => { const p = s.split('.'); return p.length > 1 ? `${p[0]}.${p[1].slice(0, d)}` : s; };
  const isValidAmount = (v: string) => v !== '' && !isNaN(parseFloat(v)) && parseFloat(v) > 0;

  // ytPrice as float for You Get calculation (30 dec)
  const ytPrice = ytPriceRaw > 0n ? Number(ytPriceRaw) / 1e30 : 0;
  // You Get = selectedTokenUSDPrice × amount / ytPrice
  const depositYouGet = ytPrice > 0 && selectedTokenUSDPrice !== null && isValidAmount(amount)
    ? (selectedTokenUSDPrice * parseFloat(amount)) / ytPrice
    : null;

  const handleAmountChange = (value: string) => {
    if (value === '') { setAmount(value); return; }
    if (!/^\d*\.?\d*$/.test(value)) return;
    const parts = value.split('.');
    if (parts.length > 1 && parts[1].length > displayDecimals) return;
    const maxBalance = activeAction === 'deposit' ? parseFloat(usdcBalance) : parseFloat(ytBalance);
    if (parseFloat(value) > maxBalance) {
      setAmount(truncateDecimals(activeAction === 'deposit' ? usdcBalance : ytBalance, displayDecimals));
      return;
    }
    setAmount(value);
  };

  const DEPOSIT_TOAST_ID = 'mint-deposit-tx';
  const WITHDRAW_TOAST_ID = 'mint-withdraw-tx';

  // Approve 交易提交 toast
  useEffect(() => {
    if (approveHash) {
      toast.loading(t("mintSwap.toast.approvalSubmitted"), {
        id: DEPOSIT_TOAST_ID,
        description: t("mintSwap.toast.waitingConfirmation"),
        action: { label: t("mintSwap.toast.viewTx"), onClick: () => window.open(getTxUrl(approveHash), '_blank') },
      });
    }
  }, [approveHash]);

  useEffect(() => {
    if (withdrawApproveHash) {
      toast.loading(t("mintSwap.toast.approvalSubmitted"), {
        id: WITHDRAW_TOAST_ID,
        description: t("mintSwap.toast.waitingConfirmation"),
        action: { label: t("mintSwap.toast.viewTx"), onClick: () => window.open(getTxUrl(withdrawApproveHash), '_blank') },
      });
    }
  }, [withdrawApproveHash]);

  // 主交易提交 toast
  useEffect(() => {
    if (depositHash && depositStatus === 'depositing') {
      toast.loading(t("mintSwap.toast.depositSubmitted"), {
        id: DEPOSIT_TOAST_ID,
        description: t("mintSwap.toast.waitingConfirmation"),
        action: { label: t("mintSwap.toast.viewTx"), onClick: () => window.open(getTxUrl(depositHash), '_blank') },
      });
    }
  }, [depositHash, depositStatus]);

  useEffect(() => {
    if (withdrawHash && withdrawStatus === 'withdrawing') {
      toast.loading(t("mintSwap.toast.withdrawSubmitted"), {
        id: WITHDRAW_TOAST_ID,
        description: t("mintSwap.toast.waitingConfirmation"),
        action: { label: t("mintSwap.toast.viewTx"), onClick: () => window.open(getTxUrl(withdrawHash), '_blank') },
      });
    }
  }, [withdrawHash, withdrawStatus]);

  // 存款成功后刷新余额
  useEffect(() => {
    if (depositStatus === 'success') {
      toast.success(t("mintSwap.toast.depositSuccess"), {
        id: DEPOSIT_TOAST_ID,
        description: t("mintSwap.toast.depositSuccessDesc"),
        duration: 5000,
      });
      refetchBalance();
      refetchYT();
      onVaultRefresh?.();
      const timer1 = setTimeout(() => { refetchBalance(); refetchYT(); onVaultRefresh?.(); }, 3000);
      const timer2 = setTimeout(() => { resetDeposit(); setAmount(""); }, 6000);
      return () => { clearTimeout(timer1); clearTimeout(timer2); };
    }
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [depositStatus]);

  // 取款成功后刷新余额
  useEffect(() => {
    if (withdrawStatus === 'success') {
      toast.success(t("mintSwap.toast.withdrawSuccess"), {
        id: WITHDRAW_TOAST_ID,
        description: t("mintSwap.toast.withdrawSuccessDesc"),
        duration: 5000,
      });
      refetchBalance();
      refetchYT();
      onVaultRefresh?.();
      const timer1 = setTimeout(() => { refetchBalance(); refetchYT(); onVaultRefresh?.(); }, 3000);
      const timer2 = setTimeout(() => { resetWithdraw(); setAmount(""); }, 6000);
      return () => { clearTimeout(timer1); clearTimeout(timer2); };
    }
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [withdrawStatus]);

  // 错误 toast
  useEffect(() => {
    if (depositError) {
      if (depositError === 'Transaction cancelled') {
        toast.dismiss(DEPOSIT_TOAST_ID);
      } else {
        toast.error(t("mintSwap.toast.depositFailed"), { id: DEPOSIT_TOAST_ID, duration: 5000 });
      }
    }
  }, [depositError]);

  useEffect(() => {
    if (withdrawError) {
      if (withdrawError === 'Transaction cancelled') {
        toast.dismiss(WITHDRAW_TOAST_ID);
      } else {
        toast.error(t("mintSwap.toast.withdrawFailed"), { id: WITHDRAW_TOAST_ID, duration: 5000 });
      }
    }
  }, [withdrawError]);

  return (
    <div className="bg-bg-surface dark:bg-gray-800 rounded-3xl border border-border-gray dark:border-gray-700 flex flex-col overflow-hidden">
      {/* Content */}
      <div className="flex flex-col gap-4 md:gap-6 p-4 md:p-6">
        {/* Deposit/Withdraw Toggle */}
        <Tabs
          selectedKey={activeAction}
          onSelectionChange={(key) => {
            const next = key as "deposit" | "withdraw";
            setActiveAction(next);
            setAmount("");
            if (next === "deposit") { resetWithdraw(); } else { resetDeposit(); }
          }}
          variant="solid"
          classNames={{
            base: "w-full",
            tabList: "bg-[#f9fafb] dark:bg-gray-700 rounded-xl p-1 gap-0 w-full",
            cursor: "bg-bg-surface dark:bg-gray-600 shadow-sm",
            tab: "h-8 px-4",
            tabContent: "text-body-small font-medium text-text-tertiary dark:text-gray-400 group-data-[selected=true]:font-bold group-data-[selected=true]:text-text-primary dark:group-data-[selected=true]:text-white",
          }}
        >
          <Tab key="deposit" title={t("mintSwap.deposit")} />
          <Tab key="withdraw" title={t("mintSwap.withdraw")} />
        </Tabs>

        {/* Input Area */}
        <div className="flex flex-col gap-2">
          <div className="bg-bg-subtle dark:bg-gray-700 rounded-xl border border-border-gray dark:border-gray-600 p-4 flex flex-col gap-3">
            {/* Label and Balance */}
            <div className="flex items-center justify-between">
              <span className="text-caption-tiny font-medium text-[#4b5563] dark:text-gray-400">
                {activeAction === 'deposit' ? t("mintSwap.deposit") : t("mintSwap.withdraw")}
              </span>
              <div className="flex items-center gap-1">
                <Image src="/components/common/icon0.svg" alt="" width={12} height={12} />
                <span className="text-caption-tiny font-medium text-[#4b5563] dark:text-gray-400">
                  {t("mintSwap.balance")}: {!mounted ? '0' : (isBalanceLoading ? '...' : activeAction === 'deposit'
                    ? `$${parseFloat(truncateDecimals(usdcBalance, displayDecimals)).toLocaleString('en-US', { maximumFractionDigits: displayDecimals })}`
                    : `${parseFloat(truncateDecimals(ytBalance, displayDecimals)).toLocaleString('en-US', { maximumFractionDigits: displayDecimals })} ${tokenType}`)}
                </span>
              </div>
            </div>

            {/* Input Row */}
            <div className="flex items-center justify-between gap-2">
              <div className="flex flex-col items-start flex-1">
                <input
                  type="text" inputMode="decimal"
                  placeholder="0.00"
                  value={amount}
                  onChange={(e) => handleAmountChange(e.target.value)}
                  className="w-full text-left text-heading-h3 font-bold text-text-primary dark:text-white placeholder:text-[#d1d5db] dark:placeholder:text-gray-500 bg-transparent border-none outline-none"
                />
                <span className="text-caption-tiny font-regular text-text-tertiary dark:text-gray-400">
                  {amount ? (activeAction === 'deposit' ? `≈ $${amount}` : `≈ $${amount} USDC`) : "--"}
                </span>
              </div>
              <div className="flex items-center gap-2">
                <Button
                  size="sm"
                  className={buttonStyles({ intent: "max" })}
                  onPress={() => setAmount(truncateDecimals(activeAction === 'deposit' ? usdcBalance : ytBalance, displayDecimals))}
                >
                  {t("mintSwap.max")}
                </Button>
                {activeAction === 'deposit' ? (
                  <TokenSelector
                    selectedToken={selectedToken}
                    onSelect={setSelectedToken}
                    filterTypes={['stablecoin']}
                  />
                ) : (
                  <div className="bg-white dark:bg-gray-700 rounded-full px-4 h-[46px] flex items-center gap-2">
                    <Image
                      src={ytToken?.iconUrl || '/assets/tokens/default.svg'}
                      alt={tokenType}
                      width={32}
                      height={32}
                      className="rounded-full"
                      onError={(e) => { (e.target as HTMLImageElement).src = '/assets/tokens/default.svg'; }}
                    />
                    <span className="text-body-default font-bold text-text-primary dark:text-white">{tokenType}</span>
                  </div>
                )}
              </div>
            </div>
          </div>
        </div>

        {/* Your YT Balance */}
        <div className="bg-bg-subtle dark:bg-gray-700 rounded-xl border border-border-gray dark:border-gray-600 p-4 flex flex-col gap-2">
          <span className="text-body-small font-bold text-[#4b5563] dark:text-gray-300">
            {t("mintSwap.yourTokenBalance").replace('{token}', tokenType)}
          </span>
          <div className="flex items-center justify-between gap-2">
            <span className="text-body-small font-regular text-text-tertiary dark:text-gray-400 shrink-0">
              {t("mintSwap.currentBalance")}
            </span>
            <span className="text-body-small font-bold text-[#10b981] dark:text-green-400 text-right min-w-0 truncate">
              {!mounted ? '0' : `${parseFloat(ytBalance).toLocaleString('en-US', { maximumFractionDigits: 6 })} ${tokenType}`}
            </span>
          </div>
          <div className="flex items-center justify-between gap-2">
            <span className="text-body-small font-regular text-text-tertiary dark:text-gray-400 shrink-0">
              {t("mintSwap.valueUsdc")}
            </span>
            <span className="text-body-small font-bold text-text-primary dark:text-white whitespace-nowrap">
              {!mounted ? '$0' : `≈ $${parseFloat(ytBalance).toLocaleString('en-US', { maximumFractionDigits: 6 })}`}
            </span>
          </div>
        </div>

        {/* Transaction Summary */}
        <div className="bg-bg-subtle dark:bg-gray-700 rounded-xl border border-border-gray dark:border-gray-600 p-4 flex flex-col gap-2">
          <span className="text-body-small font-bold text-[#4b5563] dark:text-gray-300">
            {t("mintSwap.transactionSummary")}
          </span>
          <div className="flex items-center justify-between gap-2">
            <span className="text-body-small font-regular text-text-tertiary dark:text-gray-400 shrink-0">
              {t("mintSwap.youGet")}
            </span>
            <span className="text-body-small font-bold text-[#10b981] dark:text-green-400 text-right min-w-0 truncate">
              {isValidAmount(amount)
                ? activeAction === 'deposit'
                  ? depositYouGet !== null
                    ? `≈ ${depositYouGet.toLocaleString('en-US', { maximumFractionDigits: 6 })} ${tokenType}`
                    : (!selectedToken ? '--' : '...')
                  : `≈ $${parseFloat(amount).toLocaleString('en-US', { maximumFractionDigits: 6 })} USDC`
                : '--'}
            </span>
          </div>
          <div className="flex items-center justify-between gap-2">
            <span className="text-body-small font-regular text-text-tertiary dark:text-gray-400 shrink-0">
              {t("mintSwap.salesPrice")}
            </span>
            <span className="text-body-small font-bold text-text-primary dark:text-white whitespace-nowrap">
              {isVaultInfoLoading && !vaultInfoTimedOut ? '...' : ytPriceDisplay}
            </span>
          </div>
        </div>

        {/* Submit Button */}
        <Button
          isDisabled={isConnected && (
            !isValidAmount(amount) ||
            isDepositLoading ||
            isWithdrawLoading ||
            ((isMatured || isFull) && activeAction === 'deposit') ||
            (!isMatured && activeAction === 'withdraw')
          )}
          color="default"
          variant="solid"
          className={buttonStyles({ intent: "theme" })}
          endContent={<Image src="/components/common/icon11.svg" alt="" width={20} height={20} />}
          onPress={() => {
            if (!isConnected) { open(); return; }
            if (amount && parseFloat(amount) > 0) {
              if (activeAction === "deposit") {
                executeApproveAndDeposit(amount);
              } else {
                executeApproveAndWithdraw(amount);
              }
            }
          }}
        >
          {!isConnected
            ? t("common.connectWallet")
            : isFull && activeAction === 'deposit'
            ? t("mintSwap.poolFull")
            : isMatured && activeAction === 'deposit'
            ? t("mintSwap.productMatured").replace("{date}", maturityDateStr)
            : activeAction === 'deposit'
            ? depositStatus === 'approving' ? t("common.approving")
              : depositStatus === 'approved' ? t("mintSwap.approvedDepositing")
              : depositStatus === 'depositing' ? t("mintSwap.depositing")
              : depositStatus === 'success' ? t("common.success")
              : depositStatus === 'error' ? t("common.failed")
              : !!amount && !isValidAmount(amount) ? t("common.invalidAmount")
              : t("mintSwap.approveDeposit")
            : !isMatured
            ? nextRedemptionTime > 0
              ? t("mintSwap.withdrawNotMatured").replace("{date}", maturityDateStr)
              : t("mintSwap.withdrawNoMaturity")
            : withdrawStatus === 'approving' ? t("common.approving")
              : withdrawStatus === 'approved' ? t("mintSwap.approvedWithdrawing")
              : withdrawStatus === 'withdrawing' ? t("mintSwap.withdrawing")
              : withdrawStatus === 'success' ? t("common.success")
              : withdrawStatus === 'error' ? t("common.failed")
              : !!amount && !isValidAmount(amount) ? t("common.invalidAmount")
              : t("mintSwap.approveWithdraw")
          }
        </Button>

        {/* Review Modal for Deposit */}
        <ReviewModal
          isOpen={isReviewModalOpen}
          onClose={() => setIsReviewModalOpen(false)}
          amount={amount}
        />

        {/* Withdraw Modal */}
        <WithdrawModal
          isOpen={isWithdrawModalOpen}
          onClose={() => setIsWithdrawModalOpen(false)}
          amount={amount}
        />

        {/* Terms */}
        <div className="flex flex-col gap-0 text-center">
          <div className="text-caption-tiny font-regular">
            <span className="text-[#9ca1af] dark:text-gray-400">
              {t("mintSwap.termsText")}{" "}
            </span>
            <span className="text-[#10b981] dark:text-green-400">
              {t("mintSwap.termsOfService")}
            </span>
            <span className="text-[#9ca1af] dark:text-gray-400">
              {" "}{t("mintSwap.and")}
            </span>
          </div>
          <span className="text-caption-tiny font-regular text-[#10b981] dark:text-green-400">
            {t("mintSwap.privacyPolicy")}
          </span>
        </div>
      </div>
    </div>
  );
}
