import { useCallback, useEffect, useRef, useState } from "react";
import QRCode from "qrcode";
import { Coins, ReceiptText, Ticket, QrCode } from "lucide-react";
import { useTenant } from "../shell/AppShell";
import { myUsage, redeemCode, billingOrders, billingPacks, createWechatOrder, orderStatus, fmtCredits, type MyUsage, type TopupOrder, type Pack } from "../api";
import { Badge, Button, Dialog, Input, Panel, Table, Tr, Td, cn, useToast } from "../ui";

// 用量与账单：余额 + 兑换码充值(P5.1) + 消耗趋势 + 最近消耗/充值。
// 微信扫码支付在 P5.2 挂上（渠道适配器已留位），此前不做假支付入口。
export function Usage() {
  const toast = useToast();
  const { ctx, refresh } = useTenant();
  const [days, setDays] = useState(7);
  const [u, setU] = useState<MyUsage | null>(null);
  const [orders, setOrders] = useState<TopupOrder[]>([]);
  const [code, setCode] = useState("");
  const [busy, setBusy] = useState(false);
  const [packs, setPacks] = useState<Pack[]>([]);
  const [wechatOn, setWechatOn] = useState(false); // 服务端配了商户号才亮
  const [paying, setPaying] = useState<Pack | null>(null); // 正在扫码支付的包

  const load = useCallback(() => {
    myUsage(days).then(setU).catch(() => {});
    billingOrders().then(setOrders).catch(() => {});
    billingPacks()
      .then((r) => {
        setPacks(r.packs);
        setWechatOn(r.channels.includes("wechat"));
      })
      .catch(() => {});
  }, [days]);
  useEffect(load, [load, ctx?.tenant?.id]);

  const canTopup = ctx?.role !== "viewer"; // 真闸在后端(≥member)，这里只是不摆没用的输入框

  const redeem = async () => {
    if (!code.trim() || busy) return;
    setBusy(true);
    try {
      const r = await redeemCode(code.trim());
      toast.push("success", `已入账，当前余额 ${fmtCredits(r.balance_micro)} 积分`);
      setCode("");
      load();
      refresh(); // 顶栏/概览的余额也跟着变
    } catch (e) {
      toast.push("error", (e as Error).message);
    } finally {
      setBusy(false);
    }
  };

  const maxTok = Math.max(...(u?.trend.map((d) => d.total_tok) ?? []), 1);
  const fmtTok = (n: number) => (n >= 1e6 ? `${(n / 1e6).toFixed(1)}M` : n >= 1e3 ? `${(n / 1e3).toFixed(1)}K` : `${n}`);

  return (
    <div className="mx-auto max-w-3xl space-y-4 p-8">
      <div>
        <h1 className="text-xl font-semibold tracking-tight text-slate-100">用量与账单</h1>
        <p className="mt-1 text-xs text-slate-500">{ctx?.tenant?.name ?? "…"} · 消耗以积分计</p>
      </div>

      {/* 余额 hero */}
      <div className="rounded-xl border border-line bg-ink-900 p-5 shadow-card">
        <div className="flex items-end justify-between">
          <div>
            <div className="text-xs text-slate-500">当前余额</div>
            <div className="mt-1 text-3xl font-semibold tabular-nums text-slate-100">
              {fmtCredits(u?.balance_micro ?? ctx?.credit_balance_micro ?? 0)}
              <span className="ml-1.5 text-sm font-normal text-slate-500">积分</span>
            </div>
          </div>
          {u?.credit_enforce && (u?.balance_micro ?? 0) <= 0 ? (
            <Badge tone="danger">余额不足，任务提交将被拒绝</Badge>
          ) : null}
        </div>
        {canTopup ? (
          <div className="mt-4 border-t border-line pt-4">
            {/* 微信扫码：服务端配了商户号且有在售包才出现 */}
            {wechatOn && packs.length > 0 && (
              <div className="mb-4">
                <div className="mb-2 flex items-center gap-1.5 text-xs font-medium text-slate-400">
                  <QrCode className="h-3.5 w-3.5" /> 微信扫码充值
                </div>
                <div className="flex flex-wrap gap-2">
                  {packs.map((p) => (
                    <button key={p.id} onClick={() => setPaying(p)}
                      className="group rounded-lg border border-line bg-ink-850 px-4 py-2.5 text-left transition-colors hover:border-brand/50">
                      <div className="text-sm font-medium text-slate-200">{p.name}</div>
                      <div className="mt-0.5 text-xs text-slate-500">
                        <span className="tabular-nums text-brand-400">{fmtCredits(p.credits_micro)}</span> 积分 ·
                        <span className="ml-1 tabular-nums">¥{(p.price_fen / 100).toFixed(2)}</span>
                      </div>
                    </button>
                  ))}
                </div>
              </div>
            )}
            <div className="mb-2 flex items-center gap-1.5 text-xs font-medium text-slate-400">
              <Ticket className="h-3.5 w-3.5" /> 兑换码充值
            </div>
            <div className="flex flex-wrap items-center gap-2">
              <Input
                className="w-56 font-mono uppercase placeholder:font-sans placeholder:normal-case"
                value={code}
                onChange={(e) => setCode(e.target.value)}
                onKeyDown={(e) => e.key === "Enter" && redeem()}
                placeholder="SDX-XXXX-XXXX-XXXX"
              />
              <Button variant="primary" onClick={redeem} disabled={busy || !code.trim()}>
                {busy ? "入账中…" : "兑换"}
              </Button>
              <span className="text-[11px] text-slate-600">
                {wechatOn ? "兑换码请向平台获取。" : "微信扫码支付即将上线；兑换码请向平台获取。"}
              </span>
            </div>
          </div>
        ) : (
          <p className="mt-3 text-[11px] text-slate-600">你是只读角色，充值请联系组织管理员。</p>
        )}
      </div>

      {/* 趋势 */}
      <Panel
        title="消耗趋势"
        icon={Coins}
        actions={
          <div className="flex items-center gap-1 rounded-md border border-line p-0.5">
            {[7, 30].map((d) => (
              <button key={d} onClick={() => setDays(d)}
                className={cn("rounded px-2 py-0.5 text-[11px] transition", days === d ? "bg-ink-800 text-slate-100" : "text-slate-500 hover:text-slate-300")}>
                近 {d} 天
              </button>
            ))}
          </div>
        }>
        <div className="flex h-28 items-end gap-1.5">
          {(u?.trend ?? []).map((d) => (
            <div key={d.day} className="flex flex-1 flex-col items-center gap-1">
              <div className="w-full rounded-t bg-brand/60 transition-all hover:bg-brand"
                style={{ height: `${Math.max((d.total_tok / maxTok) * 100, 2)}%` }}
                title={`${d.day}：${fmtTok(d.total_tok)} tok · ${fmtCredits(d.credits_micro)} 积分 · ${d.task_count} 次`} />
              <span className="text-[9px] tabular-nums text-slate-600">{d.day.slice(-2)}</span>
            </div>
          ))}
          {(!u || u.trend.length === 0) && <p className="flex-1 self-center text-center text-xs text-slate-600">区间内暂无消耗</p>}
        </div>
        <div className="mt-3 flex gap-4 border-t border-line pt-3 text-[11px] text-slate-500">
          <span>合计 <span className="tabular-nums text-slate-300">{fmtTok(u?.totals.total_tok ?? 0)}</span> tok</span>
          <span><span className="tabular-nums text-slate-300">{fmtCredits(u?.totals.credits_micro ?? 0)}</span> 积分</span>
          <span><span className="tabular-nums text-slate-300">{u?.totals.task_count ?? 0}</span> 次任务</span>
        </div>
      </Panel>

      {/* 最近消耗 */}
      <Panel title="最近消耗" icon={ReceiptText} bodyClassName="p-0">
        <Table cols={["任务", "模型", "tokens", "积分"]}>
          {(u?.recent ?? []).map((r) => (
            <Tr key={r.task_id}>
              <Td><span className="font-mono text-[11px] text-slate-400">{r.task_id}</span></Td>
              <Td><span className="text-xs text-slate-300">{r.model || "—"}</span></Td>
              <Td><span className="text-xs tabular-nums text-slate-300">{fmtTok(r.total_tok)}</span></Td>
              <Td><span className="text-xs tabular-nums text-slate-300">{fmtCredits(r.credits_micro)}</span></Td>
            </Tr>
          ))}
        </Table>
        {(!u || u.recent.length === 0) && <p className="p-4 text-xs text-slate-600">暂无消耗记录。</p>}
      </Panel>

      {/* 最近充值（订单流：兑换码与将来的微信支付一个查法） */}
      {orders.length > 0 && (
        <Panel title="最近充值" icon={Ticket} bodyClassName="p-0">
          <Table cols={["时间", "渠道", "积分", "状态"]}>
            {orders.map((o) => (
              <Tr key={o.id}>
                <Td><span className="text-xs text-slate-400">{new Date(o.created_at).toLocaleString()}</span></Td>
                <Td><span className="text-xs text-slate-300">{o.channel === "redeem" ? "兑换码" : o.channel === "wechat" ? "微信支付" : o.channel}</span></Td>
                <Td><span className="text-xs tabular-nums text-slate-200">+{fmtCredits(o.credits_micro)}</span></Td>
                <Td>
                  <Badge tone={o.status === "paid" ? "success" : o.status === "pending" ? "warn" : "danger"}>
                    {o.status === "paid" ? "已入账" : o.status === "pending" ? "待支付" : o.status}
                  </Badge>
                </Td>
              </Tr>
            ))}
          </Table>
        </Panel>
      )}

      {paying && (
        <PayDialog
          pack={paying}
          onClose={(paid) => {
            setPaying(null);
            if (paid) {
              toast.push("success", "支付成功，积分已入账");
              load();
              refresh();
            }
          }}
        />
      )}
    </div>
  );
}

