"use client";

import dynamic from "next/dynamic";
import Link from "next/link";
import { useCallback, useMemo, useState, type ReactElement } from "react";
import { useTranslation } from "react-i18next";
import { AlertTriangle, BarChart3, ClipboardList, RefreshCw, Shield, TrendingUp, Wallet } from "lucide-react";

import { getAdminDashboardByScope } from "@/api/admin-dashboard";
import { useAdminPlayTypeCatalog } from "@/hooks/use-admin-play-type-catalog";
import { useCachedPlayTypeOptions } from "@/hooks/use-cached-play-type-options";
import { useAsyncEffect } from "@/hooks/use-async-effect";
import { useTranslationRef } from "@/hooks/use-translation-ref";
import {
  DashboardAnalyticsMain,
  DashboardAgentRankingCard,
  DashboardPlayRankingCard,
} from "@/modules/dashboard/dashboard-analytics-panel";
import { DashboardCurrentDrawCard } from "@/modules/dashboard/dashboard-current-draw-card";
import { useDashboardAnalytics } from "@/modules/dashboard/use-dashboard-analytics";
import {
  formatDashboardMoneyMinor,
} from "@/modules/dashboard/use-dashboard-analytics";
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
import { AdminNoResourceState } from "@/components/admin/admin-no-resource-state";
import { Button, buttonVariants } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Skeleton } from "@/components/ui/skeleton";
import { useAdminCurrencyCatalog } from "@/hooks/use-admin-currency-catalog";
import { adminWeekdayKeyForDate, formatAdminCalendarToday } from "@/lib/admin-datetime";
import { normalizeAdminLanguage } from "@/i18n";
import { getAdminRequestLocale } from "@/lib/admin-locale";
import {
  coerceAdminMinor,
  formatAdminMinorUnits,
  getAdminCurrencyDecimalPlaces,
} from "@/lib/money";
import { cn } from "@/lib/utils";
import { LotteryApiBizError } from "@/types/api/errors";
import type {
  AdminDashboardLifetimeFinance,
  AdminDashboardPlatformRisk,
  AdminDashboardResultBatchQueue,
  AdminDashboardTodayFinance,
  AdminDashboardWarning,
} from "@/types/api/admin-dashboard";
import type { AdminDrawFinanceSummaryData } from "@/types/api/admin-draw-finance";
import type { AdminRiskPoolRow } from "@/types/api/admin-risk";
import type { DrawCurrentSnapshot } from "@/types/api/public-draw";

// recharts 图表组件懒加载，避免 ~200KB 进入主 bundle
const DashboardKpiCard = dynamic(
  () => import("@/modules/dashboard/dashboard-visuals").then((m) => ({ default: m.DashboardKpiCard })),
  { ssr: false },
);
const DashboardPanelCard = dynamic(
  () => import("@/modules/dashboard/dashboard-visuals").then((m) => ({ default: m.DashboardPanelCard })),
  { ssr: false },
);
const AbnormalTransferPanelFooter = dynamic(
  () => import("@/modules/dashboard/dashboard-visuals").then((m) => ({ default: m.AbnormalTransferPanelFooter })),
  { ssr: false },
);
const CapUsageBar = dynamic(
  () => import("@/modules/dashboard/dashboard-visuals").then((m) => ({ default: m.CapUsageBar })),
  { ssr: false },
);
const FinanceStructureChart = dynamic(
  () => import("@/modules/dashboard/dashboard-visuals").then((m) => ({ default: m.FinanceStructureChart })),
  { ssr: false },
);
const HotUsageBars = dynamic(
  () => import("@/modules/dashboard/dashboard-visuals").then((m) => ({ default: m.HotUsageBars })),
  { ssr: false },
);
const ResultBatchQueueSummary = dynamic(
  () => import("@/modules/dashboard/dashboard-visuals").then((m) => ({ default: m.ResultBatchQueueSummary })),
  { ssr: false },
);
const PlatformLifetimePayoutSnapshot = dynamic(
  () => import("@/modules/dashboard/dashboard-visuals").then((m) => ({ default: m.PlatformLifetimePayoutSnapshot })),
  { ssr: false },
);
const SettlementStatusChart = dynamic(
  () => import("@/modules/dashboard/dashboard-visuals").then((m) => ({ default: m.SettlementStatusChart })),
  { ssr: false },
);

type HotPlayTab = "4D" | "3D" | "2D" | "special";

