"use client";

import { useCallback, useEffect, useState } from "react";
import { useTranslation } from "react-i18next";

import { getPlayEffective } from "@/api/play";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@/components/ui/card";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import { useActivePlayerCurrency } from "@/hooks/use-active-player-currency";
import { getLotteryRequestLocale } from "@/lib/lottery-locale";
import { PLAY_CATALOG_REFRESH_EVENT } from "@/lib/play-catalog-events";
import { PLAYER_CURRENCY_CHANGE_EVENT } from "@/lib/player-currency-preference";
import { cn } from "@/lib/utils";
import { LotteryApiBizError } from "@/types/api/errors";
import type {
  PlayEffectivePayload,
  PlayEffectivePlayRow,
} from "@/types/api/play-effective";

const DEFAULT_POLL_MS = 120_000;

function pickDisplayName(row: PlayEffectivePlayRow): string {
  return row.display_name?.trim() || row.play_code;
}

function pickRuleText(row: PlayEffectivePlayRow): string | null {
  const c = row.config;
  if (!c) {
    return null;
  }
  const loc = getLotteryRequestLocale();
  if (loc === "zh") {
    return c.rule_text_zh ?? c.rule_text_en;
  }
  if (loc === "ne") {
    return c.rule_text_ne ?? c.rule_text_en;
  }
  return c.rule_text_en ?? c.rule_text_zh;
}

/** 主数据开关 + 配置版本内开关，同时有 config 行才算对客开放 */
function isPlayOpenForPlayer(row: PlayEffectivePlayRow): boolean {
  if (!row.master_enabled || row.config === null) {
    return false;
  }
  return row.config.is_enabled;
}

type LoadState =
  | { kind: "loading" }
  | { kind: "ok"; data: PlayEffectivePayload }
  | { kind: "error"; message: string; notReady?: boolean };

function formatMoneyAmount(n: number): string {
  return new Intl.NumberFormat(undefined, { maximumFractionDigits: 0 }).format(
    n,
  );
}

