"use client";

import { ArrowDownLeft, ArrowUpRight, Wallet } from "lucide-react";
import Image from "next/image";
import { useRouter, useSearchParams } from "next/navigation";
import { useCallback, useEffect, useRef, useState } from "react";
import { useTranslation } from "react-i18next";

import { getWalletBalance, getWalletLogs, getWalletSettlementBills } from "@/api/wallet";
import { Button } from "@/components/ui/button";
import { Skeleton } from "@/components/ui/skeleton";
import { PlayerPanel } from "@/components/layout/player-panel";
import {
  TransferInDialog,
  TransferOutDialog,
} from "@/features/wallet/wallet-transfer-dialogs";
import { PlayerMoneyDisplay } from "@/components/player-money-display";
import { WalletLogsBlock } from "@/features/wallet/wallet-logs-block";
import { useActivePlayerCurrency } from "@/hooks/use-active-player-currency";
import { isCreditFundingPlayer } from "@/lib/player-funding-mode";
import { formatMinorAsCurrency } from "@/lib/money";
import { formatLotteryInstantInTimeZone, formatPlayerInstant } from "@/lib/player-datetime";
import { PLAYER_CURRENCY_CHANGE_EVENT } from "@/lib/player-currency-preference";
import { formatWalletClientError } from "@/lib/wallet-api-error";
import { usePlayerSessionStore } from "@/stores/player-session-store";
import type { WalletBalanceData } from "@/types/api/wallet-balance";
import { getWalletLogsLastPage, type WalletLogsData } from "@/types/api/wallet-logs";
import type {
  WalletSettlementBillItem,
  WalletSettlementBillsData,
} from "@/types/api/wallet-settlement-bills";
import type { PlayerMeData } from "@/types/api/player-me";

const WALLET_LOGS_PAGE_SIZE = 10;
type FundingModeView = "credit" | "wallet" | "unknown";

function scrollToWalletSection(id: string): void {
  if (typeof document === "undefined") return;
  document.getElementById(id)?.scrollIntoView({ behavior: "smooth", block: "start" });
}

function resolveFundingModeView(
  balance: WalletBalanceData | null,
  profile: PlayerMeData | null,
): FundingModeView {
  if (isCreditFundingPlayer(balance) || isCreditFundingPlayer(profile)) {
    return "credit";
  }

  if (balance?.funding_mode === "wallet" || profile?.funding_mode === "wallet") {
    return "wallet";
  }

  return "unknown";
}

function settlementStatusLabel(
  status: string,
  t: (key: string, options?: { defaultValue?: string }) => string,
): string {
  const fallback: Record<string, string> = {
    pending_confirm: "待确认",
    confirmed: "待收付",
    partial_paid: "部分收付",
    overdue: "已逾期",
    settled: "已结清",
  };

  return t(`wallet.settlementStatus.${status}`, { defaultValue: fallback[status] ?? status });
}

function formatPeriodRange(
  item: WalletSettlementBillItem,
  settlementTimeZone?: string,
): string {
  const start = item.period_start
    ? (settlementTimeZone
      ? formatLotteryInstantInTimeZone(item.period_start, settlementTimeZone)
      : formatPlayerInstant(item.period_start)).slice(0, 10)
    : "—";
  const end = item.period_end
    ? (settlementTimeZone
      ? formatLotteryInstantInTimeZone(item.period_end, settlementTimeZone)
      : formatPlayerInstant(item.period_end)).slice(0, 10)
    : "—";
  return `${start} / ${end}`;
}

