"use client";

import { useRouter, useSearchParams } from "next/navigation";
import { Suspense, useState, useMemo, useEffect, useCallback } from "react";
import { useQuery } from "@tanstack/react-query";
import { useReadContracts, useAccount } from "wagmi";
import Sidebar from "@/components/layout/Sidebar";
import TopBar from "@/components/layout/TopBar";
import PageTitle from "@/components/layout/PageTitle";
import SectionHeader from "@/components/layout/SectionHeader";
import ViewToggle from "@/components/fundmarket/ViewToggle";
import StatsCards from "@/components/fundmarket/StatsCards";
import StatsCardsSkeleton from "@/components/fundmarket/StatsCardsSkeleton";
import ProductCard from "@/components/fundmarket/ProductCard";
import ProductCardSkeleton from "@/components/fundmarket/ProductCardSkeleton";
import ProductCardList from "@/components/fundmarket/ProductCardList";
import ProductCardListSkeleton from "@/components/fundmarket/ProductCardListSkeleton";
import { fetchProducts, fetchStats } from "@/lib/api/fundmarket";
import { fetchContracts } from "@/lib/api/contracts";
import { abis } from "@/lib/contracts";
import { useApp } from "@/contexts/AppContext";

const erc20BalanceOfAbi = [
  {
    name: "balanceOf",
    type: "function",
    stateMutability: "view",
    inputs: [{ name: "account", type: "address" }],
    outputs: [{ name: "", type: "uint256" }],
  },
] as const;

function formatPoolCap(usd: number): string {
  if (usd >= 1_000_000) return `$${(usd / 1_000_000).toFixed(1)}M`;
  if (usd >= 1_000) return `$${(usd / 1_000).toFixed(1)}K`;
  return `$${usd.toFixed(2)}`;
}

export default function Home() {
  return (
    <Suspense>
      <HomeContent />
    </Suspense>
  );
}

