"use client";

import Link from "next/link";
import { useCallback, useEffect, useMemo, useState, type ReactElement, type ReactNode } from "react";
import { format, subDays } from "date-fns";
import { useTranslation } from "react-i18next";
import { BarChart3, Gift, TrendingUp, Wallet } from "lucide-react";

import { getAdminDashboardAnalytics } from "@/api/admin-dashboard";
import { AdminDateRangeField } from "@/components/admin/admin-date-range-field";
import { Alert, AlertDescription } from "@/components/ui/alert";
import { buttonVariants } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Label } from "@/components/ui/label";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { Skeleton } from "@/components/ui/skeleton";
import { useAdminPlayCodeLabel } from "@/hooks/use-admin-play-type-catalog";
import { formatAdminMinorUnits, getAdminCurrencyDecimalPlaces } from "@/lib/money";
import { cn } from "@/lib/utils";
import { StatCard } from "@/modules/dashboard/dashboard-visuals";
import {
  DailyTrendChart,
  PeriodCompareStrip,
  PlayBreakdownChart,
} from "@/modules/dashboard/dashboard-trend-charts";
import { LotteryApiBizError } from "@/types/api/errors";
import type {
  AdminDashboardAnalyticsData,
  DashboardAnalyticsMetric,
  DashboardAnalyticsPeriod,
} from "@/types/api/admin-dashboard-analytics";

const PERIOD_OPTIONS: DashboardAnalyticsPeriod[] = [
  "today",
  "last_7_days",
  "last_30_days",
  "this_month",
  "lifetime",
  "custom",
];

const METRIC_OPTIONS: DashboardAnalyticsMetric[] = ["overview", "bet", "payout", "profit"];

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

function formatSignedMoneyMinor(minor: number, currencyCode: string | null): string {
  if (minor === 0) {
    return formatMoneyMinor(0, currencyCode);
  }
  const s = minor > 0 ? "+" : "−";
  return `${s}${formatMoneyMinor(Math.abs(minor), currencyCode)}`;
}