export function HallPlayCatalogPanel() {
  const { t } = useTranslation("player");
  const { activeCurrency: currencyParam } = useActivePlayerCurrency();
  const [state, setState] = useState<LoadState>({ kind: "loading" });

  const load = useCallback(async () => {
    setState((s) => (s.kind === "ok" ? s : { kind: "loading" }));
    try {
      const data = await getPlayEffective({ currency: currencyParam });
      setState({ kind: "ok", data });
    } catch (e) {
      if (e instanceof LotteryApiBizError && e.code === 9004) {
        setState({
          kind: "error",
          message: t("hall.playCatalog.notReady"),
          notReady: true,
        });
        return;
      }
      const msg =
        e instanceof LotteryApiBizError
          ? e.message
          : t("hall.playCatalog.loadFailed");
      setState({ kind: "error", message: msg });
    }
  }, [currencyParam, t]);

  useEffect(() => {
    queueMicrotask(() => {
      void load();
    });
  }, [load]);

  useEffect(() => {
    const id = window.setInterval(() => {
      void load();
    }, DEFAULT_POLL_MS);
    return () => window.clearInterval(id);
  }, [load]);

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

  useEffect(() => {
    const onCatalogRefresh = () => void load();
    window.addEventListener(PLAY_CATALOG_REFRESH_EVENT, onCatalogRefresh);
    return () => window.removeEventListener(PLAY_CATALOG_REFRESH_EVENT, onCatalogRefresh);
  }, [load]);

  const body = (() => {
    if (state.kind === "loading") {
      return (
        <p className="text-sm text-muted-foreground">{t("hall.playCatalog.loading")}</p>
      );
    }
    if (state.kind === "error") {
      return (
        <div className="space-y-2">
          <p className="text-sm text-destructive">{state.message}</p>
          <Button type="button" size="sm" variant="secondary" onClick={() => void load()}>
            {t("actions.retry")}
          </Button>
        </div>
      );
    }

    const { data } = state;
    const ordered = [...data.plays].sort(
      (a, b) => a.sort_order - b.sort_order || a.play_code.localeCompare(b.play_code),
    );

    return (
      <div className="space-y-3">
        <p className="text-xs text-muted-foreground">
          {t("hall.playCatalog.meta", {
            currency: data.currency_code,
            playVersion: data.effective_versions.play_config.version_no,
            oddsVersion: data.effective_versions.odds.version_no,
          })}
        </p>

        <div className="overflow-x-auto rounded-md border">
          <Table>
            <TableHeader>
              <TableRow>
                <TableHead className="min-w-[140px]">{t("hall.playCatalog.play")}</TableHead>
                <TableHead className="w-[88px] text-center">
                  {t("hall.playCatalog.status")}
                </TableHead>
                <TableHead className="min-w-[160px] whitespace-nowrap">
                  {t("hall.playCatalog.limit")}
                </TableHead>
                <TableHead className="min-w-[100px]">{t("hall.playCatalog.odds")}</TableHead>
                <TableHead className="min-w-[200px]">
                  {t("hall.playCatalog.description")}
                </TableHead>
              </TableRow>
            </TableHeader>
            <TableBody>
              {ordered.map((row) => {
                const open = isPlayOpenForPlayer(row);
                const rule = pickRuleText(row);
                const oddsMul =
                  row.odds === null
                    ? "—"
                    : typeof row.odds.odds_multiplier === "number"
                      ? row.odds.odds_multiplier.toFixed(4)
                      : (row.odds.odds_value / 10000).toFixed(4);

                return (
                  <TableRow
                    key={row.play_code}
                    className={cn(!open && "opacity-60")}
                  >
                    <TableCell>
                      <div className="flex flex-col gap-0.5">
                        <span className="font-medium">{pickDisplayName(row)}</span>
                        <span className="font-mono text-xs text-muted-foreground">
                          {row.play_code}
                          {row.dimension != null ? ` · ${row.dimension}D` : ""}
                        </span>
                      </div>
                    </TableCell>
                    <TableCell className="text-center">
                      {open ? (
                        <Badge variant="default" className="font-normal">
                          {t("hall.playCatalog.open")}
                        </Badge>
                      ) : (
                        <Badge variant="secondary" className="font-normal">
                          {t("hall.playCatalog.closed")}
                        </Badge>
                      )}
                    </TableCell>
                    <TableCell className="font-mono text-sm tabular-nums">
                      {row.config ? (
                        <>
                          {formatMoneyAmount(row.config.min_bet_amount)}
                          {" — "}
                          {formatMoneyAmount(row.config.max_bet_amount)}
                        </>
                      ) : (
                        "—"
                      )}
                    </TableCell>
                    <TableCell className="font-mono text-sm tabular-nums">
                      {row.odds ? oddsMul : "—"}
                    </TableCell>
                    <TableCell className="text-muted-foreground text-sm leading-snug">
                      {rule ?? "—"}
                    </TableCell>
                  </TableRow>
                );
              })}
            </TableBody>
          </Table>
        </div>

        {data.risk_cap_items.length > 0 ? (
          <div className="space-y-2">
            <h3 className="text-sm font-medium text-foreground">
              {t("hall.playCatalog.riskTitle")}
            </h3>
            <div className="overflow-x-auto rounded-md border">
              <Table>
                <TableHeader>
                  <TableRow>
                    <TableHead>{t("hall.playCatalog.number")}</TableHead>
                    <TableHead>{t("hall.playCatalog.capAmount")}</TableHead>
                    <TableHead>{t("hall.playCatalog.type")}</TableHead>
                  </TableRow>
                </TableHeader>
                <TableBody>
                  {data.risk_cap_items.map((r, i) => (
                    <TableRow key={`${r.normalized_number}-${i}`}>
                      <TableCell className="font-mono">{r.normalized_number}</TableCell>
                      <TableCell className="font-mono tabular-nums text-sm">
                        {formatMoneyAmount(r.cap_amount)}
                      </TableCell>
                      <TableCell className="text-sm text-muted-foreground">
                        {r.cap_type}
                      </TableCell>
                    </TableRow>
                  ))}
                </TableBody>
              </Table>
            </div>
          </div>
        ) : null}
      </div>
    );
  })();

  return (
    <Card>
      <CardHeader className="flex flex-col gap-2">
        <div className="space-y-1">
          <CardTitle className="text-base">{t("hall.playCatalog.title")}</CardTitle>
          <CardDescription>
            {t("hall.playCatalog.descriptionText", {
              seconds: DEFAULT_POLL_MS / 1000,
            })}
          </CardDescription>
        </div>
        <Button
          type="button"
          variant="outline"
          size="sm"
          className="shrink-0"
          onClick={() => void load()}
        >
          {t("hall.playCatalog.refresh")}
        </Button>
      </CardHeader>
      <CardContent>{body}</CardContent>
    </Card>
  );
}