// PayDialog 微信 Native 扫码支付：下单 → code_url 画二维码 → 轮询单态（2.5s；
// 服务端 pending 时会顺路主动查单，收不到公网回调的环境也能确认到账）。
function PayDialog({ pack, onClose }: { pack: Pack; onClose: (paid: boolean) => void }) {
  const [qr, setQr] = useState("");
  const [err, setErr] = useState("");
  const [state, setState] = useState<"creating" | "waiting" | "paid" | "expired">("creating");
  const orderRef = useRef("");

  useEffect(() => {
    let alive = true;
    let timer: number | null = null;
    (async () => {
      try {
        const o = await createWechatOrder(pack.id);
        if (!alive) return;
        orderRef.current = o.order_id;
        setQr(await QRCode.toDataURL(o.code_url, { width: 240, margin: 1 }));
        setState("waiting");
        timer = window.setInterval(async () => {
          try {
            const s = await orderStatus(orderRef.current);
            if (!alive) return;
            if (s.status === "paid") {
              setState("paid");
              if (timer) window.clearInterval(timer);
              window.setTimeout(() => onClose(true), 800);
            } else if (s.status === "expired" || s.status === "failed") {
              setState("expired");
              if (timer) window.clearInterval(timer);
            }
          } catch {
            /* 单次轮询失败忽略，下个 tick 再试 */
          }
        }, 2500);
      } catch (e) {
        if (alive) setErr((e as Error).message);
      }
    })();
    return () => {
      alive = false;
      if (timer) window.clearInterval(timer);
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [pack.id]);

  return (
    <Dialog open title={`微信扫码 · ${pack.name}`} onClose={() => onClose(state === "paid")}>
      <div className="flex flex-col items-center gap-3 py-2">
        {err ? (
          <p className="text-xs text-danger">{err}</p>
        ) : state === "creating" ? (
          <p className="py-16 text-xs text-slate-500">正在生成支付二维码…</p>
        ) : (
          <>
            {/* 二维码底色固定纯白：扫码器对暗色主题下的低对比码识别率差 */}
            <div className="rounded-lg bg-white p-2">
              <img src={qr} alt="微信支付二维码" width={240} height={240} />
            </div>
            <div className="text-center">
              <div className="text-lg font-semibold tabular-nums text-slate-100">¥{(pack.price_fen / 100).toFixed(2)}</div>
              <div className="mt-1 text-xs text-slate-500">
                {state === "paid" ? "✅ 已支付，入账中…" : state === "expired" ? "订单已过期，请关闭后重新下单" : `微信扫一扫支付，到账 ${fmtCredits(pack.credits_micro)} 积分`}
              </div>
            </div>
          </>
        )}
      </div>
    </Dialog>
  );
}