export function DashboardAnalyticsPanel({
  enabled,
  playOptions,
}: {
  enabled: boolean;
  playOptions: { code: string; label: string }[];
}): ReactNode {
  const { t } = useTranslation(["dashboard", "common"]);
  const playLabel = useAdminPlayCodeLabel();

  const [period, setPeriod] = useState<DashboardAnalyticsPeriod>("last_7_days");
  const [metric, setMetric] = useState<DashboardAnalyticsMetric>("overview");
  const [playCode, setPlayCode] = useState<string>("");
  const [customFrom, setCustomFrom] = useState(() => format(subDays(new Date(), 6), "yyyy-MM-dd"));
  const [customTo, setCustomTo] = useState(() => format(new Date(), "yyyy-MM-dd"));

  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [data, setData] = useState<AdminDashboardAnalyticsData | null>(null);

  const load = useCallback(async () => {
    if (!enabled) {
      setLoading(false);
      setData(null);
      return;
    }

    setLoading(true);
    setError(null);

    try {
      const payload = await getAdminDashboardAnalytics({
        period,
        metric,
        play_code: playCode !== "" ? playCode : undefined,
        ...(period === "custom"
          ? { date_from: customFrom, date_to: customTo }
          : {}),
      });
      setData(payload);
    } catch (e) {
      setData(null);
      const raw = e instanceof LotteryApiBizError ? e.message : "";
      const needsAuthSync =
        raw.includes("admin.dashboard.analytics") || raw.includes("资源未配置");
      setError(
        needsAuthSync ? t("warnings.apiResourceMissing") : raw || t("warnings.loadFailed"),
      );
    } finally {
      setLoading(false);
    }
  }, [enabled, period, metric, playCode, customFrom, customTo, t]);

  useEffect(() => {
    const timer = window.setTimeout(() => {
      void load();
    }, 0);
    return () => window.clearTimeout(timer);
  }, [load]);

  const currency = data?.currency_code ?? null;
  const summary = data?.summary;

  const periodRangeLabel = useMemo(() => {
    if (!data) {
      return null;
    }
    return data.date_from === data.date_to
      ? data.date_from
      : `${data.date_from} — ${data.date_to}`;
  }, [data]);

  const metricLabel = useMemo(
    () => t(`analytics.metrics.${metric}`),
    [metric, t],
  );

  const playFilterLabel = useMemo(() => {
    if (playCode === "") {
      return t("analytics.allPlays");
    }
    return playOptions.find((p) => p.code === playCode)?.label ?? playCode;
  }, [playCode, playOptions, t]);

  const resolvePlayLabel = useCallback(
    (code: string, dimension: number) => {
      const base = playLabel(code);
      return dimension > 0 ? `${base} · ${dimension}D` : base;
    },
    [playLabel],
  );

  if (!enabled) {
    return null;
  }

  return (
    <section className="space-y-4">
      <Card className="border-border/80 shadow-sm">
        <CardHeader className="space-y-4 pb-2">
          <div className="flex flex-wrap items-center justify-between gap-2">
            <CardTitle className="text-base">{t("analytics.title")}</CardTitle>
            <Link
              href="/admin/reports"
              className={cn(buttonVariants({ variant: "ghost", size: "sm" }), "h-8 gap-1.5 text-xs")}
            >
              <BarChart3 className="size-3.5" aria-hidden />
              {t("viewReports")}
            </Link>
          </div>

          <div className="flex flex-wrap gap-1.5" role="group" aria-label={t("analytics.periodLabel")}>
            {PERIOD_OPTIONS.map((p) => (
              <button
                key={p}
                type="button"
                className={cn(
                  "rounded-md border px-2.5 py-1 text-xs font-medium transition-colors",
                  period === p
                    ? "border-primary bg-primary text-primary-foreground"
                    : "border-border bg-card text-muted-foreground hover:bg-muted",
                )}
                onClick={() => setPeriod(p)}
              >
                {t(`analytics.periods.${p}`)}
              </button>
            ))}
          </div>

          <div className="grid gap-4 lg:grid-cols-[1fr_auto_auto] lg:items-end">
            {period === "custom" ? (
              <AdminDateRangeField
                id="dashboard-analytics-range"
                label={t("analytics.customRange")}
                from={customFrom}
                to={customTo}
                onRangeChange={({ from, to }) => {
                  setCustomFrom(from);
                  setCustomTo(to);
                }}
              />
            ) : (
              <p className="text-sm text-muted-foreground lg:col-span-1">
                {periodRangeLabel
                  ? t("analytics.rangeHint", { range: periodRangeLabel })
                  : t("analytics.selectPeriod")}
              </p>
            )}

            <div className="space-y-1.5">
              <Label className="text-xs text-muted-foreground">{t("analytics.metricLabel")}</Label>
              <Select value={metric} onValueChange={(v) => setMetric(v as DashboardAnalyticsMetric)}>
                <SelectTrigger className="w-full min-w-[140px]">
                  <SelectValue>{metricLabel}</SelectValue>
                </SelectTrigger>
                <SelectContent>
                  {METRIC_OPTIONS.map((m) => (
                    <SelectItem key={m} value={m}>
                      {t(`analytics.metrics.${m}`)}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>

            <div className="space-y-1.5">
              <Label className="text-xs text-muted-foreground">{t("analytics.playLabel")}</Label>
              <Select
                value={playCode === "" ? "__all__" : playCode}
                onValueChange={(v) => setPlayCode(!v || v === "__all__" ? "" : v)}
              >
                <SelectTrigger className="w-full min-w-[160px]">
                  <SelectValue>{playFilterLabel}</SelectValue>
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value="__all__">{t("analytics.allPlays")}</SelectItem>
                  {playOptions.map((p) => (
                    <SelectItem key={p.code} value={p.code}>
                      {p.label}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
          </div>
        </CardHeader>

        <CardContent className="space-y-6">
          {error ? (
            <Alert className="border-amber-200 bg-amber-50 dark:border-amber-900/60 dark:bg-amber-950/30">
              <AlertDescription>{error}</AlertDescription>
            </Alert>
          ) : null}

          {data?.chart_meta.truncated ? (
            <p className="text-xs text-amber-700 dark:text-amber-400">
              {t("analytics.chartTruncated", {
                from: data.chart_meta.chart_date_from,
                to: data.chart_meta.chart_date_to,
                days: data.chart_meta.span_days,
              })}
            </p>
          ) : null}

          {loading ? (
            <div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
              {Array.from({ length: 3 }).map((_, i) => (
                <Skeleton key={i} className="h-24 w-full rounded-xl" />
              ))}
            </div>
          ) : summary ? (
            <div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
              <StatCard
                label={t("analytics.summaryBet")}
                value={formatMoneyMinor(summary.total_bet_minor, currency)}
                hint={t("lifetimeActivityHint", {
                  draws: summary.draw_count.toLocaleString("zh-CN"),
                  days: summary.business_day_count.toLocaleString("zh-CN"),
                })}
                icon={<Wallet className="size-5" aria-hidden />}
              />
              <StatCard
                label={t("analytics.summaryPayout")}
                value={formatMoneyMinor(summary.total_payout_minor, currency)}
                hint={
                  summary.total_bet_minor > 0
                    ? t("payoutRateOfBet", {
                        rate: ((summary.total_payout_minor / summary.total_bet_minor) * 100).toFixed(1),
                      })
                    : undefined
                }
                icon={<Gift className="size-5" aria-hidden />}
                accent="destructive"
              />
              <StatCard
                label={t("analytics.summaryProfit")}
                value={formatSignedMoneyMinor(summary.approx_house_gross_minor, currency)}
                hint={
                  summary.total_bet_minor > 0
                    ? t("marginRate", {
                        rate: ((summary.approx_house_gross_minor / summary.total_bet_minor) * 100).toFixed(1),
                      })
                    : undefined
                }
                icon={<TrendingUp className="size-5" aria-hidden />}
              />
            </div>
          ) : null}
        </CardContent>
      </Card>

      <div className="grid gap-4 lg:grid-cols-2 lg:items-start">
        <Card className="flex h-full flex-col border-border/80 shadow-sm">
          <CardHeader className="pb-2">
            <CardTitle className="text-base">{t("analytics.dailyTrend")}</CardTitle>
          </CardHeader>
          <CardContent className="pb-4">
            {loading ? (
              <Skeleton className="h-[220px] w-full" />
            ) : data ? (
              <DailyTrendChart
                series={data.daily_series}
                metric={metric}
                formatMoney={formatMoneyMinor}
                currency={currency}
              />
            ) : (
              <p className="py-8 text-center text-sm text-muted-foreground">{t("states.noData", { ns: "common" })}</p>
            )}
          </CardContent>
        </Card>

        <Card className="flex h-full flex-col border-border/80 shadow-sm">
          <CardHeader className="pb-2">
            <CardTitle className="text-base">{t("analytics.playBreakdown")}</CardTitle>
          </CardHeader>
          <CardContent className="pb-4">
            {loading ? (
              <Skeleton className="h-[220px] w-full" />
            ) : data ? (
              <div className="max-h-[280px] overflow-y-auto pr-1">
                <PlayBreakdownChart
                  rows={data.play_breakdown}
                  metric={metric}
                  formatMoney={formatMoneyMinor}
                  currency={currency}
                  playLabel={resolvePlayLabel}
                />
              </div>
            ) : (
              <p className="py-8 text-center text-sm text-muted-foreground">{t("states.noData", { ns: "common" })}</p>
            )}
          </CardContent>
        </Card>
      </div>

      {data && !loading ? (
        <Card className="border-border/80 shadow-sm">
          <CardHeader className="pb-2">
            <CardTitle className="text-base">{t("analytics.periodDistribution")}</CardTitle>
          </CardHeader>
          <CardContent>
            <PeriodCompareStrip
              series={data.daily_series}
              formatMoney={formatMoneyMinor}
              currency={currency}
            />
          </CardContent>
        </Card>
      ) : null}
    </section>
  );
}