function formatMoneyMinor(minor: number, currencyCode: string | null): string {
  const safeMinor = coerceAdminMinor(minor);
  const code = (currencyCode ?? "NPR").toUpperCase();
  const decimals = getAdminCurrencyDecimalPlaces(code);
  const major = safeMinor / 10 ** decimals;
  try {
    return new Intl.NumberFormat(getAdminRequestLocale(), {
      style: "currency",
      currency: code,
      minimumFractionDigits: decimals,
      maximumFractionDigits: decimals,
    }).format(major);
  } catch {
    return formatAdminMinorUnits(safeMinor, code, decimals);
  }
}

function drawScopedHref(
  drawId: number | null,
  suffix = "",
  fallback = "/admin/draws",
): string {
  return drawId != null ? `/admin/draws/${drawId}${suffix}` : fallback;
}

function pendingReviewHref(
  drawId: number | null,
  queue: AdminDashboardResultBatchQueue | null,
): string {
  if (queue != null && queue.pending_review_total > 0 && queue.first_pending_draw_id != null) {
    return `/admin/draws/${queue.first_pending_draw_id}/review`;
  }

  return drawScopedHref(drawId, "/review");
}

function poolPlayCategory(normalizedNumber: string): HotPlayTab | "other" {
  const raw = normalizedNumber.trim();
  const digits = raw.replace(/\D/g, "");
  const digitLen = digits.length;
  const hasLetter = /[A-Za-z]/.test(raw);

  if (hasLetter && digitLen < 3) {
    return "special";
  }
  if (digitLen >= 4) {
    return "4D";
  }
  if (digitLen === 3) {
    return "3D";
  }
  if (digitLen === 2) {
    return "2D";
  }
  if (hasLetter) {
    return "special";
  }
  return "other";
}

function topPoolsForTab(pools: AdminRiskPoolRow[], tab: HotPlayTab): AdminRiskPoolRow[] {
  return [...pools]
    .filter((p) => poolPlayCategory(p.normalized_number) === tab)
    .sort((a, b) => (b.usage_ratio ?? 0) - (a.usage_ratio ?? 0))
    .slice(0, 10);
}

