"use client";

import Link from "next/link";
import { useCallback, useEffect, useState } from "react";
import { ChevronRight } from "lucide-react";
import { useTranslation } from "react-i18next";

import { getTicketItemDetail, getTicketItems } from "@/api/ticket-items";
import { Button } from "@/components/ui/button";
import { PlayerPanel } from "@/components/layout/player-panel";
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@/components/ui/card";
import { Skeleton } from "@/components/ui/skeleton";
import { TwentyThreeResultsGrid } from "@/features/results/twenty-three-results-grid";
import { useCurrencyCatalog } from "@/hooks/use-currency-catalog";
import { ticketDetailHref } from "@/features/orders/group-ticket-items";
import { StatusDot, ticketStatusDisplay } from "@/features/orders/ticket-item-status";
import { formatPlayerInstant } from "@/lib/player-datetime";
import { formatMinorAsCurrency } from "@/lib/money";
import { isCreditFundingPlayer } from "@/lib/player-funding-mode";
import { norm4d } from "@/lib/norm-4d";
import { useActivePlayerCurrency } from "@/hooks/use-active-player-currency";
import { usePlayerSessionStore } from "@/stores/player-session-store";
import { playLabel } from "@/lib/play-labels";
import { cn } from "@/lib/utils";
import type { TicketItemDetailPayload, TicketItemListRow } from "@/types/api/ticket-items";

type OddsSnapRow = { prize_scope?: string; odds_value?: number };

function formatOddsSnapshot(
  json: unknown,
  t: (key: string, options?: { defaultValue?: string }) => string,
): string {
  if (!Array.isArray(json)) return "—";
  const parts = (json as OddsSnapRow[])
    .filter((r) => r.prize_scope && r.odds_value != null)
    .map((r) => {
      const scope = String(r.prize_scope);
      const label = t(`prizeTier.${scope}`, { defaultValue: scope });
      const mult = Number(r.odds_value) / 10_000;
      return `${label} ${mult}x`;
    });
  return parts.length ? parts.join(" · ") : "—";
}

type TimelineRow = {
  code: string;
  label: string;
  time: string;
};

const TRANSIENT_TICKET_STATUSES = new Set([
  "pending_confirm",
  "partial_pending_confirm",
  "pending_draw",
  "pending_payout",
]);

type TicketItemDetailWithExtras = TicketItemDetailPayload & {
  timeline?: TimelineRow[];
  match_result?: {
    matched?: boolean;
    matched_prize_tier?: string | null;
    win_amount_minor?: number;
    jackpot_allocation_minor?: number;
    lines?: Array<{
      number_4d?: string | null;
      matched_tier?: string | null;
      payout?: number | null;
    }>;
  };
};