function HomeContent() {
  const router = useRouter();
  const searchParams = useSearchParams();
  const { t } = useApp();
  const { address: userAddress, chainId: userChainId } = useAccount();
  const initialView = searchParams.get("view") === "list" ? "list" : "grid";
  const [viewMode, setViewMode] = useState<"grid" | "list">(initialView);
  const [isTransitioning, setIsTransitioning] = useState(false);

  const { data: products = [], isLoading: productsLoading } = useQuery({
    queryKey: ["fundmarket-products"],
    queryFn: () => fetchProducts(),
  });

  const { data: stats = [], isLoading: statsLoading } = useQuery({
    queryKey: ["fundmarket-stats"],
    queryFn: () => fetchStats(),
  });

  // 从合约注册表获取 YTAssetFactory 地址（复用已缓存的 contract-registry 查询）
  const { data: contractConfigs = [] } = useQuery({
    queryKey: ["contract-registry"],
    queryFn: fetchContracts,
    staleTime: 5 * 60 * 1000,
  });

  const factoryByChain = useMemo(() => {
    const map: Record<number, `0x${string}`> = {};
    for (const c of contractConfigs) {
      if (c.name === "YTAssetFactory" && c.address) {
        map[c.chain_id] = c.address as `0x${string}`;
      }
    }
    return map;
  }, [contractConfigs]);

  // 为每个有合约地址的产品构建 getVaultInfo 调用
  const vaultContracts = useMemo(() => {
    return products
      .filter((p) => p.contractAddress && factoryByChain[p.chainId])
      .map((p) => ({
        address: factoryByChain[p.chainId],
        abi: abis.YTAssetFactory as any,
        functionName: "getVaultInfo" as const,
        args: [p.contractAddress as `0x${string}`],
        chainId: p.chainId,
      }));
  }, [products, factoryByChain]);

  const { data: vaultData, isLoading: isVaultLoading } = useReadContracts({
    contracts: vaultContracts,
    query: { enabled: vaultContracts.length > 0 },
  });

  // 超时 3 秒后不再等合约数据，直接渲染
  const [vaultTimedOut, setVaultTimedOut] = useState(false);
  useEffect(() => {
    if (vaultContracts.length === 0) return;
    setVaultTimedOut(false);
    const t = setTimeout(() => setVaultTimedOut(true), 3000);
    return () => clearTimeout(t);
  }, [vaultContracts.length]);

  const contractsReady = vaultContracts.length === 0 || vaultData !== undefined || vaultTimedOut;

  // 从合约实时数据提取 Pool Cap / Pool Capacity % / Maturity
  const formatLockUp = (nextRedemptionTime: bigint): string => {
    const ts = Number(nextRedemptionTime);
    if (!ts) return '--';
    const diff = ts * 1000 - Date.now();
    if (diff <= 0) return 'Matured';
    const totalDays = Math.ceil(diff / (1000 * 60 * 60 * 24));
    if (totalDays >= 365) return `${Math.floor(totalDays / 365)}y ${totalDays % 365}d`;
    if (totalDays >= 30) return `${Math.floor(totalDays / 30)}mo`;
    return `${totalDays}d`;
  };

  const vaultInfoMap = useMemo(() => {
    if (!vaultData) return {} as Record<number, { poolCap: string; poolCapacityPercent: number; maturity?: string; lockUp: string; status: 'active' | 'full' | 'ended' }>;
    const map: Record<number, { poolCap: string; poolCapacityPercent: number; maturity?: string; lockUp: string; status: 'active' | 'full' | 'ended' }> = {};
    const eligibleProducts = products.filter(
      (p) => p.contractAddress && factoryByChain[p.chainId]
    );
    eligibleProducts.forEach((p, i) => {
      const entry = vaultData[i];
      if (entry?.status !== "success" || !entry.result) return;
      // getVaultInfo: [exists, totalAssets, idleAssets, managedAssets, totalSupply, hardCap, usdcPrice, ytPrice, nextRedemptionTime]
      const res = entry.result as [boolean, bigint, bigint, bigint, bigint, bigint, bigint, bigint, bigint];
      const hardCap = res[5];
      const totalSupply = res[4];
      const nextRedemptionTime = res[8];
      if (hardCap === 0n) return;

      // Pool Cap = hardCap 直接读取（18 dec YT tokens）
      const poolCapTokens = Number(hardCap) / 1e18;
      const percent = (Number(totalSupply) / Number(hardCap)) * 100;

      // Maturity = nextRedemptionTime（Unix 秒），0 表示未配置，留 undefined 让外层 fallback API 值
      let maturity: string | undefined;
      if (nextRedemptionTime > 0n) {
        const date = new Date(Number(nextRedemptionTime) * 1000);
        const dateStr = date.toLocaleDateString("en-GB", {
          day: "2-digit",
          month: "short",
          year: "numeric",
        });
        maturity = date < new Date() ? `${dateStr} (Matured)` : dateStr;
      }

      const isMatured = nextRedemptionTime > 0n && Number(nextRedemptionTime) * 1000 < Date.now();
      const isFull = hardCap > 0n && totalSupply >= hardCap;
      const status: 'active' | 'full' | 'ended' = isMatured ? 'ended' : isFull ? 'full' : 'active';

      map[p.id] = {
        poolCap: poolCapTokens > 0 ? formatPoolCap(poolCapTokens) : "--",
        poolCapacityPercent: Math.min(percent, 100),
        maturity,
        lockUp: formatLockUp(nextRedemptionTime),
        status,
      };
    });
    return map;
  }, [vaultData, products, factoryByChain]);

  // ERC20 balanceOf batch — one call per product token contract, requires wallet connected
  const balanceContracts = useMemo(() => {
    if (!userAddress) return [];
    return products
      .filter((p) => p.contractAddress && factoryByChain[p.chainId])
      .map((p) => ({
        address: p.contractAddress as `0x${string}`,
        abi: erc20BalanceOfAbi,
        functionName: "balanceOf" as const,
        args: [userAddress],
        chainId: p.chainId,
      }));
  }, [products, factoryByChain, userAddress]);

  const { data: balanceData } = useReadContracts({
    contracts: balanceContracts,
    query: { enabled: balanceContracts.length > 0 },
  });

  // Compute "Your Total Balance" = Σ(tokenBalance[i] * ytPrice[i])
  // ytPrice has 30 decimals, balance has 18 decimals → divide by 10^48
  const totalBalanceUSD = useMemo(() => {
    if (!userAddress || !vaultData || !balanceData) return null;
    const eligibleProducts = products.filter(
      (p) => p.contractAddress && factoryByChain[p.chainId]
    );
    let totalUsdMillionths = 0n;
    eligibleProducts.forEach((_, i) => {
      const vEntry = vaultData[i];
      const bEntry = balanceData[i];
      if (vEntry?.status !== "success" || !vEntry.result) return;
      if (bEntry?.status !== "success" || bEntry.result === undefined) return;
      const res = vEntry.result as [boolean, bigint, bigint, bigint, bigint, bigint, bigint, bigint, bigint];
      const ytPriceRaw = res[7];
      const balanceRaw = bEntry.result as bigint;
      if (!ytPriceRaw || !balanceRaw) return;
      // Multiply first, divide once: (balance * ytPrice * 1e6) / 10^48
      totalUsdMillionths += (balanceRaw * ytPriceRaw * 1_000_000n) / (10n ** 48n);
    });
    return Number(totalUsdMillionths) / 1_000_000;
  }, [userAddress, vaultData, balanceData, products, factoryByChain]);

  // Fetch net USDC deposited from backend (for earning calculation)
  const { data: netDepositedData } = useQuery({
    queryKey: ["net-deposited", userAddress, userChainId],
    queryFn: async () => {
      if (!userAddress) return null;
      const chainId = userChainId ?? 97;
      const res = await fetch(`/api/fundmarket/net-deposited?address=${userAddress.toLowerCase()}&chain_id=${chainId}`);
      const json = await res.json();
      return json.data as { netDepositedUSD: number } | null;
    },
    enabled: !!userAddress,
    refetchInterval: 60_000,
  });

  // Your Total Earning = currentValue (totalBalanceUSD) - netDepositedUSD
  // Only compute when netDepositedUSD > 0 (i.e. scanner has real data)
  const totalEarningUSD = useMemo(() => {
    if (totalBalanceUSD === null || !netDepositedData) return null;
    if (netDepositedData.netDepositedUSD <= 0) return null;
    return totalBalanceUSD - netDepositedData.netDepositedUSD;
  }, [totalBalanceUSD, netDepositedData]);

  // Stat label translation keys in API order
  const statLabelKeys = [
    "productPage.totalValueLocked",
    "productPage.cumulativeYield",
    "productPage.yourTotalBalance",
    "productPage.yourTotalEarning",
  ];

  // Override stats[2] (Your Total Balance) with computed on-chain value
  const displayStats = useMemo(() => {
    if (!stats.length) return stats;
    const result = stats.map((stat, i) => ({
      ...stat,
      label: statLabelKeys[i] ? t(statLabelKeys[i]) : stat.label,
    }));
    if (result[2] && totalBalanceUSD !== null) {
      result[2] = {
        ...result[2],
        value: totalBalanceUSD > 0
          ? `$${totalBalanceUSD >= 1_000_000
              ? `${(totalBalanceUSD / 1_000_000).toFixed(2)}M`
              : totalBalanceUSD >= 1_000
              ? `${(totalBalanceUSD / 1_000).toFixed(2)}K`
              : totalBalanceUSD.toFixed(2)}`
          : "$0.00",
      };
    }
    if (result[3] && totalEarningUSD !== null) {
      const isPositive = totalEarningUSD >= 0;
      const absVal = Math.abs(totalEarningUSD);
      const formatted = absVal >= 1_000_000
        ? `${(absVal / 1_000_000).toFixed(2)}M`
        : absVal >= 1_000
        ? `${(absVal / 1_000).toFixed(2)}K`
        : absVal.toFixed(2);
      result[3] = {
        ...result[3],
        value: `${isPositive ? '' : '-'}$${formatted}`,
        isPositive,
      };
    }
    return result;
  }, [stats, totalBalanceUSD, totalEarningUSD, t]);

  const loading = productsLoading || statsLoading || (isVaultLoading && !contractsReady);

  const breadcrumbItems = [
    { label: "ASSETX", href: "/market" },
    { label: "Fund Market" },
  ];

  const handleViewChange = useCallback((newMode: "grid" | "list") => {
    if (newMode === viewMode) return;
    setIsTransitioning(true);
    // 同步更新 URL search params（replaceState，不产生历史记录）
    const params = new URLSearchParams(searchParams.toString());
    if (newMode === "grid") {
      params.delete("view");
    } else {
      params.set("view", newMode);
    }
    const qs = params.toString();
    window.history.replaceState(null, "", qs ? `?${qs}` : window.location.pathname);
    setTimeout(() => {
      setViewMode(newMode);
      setIsTransitioning(false);
    }, 200);
  }, [viewMode, searchParams]);

  const handleInvest = (productId: number) => {
    router.push(`/market/product/${productId}`);
  };

  return (
    <div className="min-h-screen bg-gray-100 dark:bg-gray-800 flex">
      <Sidebar />
      <div className="flex-1 min-w-0 flex flex-col md:ml-[240px] pt-14 md:pt-0">
        {/* Top Bar */}
        <div className="bg-gray-100 dark:bg-gray-800 border-b border-border-normal dark:border-gray-700 px-4 md:px-8 py-3">
          <TopBar breadcrumbItems={breadcrumbItems} />
        </div>

        {/* Main Content */}
        <div className="px-4 md:px-8 pt-4 md:pt-8 pb-4 md:pb-8">
          {/* Page Title */}
          <PageTitle title="AssetX Fund Market" />

          {/* Stats Cards */}
          <div className="mb-8">
            {loading ? (
              <StatsCardsSkeleton />
            ) : (
              <StatsCards stats={displayStats} />
            )}
          </div>

          {/* Assets Section */}
          <div className="flex flex-col gap-6 mt-8 md:mt-16">
            {/* Section Header with View Toggle */}
            <SectionHeader title="Assets">
              <ViewToggle value={viewMode} onChange={handleViewChange} />
            </SectionHeader>

            {/* Product Cards - Grid or List View */}
            <div
              className="transition-opacity duration-200"
              style={{ opacity: isTransitioning ? 0 : 1 }}
            >
              {loading ? (
                viewMode === "grid" ? (
                  <div className="grid grid-cols-1 md:grid-cols-3 gap-6">
                    {[1, 2, 3].map((index) => (
                      <div key={index}>
                        <ProductCardSkeleton />
                      </div>
                    ))}
                  </div>
                ) : (
                  <div className="flex flex-col gap-4">
                    {[1, 2, 3].map((index) => (
                      <ProductCardListSkeleton key={index} />
                    ))}
                  </div>
                )
              ) : viewMode === "grid" ? (
                <div className="grid grid-cols-1 md:grid-cols-3 gap-6">
                  {products.map((product, index) => (
                    <div
                      key={product.id}
                      className="animate-fade-in"
                      style={{
                        animationDelay: `${index * 0.1}s`,
                      }}
                    >
                      <ProductCard
                        productId={product.id}
                        name={product.name}
                        category={product.category}
                        categoryColor={product.categoryColor}
                        iconUrl={product.iconUrl}
                        yieldAPY={product.yieldAPY}
                        poolCap={vaultInfoMap[product.id]?.poolCap ?? product.poolCap}
                        maturity={vaultInfoMap[product.id]?.maturity || "--"}
                        risk={product.risk}
                        riskLevel={product.riskLevel}
                        lockUp={vaultInfoMap[product.id]?.lockUp ?? '--'}
                        circulatingSupply={product.circulatingSupply}
                        poolCapacityPercent={vaultInfoMap[product.id]?.poolCapacityPercent ?? product.poolCapacityPercent}
                        status={vaultInfoMap[product.id]?.status}
                        onInvest={() => handleInvest(product.id)}
                      />
                    </div>
                  ))}
                </div>
              ) : (
                <div className="flex flex-col gap-4">
                  {products.map((product, index) => (
                    <div
                      key={product.id}
                      className="animate-fade-in"
                      style={{
                        animationDelay: `${index * 0.08}s`,
                      }}
                    >
                      <ProductCardList
                        productId={product.id}
                        name={product.name}
                        category={product.category}
                        categoryColor={product.categoryColor}
                        iconUrl={product.iconUrl}
                        poolCap={vaultInfoMap[product.id]?.poolCap ?? product.poolCap}
                        lockUp={vaultInfoMap[product.id]?.lockUp ?? '--'}
                        poolCapacityPercent={vaultInfoMap[product.id]?.poolCapacityPercent ?? product.poolCapacityPercent}
                        status={vaultInfoMap[product.id]?.status}
                        onInvest={() => handleInvest(product.id)}
                      />
                    </div>
                  ))}
                </div>
              )}
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}