export function DashboardConsole(): ReactElement {
  const { t, i18n } = useTranslation(["dashboard", "common"]);
  useAdminCurrencyCatalog();
  useAdminPlayTypeCatalog();
  const todayLabel = useMemo(() => {
    const locale = normalizeAdminLanguage(i18n.resolvedLanguage ?? i18n.language);
    const weekday = t(`date.weekdays.${adminWeekdayKeyForDate()}`, { ns: "common" });

    return formatAdminCalendarToday(locale, weekday);
  }, [i18n.language, i18n.resolvedLanguage, t]);
  const [loading, setLoading] = useState(true);
  const [refreshing, setRefreshing] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const [hall, setHall] = useState<DrawCurrentSnapshot | null>(null);
  const [drawId, setDrawId] = useState<number | null>(null);
  const [finance, setFinance] = useState<AdminDrawFinanceSummaryData | null>(null);
  const [capabilities, setCapabilities] = useState<{ draw_finance_risk: boolean; wallet_transfer_view: boolean } | null>(null);
  const [resultBatchQueue, setResultBatchQueue] = useState<AdminDashboardResultBatchQueue | null>(
    null,
  );
  const [lifetimeFinance, setLifetimeFinance] = useState<AdminDashboardLifetimeFinance | null>(
    null,
  );
  const [todayFinance, setTodayFinance] = useState<AdminDashboardTodayFinance | null>(null);
  const [apiWarnings, setApiWarnings] = useState<AdminDashboardWarning[]>([]);
  const [platformRisk, setPlatformRisk] = useState<AdminDashboardPlatformRisk | null>(null);
  const [riskLocked, setRiskLocked] = useState(0);
  const [riskCap, setRiskCap] = useState(0);
  const [hotPoolSample, setHotPoolSample] = useState<AdminRiskPoolRow[]>([]);
  const [abnormalTransferTotal, setAbnormalTransferTotal] = useState<number | null>(null);
  const [hotTab, setHotTab] = useState<HotPlayTab>("4D");
  const playOptions = useCachedPlayTypeOptions();
  const tRef = useTranslationRef(["dashboard", "common"]);

  const load = useCallback(async (isRefresh = false) => {
    if (isRefresh) {
      setRefreshing(true);
    } else {
      setLoading(true);
    }
    setError(null);
    setFinance(null);
    setCapabilities(null);
    setResultBatchQueue(null);
    setLifetimeFinance(null);
    setTodayFinance(null);
    setApiWarnings([]);
    setPlatformRisk(null);
    setDrawId(null);
    setRiskLocked(0);
    setRiskCap(0);
    setHotPoolSample([]);
    setAbnormalTransferTotal(null);

    try {
      const d = await getAdminDashboardByScope({});
      setHall(d.hall);

      if (d.resolved_draw != null) {
        setDrawId(d.resolved_draw.id);
      }

      setCapabilities(d.capabilities);
      if (d.finance != null) {
        setFinance(d.finance);
      }
      setResultBatchQueue(d.result_batch_queue);
      setLifetimeFinance(d.lifetime_finance);
      setTodayFinance(d.today_finance);
      setApiWarnings(d.warnings ?? []);
      setPlatformRisk(d.platform_risk);
      if (d.risk != null) {
        setRiskLocked(d.risk.locked_amount);
        setRiskCap(d.risk.cap_amount);
        setHotPoolSample(d.risk.hot_pool_rows);
      }
      setAbnormalTransferTotal(d.abnormal_transfer_total);
    } catch (e) {
      const msg =
        e instanceof LotteryApiBizError ? e.message : tRef.current("warnings.loadFailed");
      setError(msg);
    } finally {
      setLoading(false);
      setRefreshing(false);
    }
  }, [tRef]);

  useAsyncEffect(() => {
    void load(false);
  }, []);

  const currency =
    todayFinance?.currency_code
    ?? lifetimeFinance?.currency_code
    ?? finance?.currency_code
    ?? null;
  const canFinance = capabilities?.draw_finance_risk ?? false;
  const platformLocked = coerceAdminMinor(platformRisk?.locked_amount);
  const platformCap = coerceAdminMinor(platformRisk?.cap_amount);
  const rawPlatformUsagePct = platformRisk?.usage_percent;
  const useCurrentDrawRisk = drawId != null;
  const capUsageLocked = useCurrentDrawRisk ? riskLocked : platformLocked;
  const capUsageCap = useCurrentDrawRisk ? riskCap : platformCap;
  const capUsagePct =
    capUsageCap > 0
      ? (capUsageLocked / capUsageCap) * 100
      : typeof rawPlatformUsagePct === "number" && Number.isFinite(rawPlatformUsagePct)
        ? Math.min(100, Math.max(0, rawPlatformUsagePct))
        : platformCap > 0
          ? (platformLocked / platformCap) * 100
          : 0;
  const showCapUsageCard = useCurrentDrawRisk || platformRisk != null;

  const hotRows = useMemo(() => topPoolsForTab(hotPoolSample, hotTab), [hotPoolSample, hotTab]);

  const pendingReviewTotal = resultBatchQueue?.pending_review_total ?? 0;

  const analytics = useDashboardAnalytics({
    enabled: canFinance,
    playOptions,
    scope: { siteCode: "", agentNodeId: undefined },
  });
  const showAnalytics = canFinance;

  return (
    <div className="flex min-w-0 w-full max-w-none flex-col gap-5">
      <div className="flex flex-wrap items-center justify-between gap-2">
        <div className="min-w-0">
          <h1 className="admin-list-title">{t("title")}</h1>
          <p className="mt-0.5 text-xs text-muted-foreground">{todayLabel}</p>
        </div>
        <Button
          type="button"
          variant="outline"
          size="sm"
          className="h-8"
          disabled={loading || refreshing}
          onClick={() => void load(true)}
        >
          <RefreshCw className={cn("size-3.5", refreshing && "animate-spin")} />
          {t("actions.refresh", { ns: "common" })}
        </Button>
      </div>

      {error ? (
        <Alert className="border-amber-200 bg-amber-50 dark:border-amber-900/60 dark:bg-amber-950/30">
          <AlertTitle>{t("notice")}</AlertTitle>
          <AlertDescription>{error}</AlertDescription>
        </Alert>
      ) : null}

      {!loading && capabilities && !capabilities.draw_finance_risk ? (
        <Alert className="border-amber-200 bg-amber-50 dark:border-amber-900/60 dark:bg-amber-950/30">
          <AlertTitle>{t("notice")}</AlertTitle>
          <AlertDescription>{t("warnings.drawPermission")}</AlertDescription>
        </Alert>
      ) : null}

      {!loading && apiWarnings.length > 0 ? (
        <Alert className="border-amber-200 bg-amber-50 dark:border-amber-900/60 dark:bg-amber-950/30">
          <AlertTitle>{t("notice")}</AlertTitle>
          <AlertDescription>{apiWarnings.map((w) => w.message).join(" ")}</AlertDescription>
        </Alert>
      ) : null}

      <section className="flex min-w-0 flex-col gap-4">
        <DashboardCurrentDrawCard
          key={`${hall?.draw_no ?? "empty"}:${hall?.seconds_to_close ?? 0}:${loading ? "loading" : "ready"}`}
          hall={hall}
          drawId={drawId}
          loading={loading}
        />

        {canFinance && !loading && todayFinance ? (
          <div className="grid min-w-0 grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-3">
            <DashboardKpiCard
              label={t("todayBetTotal")}
              value={formatDashboardMoneyMinor(todayFinance.total_bet_minor, currency)}
              icon={<TrendingUp className="size-4" />}
              hint={t("todayBusinessDateHint", { date: todayFinance.business_date })}
            />
            <DashboardKpiCard
              label={t("todayProfit")}
              signedAmountMinor={todayFinance.approx_house_gross_minor}
              currencyCode={currency}
              icon={<BarChart3 className="size-4" />}
              hint={t("todayPayoutHint", {
                amount: formatDashboardMoneyMinor(todayFinance.total_payout_minor, currency),
              })}
            />
            <DashboardKpiCard
              label={t("lifetimeProfit")}
              signedAmountMinor={lifetimeFinance?.approx_house_gross_minor}
              currencyCode={currency}
              icon={<Wallet className="size-4" />}
              hint={
                lifetimeFinance
                  ? t("lifetimeActivityHint", {
                      draws: lifetimeFinance.draw_count,
                      days: lifetimeFinance.business_day_count,
                    })
                  : undefined
              }
              value={lifetimeFinance ? undefined : "—"}
            />
          </div>
        ) : null}

        <div className="grid min-w-0 grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-4">
        <DashboardPanelCard
          href={pendingReviewHref(drawId, resultBatchQueue)}
          title={t("pendingReviewResults")}
          value={resultBatchQueue != null ? pendingReviewTotal : "—"}
          subtitle={t("resultBatchQueueScope")}
          actionLabel={
            pendingReviewTotal > 0
              ? t("actions.reviewNow", { ns: "common" })
              : t("drawDetails")
          }
          icon={<ClipboardList className="size-5" aria-hidden />}
          accent={pendingReviewTotal > 0 ? "destructive" : "muted"}
          highlight={pendingReviewTotal > 0}
          loading={loading}
        >
          {resultBatchQueue != null ? (
            <ResultBatchQueueSummary queue={resultBatchQueue} compact />
          ) : null}
        </DashboardPanelCard>

        <DashboardPanelCard
          href="/admin/wallet/transfer-orders"
          title={t("abnormalTransferOrders")}
          value={abnormalTransferTotal ?? "—"}
          subtitle={t("abnormalTransferScope")}
          actionLabel={t("actions.viewAll", { ns: "common" })}
          icon={<AlertTriangle className="size-5" aria-hidden />}
          accent={(abnormalTransferTotal ?? 0) > 0 ? "warning" : "muted"}
          loading={loading}
          highlight={(abnormalTransferTotal ?? 0) > 0}
        >
          <AbnormalTransferPanelFooter
            total={abnormalTransferTotal}
            walletPermission={capabilities?.wallet_transfer_view ?? false}
          />
        </DashboardPanelCard>

        <DashboardPanelCard
          href={drawScopedHref(drawId, "/risk/pools")}
          title={t("riskCapUsage")}
          value={`${capUsagePct.toFixed(1)}%`}
          actionLabel={t("occupancyDetails")}
          icon={<Shield className="size-5" aria-hidden />}
          accent={
            capUsagePct >= 90
              ? "destructive"
              : capUsagePct >= 70
                ? "primary"
                : "muted"
          }
          loading={loading}
        >
          {showCapUsageCard ? (
            <CapUsageBar
              locked={capUsageLocked}
              cap={capUsageCap}
              usagePct={capUsagePct}
              formatMoney={formatMoneyMinor}
              currency={currency}
              compact
            />
          ) : null}
        </DashboardPanelCard>

        <DashboardPanelCard
          href="/admin/reports"
          title={t("lifetimePayout")}
          value={
            lifetimeFinance
              ? formatMoneyMinor(lifetimeFinance.total_payout_minor, currency)
              : "—"
          }
          subtitle={
            lifetimeFinance
              ? t("platformOrderAndTicket", {
                  orders: lifetimeFinance.order_count,
                  tickets: lifetimeFinance.ticket_item_count,
                })
              : t("states.noResource", { ns: "common" })
          }
          actionLabel={t("actions.viewAll", { ns: "common" })}
          icon={<Wallet className="size-5" aria-hidden />}
          accent="primary"
          loading={loading}
        >
          {lifetimeFinance ? (
            <PlatformLifetimePayoutSnapshot
              finance={lifetimeFinance}
              formatMoney={formatMoneyMinor}
            />
          ) : null}
        </DashboardPanelCard>
        </div>
      </section>

      <section
        className={cn(
          "grid min-w-0 grid-cols-1 gap-4",
          showAnalytics ? "xl:grid-cols-12" : "xl:grid-cols-1",
        )}
      >
        <div
          className={cn(
            "flex min-w-0 flex-col gap-4",
            showAnalytics ? "xl:col-span-8" : "xl:col-span-12",
          )}
        >
          {showAnalytics ? <DashboardAnalyticsMain analytics={analytics} /> : null}

          <div className="grid min-w-0 grid-cols-1 gap-4 md:grid-cols-2">
            <Card className="admin-list-card py-0">
              <CardHeader className="flex flex-row items-center justify-between space-y-0 border-b border-border/60 px-4 py-3">
                <CardTitle className="text-sm font-semibold">{t("settlementOverview")}</CardTitle>
                {drawId != null ? (
                  <Link
                    href="/admin/settlement-batches"
                    className={cn(buttonVariants({ variant: "outline", size: "sm" }), "h-7 px-2 text-xs")}
                  >
                    {t("actions.viewAll", { ns: "common" })}
                  </Link>
                ) : null}
              </CardHeader>
              <CardContent className="px-4 py-4">
                {loading ? (
                  <Skeleton className="h-40 w-full" />
                ) : finance ? (
                  <SettlementStatusChart finance={finance} />
                ) : (
                  <AdminNoResourceState className="py-10 text-center text-xs text-muted-foreground" />
                )}
              </CardContent>
            </Card>

            <Card className="admin-list-card py-0">
              <CardHeader className="flex flex-row flex-wrap items-center justify-between gap-2 space-y-0 border-b border-border/60 px-4 py-3">
                <CardTitle className="text-sm font-semibold">{t("hotNumbersTop10")}</CardTitle>
                <div className="flex flex-wrap items-center gap-1">
                  <div role="tablist" aria-label={t("playDimension")} className="flex gap-0.5">
                    {([
                      { value: "4D", label: t("tabs.4d") },
                      { value: "3D", label: t("tabs.3d") },
                      { value: "2D", label: t("tabs.2d") },
                      { value: "special", label: t("tabs.special") },
                    ] as const).map((tab) => (
                      <button
                        key={tab.value}
                        type="button"
                        role="tab"
                        aria-selected={hotTab === tab.value}
                        className={cn(
                          "rounded px-2 py-0.5 text-[11px] font-medium transition-colors",
                          hotTab === tab.value
                            ? "bg-primary text-primary-foreground"
                            : "text-muted-foreground hover:bg-muted",
                        )}
                        onClick={() => setHotTab(tab.value)}
                      >
                        {tab.label}
                      </button>
                    ))}
                  </div>
                </div>
              </CardHeader>
              <CardContent className="px-4 py-4">
                {loading ? (
                  <Skeleton className="h-48 w-full" />
                ) : (
                  <HotUsageBars rows={hotRows} compact />
                )}
              </CardContent>
            </Card>
          </div>

          {showAnalytics ? (
            <Card className="admin-list-card min-w-0 py-0">
              <CardHeader className="border-b border-border/60 px-4 py-3 pb-0">
                <CardTitle className="text-sm font-semibold">{t("financeStructure")}</CardTitle>
              </CardHeader>
              <CardContent className="px-4 py-4">
                {loading ? (
                  <Skeleton className="h-52 w-full" />
                ) : finance ? (
                  <FinanceStructureChart finance={finance} formatMoney={formatMoneyMinor} />
                ) : (
                  <AdminNoResourceState className="py-10 text-center text-xs text-muted-foreground" />
                )}
              </CardContent>
            </Card>
          ) : null}

          {!showAnalytics ? (
            <Card className="admin-list-card min-w-0 py-0">
              <CardHeader className="border-b border-border/60 px-4 py-3 pb-0">
                <CardTitle className="text-sm font-semibold">{t("financeStructure")}</CardTitle>
              </CardHeader>
              <CardContent className="px-4 py-4">
                {loading ? (
                  <Skeleton className="h-52 w-full" />
                ) : finance ? (
                  <FinanceStructureChart finance={finance} formatMoney={formatMoneyMinor} />
                ) : (
                  <AdminNoResourceState className="py-10 text-center text-xs text-muted-foreground" />
                )}
              </CardContent>
            </Card>
          ) : null}
        </div>

        {showAnalytics ? (
          <aside className="flex min-w-0 flex-col gap-4 xl:col-span-4">
            <DashboardPlayRankingCard analytics={analytics} />
            <DashboardAgentRankingCard analytics={analytics} />
          </aside>
        ) : null}
      </section>
    </div>
  );
}