/** 界面文档 §4.8 注单详情 */
export function TicketOrderDetailScreen({ ticketNo }: { ticketNo: string }) {
  const { t } = useTranslation("player");
  const { activeCurrency } = useActivePlayerCurrency();
  const creditMode = isCreditFundingPlayer(usePlayerSessionStore((state) => state.profile));
  useCurrencyCatalog();
  const [data, setData] = useState<TicketItemDetailPayload | null>(null);
  const [siblingItems, setSiblingItems] = useState<TicketItemListRow[]>([]);
  const [error, setError] = useState<string | null>(null);
  const [loading, setLoading] = useState(true);
  const backHref = "/orders";
  const backLabel = t("orders.title");

  const load = useCallback(async (options?: { silent?: boolean }) => {
    if (!options?.silent) {
      setLoading(true);
    }
    setError(null);
    try {
      const row = await getTicketItemDetail(ticketNo);
      setData(row);
    } catch {
      setData(null);
      if (!options?.silent) {
        setError(t("orders.notFound"));
      }
    } finally {
      if (!options?.silent) {
        setLoading(false);
      }
    }
  }, [ticketNo, t]);

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

  useEffect(() => {
    const orderNo = (data?.order_no ?? "").trim();
    if (!orderNo) {
      setSiblingItems([]);
      return;
    }

    let cancelled = false;
    void (async () => {
      try {
        const res = await getTicketItems({ order_no: orderNo, per_page: 50 });
        if (cancelled) return;
        setSiblingItems(
          res.items.filter((row) => row.ticket_no !== ticketNo),
        );
      } catch {
        if (!cancelled) {
          setSiblingItems([]);
        }
      }
    })();

    return () => {
      cancelled = true;
    };
  }, [data?.order_no, ticketNo]);

  useEffect(() => {
    if (!data || !TRANSIENT_TICKET_STATUSES.has(data.status)) {
      return;
    }
    const refresh = () => void load({ silent: true });
    const intervalId = window.setInterval(refresh, 12_000);
    window.addEventListener("lottery-hall-refresh", refresh);
    window.addEventListener("lottery-wallet-refresh", refresh);
    return () => {
      window.clearInterval(intervalId);
      window.removeEventListener("lottery-hall-refresh", refresh);
      window.removeEventListener("lottery-wallet-refresh", refresh);
    };
  }, [data, load]);

  if (loading) {
    return (
      <PlayerPanel
        title={t("orders.betDetail")}
        backHref={backHref}
        backLabel={backLabel}
      >
        <div className="space-y-3">
          <Skeleton className="h-12 rounded-xl" />
          <Skeleton className="h-56 rounded-xl" />
        </div>
      </PlayerPanel>
    );
  }

  if (error || !data) {
    return (
      <PlayerPanel
        title={t("orders.betDetail")}
        backHref={backHref}
        backLabel={backLabel}
      >
        <div className="rounded-xl border border-red-200 bg-red-50 px-3 py-3 text-sm text-red-700">
          <p>{error ?? t("orders.noData")}</p>
          <Button
            type="button"
            size="sm"
            className="mt-3 bg-[#e5002c] text-white hover:bg-[#d10028]"
            onClick={() => void load()}
          >
            {t("actions.retry")}
          </Button>
        </div>
      </PlayerPanel>
    );
  }

  const cur = data.currency_code ?? activeCurrency;
  const st = ticketStatusDisplay(data.status, data.win_amount, data.jackpot_win_amount, t, creditMode);
  const orderStatus = data.order_status ?? null;
  const isPartialFailedOrder = orderStatus === "partial_failed";
  const isLineFailed = data.status === "failed" || data.status === "refunded";
  const failReason =
    (data.fail_reason_text ?? "").trim() ||
    (data.fail_reason_code ? t(`orders.failReason.${data.fail_reason_code}`, { defaultValue: data.fail_reason_code }) : "");
  const totalWin = data.win_amount + data.jackpot_win_amount;
  const pub = data.published_draw_results;
  const first = pub?.results?.["1st"] ?? "";
  const comboHits =
    first && data.combinations.length
      ? data.combinations.filter((c) => norm4d(c.number_4d) === norm4d(first))
      : [];

  const highlight =
    pub?.results && data.combinations.length
      ? new Set(
          data.combinations
            .map((c) => norm4d(c.number_4d))
            .filter((n) => {
              const nums = [
                pub.results["1st"],
                pub.results["2nd"],
                pub.results["3rd"],
                ...(pub.results.starter ?? []),
                ...(pub.results.consolation ?? []),
              ]
                .filter(Boolean)
                .map((x) => norm4d(String(x)));
              return nums.includes(n);
            }),
        )
      : null;

  const tierLabel = data.settlement?.matched_prize_tier
    ? t(`prizeTier.${data.settlement.matched_prize_tier}`, {
        defaultValue: data.settlement.matched_prize_tier,
      })
    : null;
  const extras = data as TicketItemDetailWithExtras;
  const timeline = extras.timeline ?? [];
  const matchResult = extras.match_result;
  const hasSettlement = data.settlement !== null || data.status === "settled_win" || data.status === "settled_lose";

  return (
    <PlayerPanel
      title={t("orders.betDetail")}
      backHref={backHref}
      backLabel={backLabel}
    >
      <div className="flex flex-col gap-3">
        {siblingItems.length > 0 ? (
          <div className="rounded-xl border border-[#e5edf8] bg-white p-3 shadow-[0_8px_24px_rgba(15,23,42,0.05)]">
            <p className="text-sm font-black text-[#0b3f96]">{t("orders.sameOrderItems")}</p>
            <div className="mt-2 space-y-2">
              {siblingItems.map((row) => {
                const lineSt = ticketStatusDisplay(
                  row.status,
                  row.win_amount,
                  row.jackpot_win_amount,
                  t,
                  creditMode,
                );
                const lineCur = row.currency_code ?? activeCurrency;
                return (
                  <Link
                    key={row.ticket_no}
                    href={ticketDetailHref(row.ticket_no)}
                    className="flex items-center gap-3 rounded-xl border border-[#e5edf8] bg-[#fbfdff] px-3 py-2.5 transition-colors hover:border-[#b9ccf6] hover:bg-white"
                  >
                    <div className="min-w-0 flex-1">
                      <p className="text-sm font-black text-[#0b3f96]">
                        {playLabel(row.play_code, t)} · {row.original_number ?? row.play_code}
                      </p>
                      <p className="mt-0.5 text-xs text-slate-500">
                        {t("orders.deduction")}{" "}
                        <span className="font-bold tabular-nums text-[#0b3f96]">
                          {formatMinorAsCurrency(row.actual_deduct_amount, lineCur)}
                        </span>
                      </p>
                    </div>
                    <div className="flex shrink-0 items-center gap-2">
                      <StatusDot
                        label={lineSt.label}
                        dotClass={lineSt.dotClass}
                        ring={lineSt.ring}
                      />
                      <ChevronRight className="size-4 text-[#7890b8]" aria-hidden />
                    </div>
                  </Link>
                );
              })}
            </div>
          </div>
        ) : null}

        <Card className="ring-0 border border-[#e8eef7] bg-white shadow-[0_8px_28px_rgba(15,23,42,0.05)]">
          <CardHeader className="space-y-2 border-b border-[#edf2f9] pb-3">
            <div className="flex flex-wrap items-center justify-between gap-2">
              <CardTitle className="text-base font-black text-[#0b3f96]">
                {t("orders.detailTitle")}
              </CardTitle>
              <StatusDot label={st.label} dotClass={st.dotClass} ring={st.ring} />
            </div>
            <CardDescription className="font-mono text-[11px] leading-relaxed text-slate-500">
              {t("orders.ticketNo", { ticketNo: data.ticket_no })} ·{" "}
              {t("orders.orderNo", { orderNo: data.order_no ?? "—" })}
            </CardDescription>
          </CardHeader>
          <CardContent className="space-y-3 text-sm">
            {isPartialFailedOrder ? (
              <div className="rounded-lg border border-amber-200 bg-amber-50 px-3 py-2 text-xs text-amber-900">
                <p className="font-bold">{t("orders.partialFailedOrderTitle")}</p>
                <p className="mt-1 leading-relaxed text-amber-800/90">
                  {t("orders.partialFailedOrderBody")}
                </p>
              </div>
            ) : null}
            {isLineFailed && failReason ? (
              <div className="rounded-lg border border-red-200 bg-red-50 px-3 py-2 text-xs text-red-800">
                <p className="font-bold">{t("orders.lineFailedTitle")}</p>
                <p className="mt-1 leading-relaxed">{failReason}</p>
              </div>
            ) : null}
            <div className="space-y-2.5 text-xs">
              <div className="flex items-baseline justify-between gap-3">
                <span className="shrink-0 text-slate-500">{t("orders.drawNo")}</span>
                <span className="text-right font-mono font-black text-[#0b3f96]">
                  {data.draw_no ?? "—"}
                </span>
              </div>
              <div className="flex items-baseline justify-between gap-3">
                <span className="shrink-0 text-slate-500">{t("orders.placedAt")}</span>
                <span className="text-right font-medium text-slate-800">
                  {formatPlayerInstant(data.placed_at ?? null)}
                </span>
              </div>
              <div className="flex items-baseline justify-between gap-3">
                <span className="shrink-0 text-slate-500">{t("orders.number")}</span>
                <span className="text-right font-mono text-base font-black text-[#0b3f96]">
                  {data.original_number ?? "—"}
                </span>
              </div>
              <div className="flex items-baseline justify-between gap-3">
                <span className="shrink-0 text-slate-500">{t("orders.play")}</span>
                <span className="text-right font-semibold text-[#32518d]">
                  {playLabel(data.play_code, t)} ({data.dimension ?? "—"}D)
                </span>
              </div>
              <div className="flex items-baseline justify-between gap-3">
                <span className="shrink-0 text-slate-500">{t("orders.amount")}</span>
                <span className="text-right font-black tabular-nums text-[#d81435]">
                  {formatMinorAsCurrency(data.total_bet_amount, cur)}
                </span>
              </div>
              <div className="flex items-baseline justify-between gap-3">
                <span className="shrink-0 text-slate-500">{t("orders.rebateRate")}</span>
                <span className="text-right font-semibold tabular-nums text-emerald-600">
                  {(Number(data.rebate_rate_snapshot) * 100).toFixed(1)}%
                </span>
              </div>
              <div className="flex items-baseline justify-between gap-3">
                <span className="shrink-0 text-slate-500">{t("orders.actualDeduct")}</span>
                <span className="text-right font-black tabular-nums text-[#0b3f96]">
                  {formatMinorAsCurrency(data.actual_deduct_amount, cur)}
                </span>
              </div>
            </div>

            <div className="rounded-lg border border-[#c8daf6] bg-[#f0f6ff] px-3 py-2.5 text-xs">
              <p className="font-bold text-[#0b3f96]">{t("orders.oddsSnapshot")}</p>
              <p className="mt-1 leading-relaxed text-[#32518d]">
                {formatOddsSnapshot(data.odds_snapshot_json, t)}
              </p>
            </div>

            {pub?.results ? (
              <div className="space-y-2">
                <p className="text-sm font-bold text-[#0b3f96]">{t("orders.drawNumbers")}</p>
                <TwentyThreeResultsGrid numbers={pub.results} highlighted4d={highlight} />
                {first ? (
                  <p className="text-xs text-slate-500">
                    {t("orders.firstPrize")}{" "}
                    <span className="font-mono font-semibold text-slate-900">{first}</span>
                    {comboHits.length > 0 ? (
                      <span className="font-semibold text-emerald-600">
                        {" "}
                        ← {t("orders.hit")}
                      </span>
                    ) : null}
                  </p>
                ) : null}
                {!hasSettlement ? (
                  <p className="rounded-lg border border-[#dce7f7] bg-[#f8fbff] px-3 py-2 text-xs text-[#32518d]">
                    {t("orders.matchPendingSettlement")}
                  </p>
                ) : null}
              </div>
            ) : (
              <div className="rounded-lg border border-[#dce7f7] bg-[#f8fbff] px-3 py-3 text-xs">
                <p className="font-bold text-[#0b3f96]">{t("orders.drawNumbers")}</p>
                <p className="mt-1 text-[#32518d]">
                  {t("orders.drawPendingMatch")}
                </p>
              </div>
            )}

            {data.settlement && tierLabel ? (
              <div className="rounded-lg border border-emerald-200 bg-emerald-50 px-3 py-2 text-xs">
                <p className="font-bold text-emerald-900">
                  {t("orders.matchWin", { tier: tierLabel })}
                </p>
              <p className="mt-1 font-mono text-emerald-800/90">
                {t("orders.winAmount", {
                  amount: formatMinorAsCurrency(data.settlement.win_amount_minor, cur),
                })}
                {data.settlement.jackpot_allocation_minor > 0 ? (
                  <>
                    {" "}
                    ·{" "}
                    {t("orders.jackpotAmount", {
                      amount: formatMinorAsCurrency(
                        data.settlement.jackpot_allocation_minor,
                        cur,
                      ),
                    })}
                  </>
                ) : null}
              </p>
              <p className="mt-1 font-mono font-semibold text-emerald-900">
                {t(creditMode ? "orders.creditWinTotal" : "orders.payoutTotal", {
                  amount: formatMinorAsCurrency(totalWin, cur),
                })}
              </p>
              </div>
            ) : hasSettlement ? (
              <p className="text-xs text-slate-500">{t("orders.matchLose")}</p>
            ) : null}

            {matchResult && hasSettlement ? (
              <div className="rounded-lg border border-[#dce7f7] bg-[#f8fbff] px-3 py-3 text-xs">
                <p className="font-bold text-[#0b3f96]">
                  {t("orders.matchResult")}
                </p>
                <p className="mt-1 text-slate-600">
                  {matchResult.matched
                    ? t("orders.matchWin", { tier: tierLabel ?? (matchResult.matched_prize_tier ?? "—") })
                    : t("orders.matchLose")}
                </p>
                {Array.isArray(matchResult.lines) && matchResult.lines.length > 0 ? (
                  <div className="mt-2 space-y-1">
                    {matchResult.lines.map((line, idx) => (
                      <p key={`${line.number_4d ?? "line"}-${idx}`} className="font-mono text-[11px] text-slate-500">
                        {line.number_4d ?? "—"} · {line.matched_tier ?? "—"} · {formatMinorAsCurrency(line.payout ?? 0, cur)}
                      </p>
                    ))}
                  </div>
                ) : null}
              </div>
            ) : null}

            {timeline.length > 0 ? (
              <div className="rounded-xl border border-[#e8eef7] bg-[#f8fbff] px-3 py-3">
                <p className="text-sm font-bold text-[#0b3f96]">
                  {t("orders.timeline")}
                </p>
                <div className="mt-2 space-y-2">
                  {timeline.map((row) => (
                    <div key={row.code} className="flex items-start justify-between gap-3 rounded-lg bg-white px-3 py-2">
                      <p className="min-w-0 text-xs font-bold text-[#32518d]">
                        {t(`orders.timelineEvent.${row.code}`, { defaultValue: row.label })}
                      </p>
                      <p className="shrink-0 font-mono text-[11px] text-slate-500">
                        {formatPlayerInstant(row.time)}
                      </p>
                    </div>
                  ))}
                </div>
              </div>
            ) : null}

          {data.settled_at ? (
            <p className="text-[11px] text-slate-500">
              {t("orders.settledAt", { time: formatPlayerInstant(data.settled_at) })}
            </p>
          ) : null}
          </CardContent>
        </Card>

        <div className="flex flex-wrap gap-3">
          {data.draw_no ? (
            <Link
              href={`/results/${encodeURIComponent(data.draw_no)}`}
              prefetch={false}
              className={cn(
                "inline-flex h-11 min-w-[140px] flex-1 items-center justify-center rounded-xl bg-[#07459f] px-4 text-sm font-bold text-white shadow-sm transition-colors hover:bg-[#063b88]",
              )}
            >
              {t("orders.viewDraw")}
            </Link>
          ) : null}
          <Link
            href={backHref}
            className={cn(
              "inline-flex h-11 min-w-[140px] flex-1 items-center justify-center rounded-xl border border-[#dce7f7] bg-white px-4 text-sm font-semibold text-[#07459f] transition-colors hover:bg-[#f1f6ff]",
            )}
          >
            {t("orders.backToOrders")}
          </Link>
        </div>
      </div>
    </PlayerPanel>
  );
}