function CreditSettlementBillsBlock({
  data,
  currency,
  settlementTimeZone,
}: {
  data: WalletSettlementBillsData | null;
  currency: string;
  settlementTimeZone?: string;
}) {
  const { t } = useTranslation("player");
  const summary = data?.summary;
  const netPending = Number(summary?.net_pending ?? 0);
  const pendingCount = Number(summary?.pending_count ?? 0);
  const netDirection = netPending >= 0 ? "receivable" : "payable";

  return (
    <section className="rounded-2xl border border-[#dce7f7] bg-white px-3 py-3 shadow-[0_10px_28px_rgba(15,23,42,0.06)]">
      <div className="flex items-start justify-between gap-3">
        <div>
          <h2 className="text-sm font-black text-[#0b3f96]">
            {t("wallet.settlementTitle", { defaultValue: "我的账期账单" })}
          </h2>
          <p className="mt-1 text-xs text-slate-500">
            {t("wallet.settlementHint", { defaultValue: "只显示未结清账单，中奖超出授信的部分在这里结算。" })}
          </p>
        </div>
        <span className="rounded-full bg-[#f1f6ff] px-2.5 py-1 text-xs font-black text-[#32518d]">
          {t("wallet.settlementPendingCount", { defaultValue: "{{count}}笔", count: pendingCount })}
        </span>
      </div>

      <div className="mt-3 grid grid-cols-2 gap-2">
        <div className="rounded-xl bg-emerald-50 px-3 py-2">
          <p className="text-xs font-bold text-emerald-700">
            {t("wallet.pendingReceivable", { defaultValue: "待收" })}
          </p>
          <p className="mt-1 font-mono text-sm font-black tabular-nums text-emerald-700">
            {formatMinorAsCurrency(summary?.pending_receivable ?? 0, currency)}
          </p>
        </div>
        <div className="rounded-xl bg-red-50 px-3 py-2">
          <p className="text-xs font-bold text-red-700">
            {t("wallet.pendingPayable", { defaultValue: "待付" })}
          </p>
          <p className="mt-1 font-mono text-sm font-black tabular-nums text-red-700">
            {formatMinorAsCurrency(summary?.pending_payable ?? 0, currency)}
          </p>
        </div>
      </div>

      <div className="mt-2 rounded-xl bg-[#f8fbff] px-3 py-2 text-xs">
        <span className="font-semibold text-slate-500">
          {netDirection === "receivable"
            ? t("wallet.netReceivable", { defaultValue: "净待收" })
            : t("wallet.netPayable", { defaultValue: "净待付" })}
        </span>
        <span className={netDirection === "receivable" ? "ml-2 font-mono font-black text-emerald-700" : "ml-2 font-mono font-black text-red-700"}>
          {formatMinorAsCurrency(Math.abs(netPending), currency)}
        </span>
      </div>

      {data === null ? (
        <Skeleton className="mt-3 h-20 w-full rounded-xl" />
      ) : data.items.length === 0 ? (
        <p className="mt-3 rounded-xl border border-dashed border-[#dce7f7] py-5 text-center text-sm text-slate-500">
          {t("wallet.noSettlementBills", { defaultValue: "暂无待结算账单" })}
        </p>
      ) : (
        <ul className="mt-3 space-y-2">
          {data.items.map((item) => {
            const receivable = item.direction === "receivable";
            return (
              <li key={item.id} className="rounded-xl border border-[#e1eaf6] px-3 py-2">
                <div className="flex items-center justify-between gap-2">
                  <div className="flex min-w-0 items-center gap-2">
                    <span className={receivable ? "rounded-full bg-emerald-100 p-1 text-emerald-700" : "rounded-full bg-red-100 p-1 text-red-700"}>
                      {receivable ? <ArrowDownLeft className="size-3.5" /> : <ArrowUpRight className="size-3.5" />}
                    </span>
                    <div className="min-w-0">
                      <p className="truncate text-sm font-black text-[#101a33]">
                        {receivable
                          ? t("wallet.agentPaysPlayer", { defaultValue: "代理应付玩家" })
                          : t("wallet.playerPaysAgent", { defaultValue: "玩家应付代理" })}
                      </p>
                      <p className="mt-0.5 text-[11px] text-slate-500">
                        {formatPeriodRange(item, settlementTimeZone)}
                      </p>
                    </div>
                  </div>
                  <div className="shrink-0 text-right">
                    <p className={receivable ? "font-mono text-sm font-black text-emerald-700" : "font-mono text-sm font-black text-red-700"}>
                      {formatMinorAsCurrency(item.unpaid_amount, currency)}
                    </p>
                    <p className="mt-0.5 text-[11px] text-slate-500">{settlementStatusLabel(item.status, t)}</p>
                  </div>
                </div>
              </li>
            );
          })}
        </ul>
      )}
    </section>
  );
}

export function WalletScreen() {
  const router = useRouter();
  const searchParams = useSearchParams();
  const { activeCurrency: currency } = useActivePlayerCurrency();
  const { t } = useTranslation("player");
  const [transferInOpen, setTransferInOpen] = useState(false);
  const [transferOutOpen, setTransferOutOpen] = useState(false);
  const [balance, setBalance] = useState<WalletBalanceData | null>(null);
  const [logs, setLogs] = useState<WalletLogsData | null>(null);
  const [settlementBills, setSettlementBills] = useState<WalletSettlementBillsData | null>(null);
  const [filter, setFilter] = useState("");
  const [loading, setLoading] = useState(true);
  const [logsLoading, setLogsLoading] = useState(false);
  const [loadingMore, setLoadingMore] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const loadMoreRef = useRef<HTMLDivElement | null>(null);

  const filterInitializedRef = useRef(false);
  const prevFilterRef = useRef("");
  const actionDeepLinkHandledRef = useRef(false);
  const sectionDeepLinkHandledRef = useRef(false);

  const profile = usePlayerSessionStore((s) => s.profile);
  const settlementTimeZone = profile?.settlement_timezone || "UTC";
  const fundingModeView = resolveFundingModeView(balance, profile);
  const fundingModeKnown = fundingModeView !== "unknown";
  const isCreditPlayer = fundingModeView === "credit";

  useEffect(() => {
    if (actionDeepLinkHandledRef.current || loading) return;
    const action = searchParams.get("action");
    if (action !== "transfer-in" && action !== "transfer-out") return;

    actionDeepLinkHandledRef.current = true;
    if (!isCreditPlayer) {
      queueMicrotask(() => {
        if (action === "transfer-in") {
          setTransferInOpen(true);
        } else {
          setTransferOutOpen(true);
        }
      });
    }
    router.replace("/wallet", { scroll: false });
  }, [isCreditPlayer, loading, router, searchParams]);

  useEffect(() => {
    if (sectionDeepLinkHandledRef.current || loading) return;
    const section = searchParams.get("section");
    if (section !== "logs" && section !== "pending") return;

    sectionDeepLinkHandledRef.current = true;
    const targetId = section === "pending" ? "wallet-pending" : "wallet-logs";
    const timer = window.setTimeout(() => {
      scrollToWalletSection(targetId);
      router.replace("/wallet", { scroll: false });
    }, 120);
    return () => window.clearTimeout(timer);
  }, [isCreditPlayer, loading, router, searchParams]);

  const loadLogs = useCallback(async (targetPage = 1, append = false) => {
    const nextLogs = await getWalletLogs({
      page: targetPage,
      size: WALLET_LOGS_PAGE_SIZE,
      type: filter || undefined,
      currency,
    });
    setLogs((current) =>
      append && current
        ? { ...nextLogs, items: [...current.items, ...nextLogs.items] }
        : nextLogs,
    );
    return nextLogs;
  }, [currency, filter]);

  useEffect(() => {
    let cancelled = false;

    void (async () => {
      setError(null);
      setLoading(true);
      try {
        const [b, nextLogs] = await Promise.all([
          getWalletBalance({ currency }),
          getWalletLogs({
            page: 1,
            size: WALLET_LOGS_PAGE_SIZE,
            type: filter || undefined,
            currency,
          }),
        ]);
        if (cancelled) return;
        setBalance(b);
        setLogs(nextLogs);
        if (isCreditFundingPlayer(b) || isCreditFundingPlayer(profile)) {
          const bills = await getWalletSettlementBills();
          if (!cancelled) setSettlementBills(bills);
        } else {
          setSettlementBills(null);
        }
      } catch (e) {
        if (!cancelled) {
          setError(formatWalletClientError(e, t));
        }
      } finally {
        if (!cancelled) {
          setLoading(false);
          setLogsLoading(false);
        }
      }
    })();

    return () => {
      cancelled = true;
    };
  }, [currency, t]); // eslint-disable-line react-hooks/exhaustive-deps -- 币种切换整页刷新；流水筛选见下方 effect

  useEffect(() => {
    if (!filterInitializedRef.current) {
      filterInitializedRef.current = true;
      prevFilterRef.current = filter;
      return;
    }
    if (prevFilterRef.current === filter) {
      return;
    }
    prevFilterRef.current = filter;

    let cancelled = false;
    setError(null);
    setLogsLoading(true);

    void (async () => {
      try {
        const nextLogs = await getWalletLogs({
          page: 1,
          size: WALLET_LOGS_PAGE_SIZE,
          type: filter || undefined,
          currency,
        });
        if (!cancelled) {
          setLogs(nextLogs);
        }
      } catch (e) {
        if (!cancelled) {
          setError(formatWalletClientError(e, t));
        }
      } finally {
        if (!cancelled) {
          setLogsLoading(false);
        }
      }
    })();

    return () => {
      cancelled = true;
    };
  }, [currency, filter, t]);

  const handleFilterChange = useCallback((value: string) => {
    if (value === filter) {
      return;
    }

    setLogs(null);
    setLogsLoading(true);
    setFilter(value);
  }, [filter]);

  const refreshAll = useCallback(async () => {
    setError(null);
    setLogsLoading(true);
    try {
      // 并行请求余额和日志
      const [b] = await Promise.all([
        getWalletBalance({ currency }),
        loadLogs(1, false),
      ]);
      setBalance(b);
      if (isCreditFundingPlayer(b) || isCreditFundingPlayer(profile)) {
        setSettlementBills(await getWalletSettlementBills());
      } else {
        setSettlementBills(null);
      }
    } catch (e) {
      setError(formatWalletClientError(e, t));
    } finally {
      setLogsLoading(false);
      setLoading(false);
    }
  }, [currency, loadLogs, profile, t]);

  useEffect(() => {
    const onCurrencyChange = () => void refreshAll();
    window.addEventListener(PLAYER_CURRENCY_CHANGE_EVENT, onCurrencyChange);
    return () => window.removeEventListener(PLAYER_CURRENCY_CHANGE_EVENT, onCurrencyChange);
  }, [refreshAll]);

  const hasMore = logs ? logs.page < getWalletLogsLastPage(logs) : false;

  const displayMinor = isCreditPlayer
    ? Number(balance?.available_balance ?? 0)
    : Number(balance?.balance ?? 0);
  const panelTitle = !fundingModeKnown
    ? t("wallet.loadingTitle", { defaultValue: "账户资金" })
    : isCreditPlayer
      ? t("wallet.creditTitle", { defaultValue: "信用" })
      : t("wallet.title");

  const loadMore = useCallback(() => {
    if (!logs || !hasMore || loadingMore) return;

    setError(null);
    setLoadingMore(true);
    void loadLogs(logs.page + 1, true)
      .catch((e) => {
        setError(formatWalletClientError(e, t));
      })
      .finally(() => {
        setLoadingMore(false);
      });
  }, [hasMore, loadLogs, loadingMore, logs, t]);

  useEffect(() => {
    const target = loadMoreRef.current;
    if (!target || loading || logsLoading || loadingMore || !hasMore) return;

    const observer = new IntersectionObserver(
      ([entry]) => {
        if (entry?.isIntersecting) {
          loadMore();
        }
      },
      { rootMargin: "160px" },
    );

    observer.observe(target);
    return () => observer.disconnect();
  }, [hasMore, loadMore, loading, loadingMore, logsLoading]);

  return (
    <PlayerPanel title={panelTitle}>
      <div className="space-y-3">
        {error ? (
          <div className="rounded-xl border border-red-200 bg-red-50 px-3 py-3 text-sm text-red-700">
            <p>{error}</p>
            <Button
              type="button"
              className="mt-3 bg-[#e5002c] text-white hover:bg-[#d10028]"
              onClick={() => void refreshAll()}
            >
              {t("actions.retry")}
            </Button>
          </div>
        ) : null}

        <section className="relative overflow-hidden rounded-xl bg-[#e5002c] px-3 py-4 text-white shadow-[0_10px_28px_rgba(229,0,44,0.25)]">
          <Image
            src="/entry/image5.png"
            alt=""
            fill
            className="pointer-events-none object-cover object-center"
            aria-hidden
          />
          <div className="relative flex items-center gap-3">
            <div className="flex size-14 shrink-0 items-center justify-center rounded-full bg-white text-[#d81435] shadow-sm">
              <Wallet className="size-7" aria-hidden />
            </div>
            <div className="min-w-0 flex-1">
              <p className="text-sm font-semibold text-white/90">
                {fundingModeKnown && isCreditPlayer
                  ? t("wallet.creditAvailable", { defaultValue: "可用信用" })
                  : fundingModeKnown
                    ? t("wallet.balance")
                    : t("wallet.loadingBalance", { defaultValue: "正在加载" })}
              </p>
              {loading || !fundingModeKnown ? (
                <Skeleton className="mt-2 h-8 w-44 rounded-md bg-white/25" />
              ) : (
                <PlayerMoneyDisplay
                  amountMinor={displayMinor}
                  currency={currency}
                  className="mt-1 text-white"
                />
              )}
              <p className="mt-2 text-xs text-white/75">
                {!fundingModeKnown
                  ? t("wallet.loadingAccountMode", { defaultValue: "正在确认资金模式…" })
                  : isCreditPlayer
                    ? t("wallet.creditSummary", {
                        defaultValue: "授信 {{limit}} · 已用 {{used}}",
                        limit: formatMinorAsCurrency(balance?.credit_limit ?? 0, currency),
                        used: formatMinorAsCurrency(balance?.used_credit ?? 0, currency),
                      })
                    : t("wallet.available", {
                        amount: formatMinorAsCurrency(balance?.available_balance ?? 0, currency),
                      })}
              </p>
            </div>
          </div>
        </section>

        {fundingModeKnown && isCreditPlayer ? (
          <CreditSettlementBillsBlock
            data={settlementBills}
            currency={currency}
            settlementTimeZone={settlementTimeZone}
          />
        ) : null}

        {fundingModeKnown && !isCreditPlayer ? (
          <div className="grid grid-cols-2 gap-3">
            <TransferInDialog
              idPrefix="wallet-"
              currency={currency}
              lotteryMinor={Number(balance?.balance ?? 0)}
              mainMinor={
                balance?.main_balance === null || balance?.main_balance === undefined
                  ? null
                  : Number(balance.main_balance)
              }
              onSuccess={refreshAll}
              triggerVariant="hall"
              triggerLabel={t("wallet.transferIn", { defaultValue: "Transfer In" })}
              triggerClassName="h-14 rounded-2xl text-base font-black"
              open={transferInOpen}
              onOpenChange={setTransferInOpen}
            />
            <TransferOutDialog
              idPrefix="wallet-"
              currency={currency}
              availableMinor={Number(balance?.available_balance ?? 0)}
              onSuccess={refreshAll}
              triggerVariant="hall"
              triggerLabel={t("wallet.transferOut", { defaultValue: "Transfer Out" })}
              triggerClassName="h-14 rounded-2xl text-base font-black"
              open={transferOutOpen}
              onOpenChange={setTransferOutOpen}
            />
          </div>
        ) : null}

        {fundingModeKnown && !isCreditPlayer && (logs?.pending_reconcile?.length ?? 0) > 0 ? (
          <section
            id="wallet-pending"
            className="scroll-mt-3 rounded-2xl border border-amber-200 bg-amber-50 px-3 py-3 text-sm text-amber-900"
          >
            <h2 className="text-sm font-black text-amber-800">
              {t("wallet.pendingSectionTitle", { defaultValue: "待对账划转" })}
            </h2>
            <p className="mt-1 text-xs text-amber-700">
              {t("wallet.pendingSectionHint", {
                defaultValue: "以下划转仍在与主站对账，请稍后刷新查看结果。",
              })}
            </p>
            <ul className="mt-3 space-y-2">
              {logs?.pending_reconcile.map((item) => (
                <li
                  key={item.transfer_no}
                  className="rounded-xl border border-amber-200 bg-white px-3 py-2"
                >
                  <div className="flex items-center justify-between gap-3">
                    <span className="font-semibold">
                      {item.direction === "in"
                        ? t("wallet.flow.transfer_in", { defaultValue: "转入" })
                        : t("wallet.flow.transfer_out", { defaultValue: "转出" })}
                    </span>
                    <span className="font-black tabular-nums text-amber-800">
                      {formatMinorAsCurrency(item.amount, item.currency_code || currency)}
                    </span>
                  </div>
                  <p className="mt-1 font-mono text-[11px] text-amber-600">{item.transfer_no}</p>
                </li>
              ))}
            </ul>
          </section>
        ) : null}

        <div id="wallet-logs" className="scroll-mt-3">
          {fundingModeKnown ? (
            <WalletLogsBlock
              creditMode={isCreditPlayer}
              logs={logs}
              logsLoading={loading || logsLoading}
              loadingMore={loadingMore}
              hasMore={hasMore}
              onLoadMore={loadMore}
              loadMoreRef={loadMoreRef}
              filter={filter}
              onFilterChange={handleFilterChange}
              currency={currency}
              settlementTimeZone={isCreditPlayer ? settlementTimeZone : undefined}
            />
          ) : (
            <Skeleton className="h-40 w-full rounded-lg" />
          )}
        </div>
      </div>
    </PlayerPanel>
  );
}
