// 提款申請頁：收創作者的提款單、每週轉出 CSV 給出納撥款、標記已撥款 / 退回。
//
// 資料來源 GET /api/admin/withdrawals（含明細、數字 UID）；動作 POST /api/admin/withdrawals/[id]。
// CSV 分層：每張提款單先一條「提款單」主行（總額），其下再列各「訂單明細」子行；
// 可用「含訂單明細」開關關掉子行、只留主行（一單一列）。含 Merchant ID 欄（暫留空給出納填，
// 日後 User 建欄位即由 API 帶 w.merchantId 自動帶出）。創作者 ID 用數字 UID（User.uid）。
// 出納拿到後看總額撥款、細項備查（見 lib/withdrawal.ts）。

const WD_STATUS = {
  pending:  { label: "待撥款", tone: "warn" },
  paid:     { label: "已撥款", tone: "success" },
  rejected: { label: "已退回", tone: "default" },
};

const WD_RANGE_OPTS = [
  { value: "all",       label: "全部期間" },
  { value: "thisWeek",  label: "本週" },
  { value: "lastWeek",  label: "上週" },
  { value: "thisMonth", label: "本月" },
  { value: "custom",    label: "自訂區間" },
];

// twDate / twDateTime 共用定義在 ui.jsx（全站共用，避免跟其他頁面同名 const 互相覆蓋）

// 依區間算 createdAt 的 [from, to)；邊界以「台北午夜」對應的 UTC 瞬間表示，避免週界差幾小時。
function wdComputeRange(kind) {
  if (kind === "all") return { from: null, to: null };
  const now = new Date();
  const ymd = (dt) => `${dt.getFullYear()}-${String(dt.getMonth() + 1).padStart(2, "0")}-${String(dt.getDate()).padStart(2, "0")}`;
  const twMidnight = (dt) => new Date(`${ymd(dt)}T00:00:00+08:00`).toISOString();

  if (kind === "thisMonth") {
    const from = new Date(now.getFullYear(), now.getMonth(), 1);
    const to = new Date(now.getFullYear(), now.getMonth() + 1, 1);
    return { from: twMidnight(from), to: twMidnight(to) };
  }
  // 週一為一週起點
  const d = new Date(now.getFullYear(), now.getMonth(), now.getDate());
  const dow = (d.getDay() + 6) % 7; // 週一=0
  const monday = new Date(d); monday.setDate(d.getDate() - dow);
  if (kind === "lastWeek") monday.setDate(monday.getDate() - 7);
  const nextMonday = new Date(monday); nextMonday.setDate(monday.getDate() + 7);
  return { from: twMidnight(monday), to: twMidnight(nextMonday) };
}

// 自訂區間：fromYmd/toYmd 皆為 YYYY-MM-DD。以「台北午夜」界定，且 to 為「含當日」→ 取結束日隔天當上界。
// 空值代表該側不設限（可只填開始或只填結束）。台灣無夏令時間，直接 +24h 取隔天安全。
function wdCustomRange(fromYmd, toYmd) {
  const from = fromYmd ? new Date(`${fromYmd}T00:00:00+08:00`).toISOString() : null;
  const to = toYmd
    ? new Date(new Date(`${toYmd}T00:00:00+08:00`).getTime() + 86400000).toISOString()
    : null;
  return { from, to };
}

const WithdrawalsPage = () => {
  const [statusTab, setStatusTab] = useState("pending");
  const [range, setRange] = useState("all");
  const [customFrom, setCustomFrom] = useState(""); // 自訂區間開始日 YYYY-MM-DD
  const [customTo, setCustomTo] = useState("");     // 自訂區間結束日（含當日）
  const [data, setData] = useState([]);
  const [counts, setCounts] = useState({ all: 0, pending: 0, paid: 0, rejected: 0 });
  const [loading, setLoading] = useState(true);
  const [expanded, setExpanded] = useState({}); // withdrawalId → bool
  const [checkedIds, setCheckedIds] = useState(() => new Set()); // 勾選要匯出的提款單 id
  const [includeItems, setIncludeItems] = useState(true); // CSV 是否含訂單明細子列；關閉＝只留提款單主行
  const [action, setAction] = useState(null);   // { type: "mark_paid"|"reject", wd }
  const toast = useToast();

  const load = () => {
    setLoading(true);
    setCheckedIds(new Set()); // 篩選條件變了，清掉舊勾選避免匯出到已看不見的單
    const p = new URLSearchParams();
    if (statusTab !== "all") p.set("status", statusTab);
    const { from, to } = range === "custom"
      ? wdCustomRange(customFrom, customTo)
      : wdComputeRange(range);
    if (from) p.set("from", from);
    if (to) p.set("to", to);
    fetch(`/api/admin/withdrawals?${p.toString()}`)
      .then(r => (r.ok ? r.json() : null))
      .then(d => { if (d) { setData(d.withdrawals ?? []); setCounts(d.counts ?? {}); } })
      .catch(() => {})
      .finally(() => setLoading(false));
  };
  useEffect(load, [statusTab, range, customFrom, customTo]);

  const handleExport = () => {
    // 匯出對象：有勾選 → 只匯出勾的那幾張；完全沒勾 → 匯出目前篩選下的全部（省得一定要先全選）。
    const target = checkedIds.size > 0 ? data.filter(w => checkedIds.has(w.id)) : data;
    if (target.length === 0) {
      toast({ title: "沒有可匯出的資料", message: "目前篩選/勾選下沒有提款單", icon: "alert" });
      return;
    }
    // 分層結構：每張提款單先出一條「提款單」主行（總額 = 創作者實際要提領的錢），
    // includeItems 開啟時，其下再列該單每筆「訂單明細」子行；關閉則只留主行（一單一列）。
    // Merchant ID 欄目前留空給出納填；日後若在 User 建欄位 → 由 API 帶 w.merchantId 自動帶出。
    const headers = ["類型", "申請時間", "提款單號", "創作者UID", "創作者名稱", "Merchant ID", "訂單編號", "訂單名稱", "委託人", "訂單建立日", "訂單完成日", "金額", "訂單數"];
    const rows = [];
    let itemTotal = 0;
    target.forEach(w => {
      const wdNo = w.id.slice(0, 8).toUpperCase();
      // UID 補零到 8 位、與創作者主頁徽章一致；用 Excel 文字守衛 ="0000..." 避免試算表吃掉前導零
      const uid = w.uid != null ? `="${String(w.uid).padStart(8, "0")}"` : "";
      const merchantId = w.merchantId ?? "";
      // 主行：提款總額
      rows.push([
        "提款單", twDateTime(w.createdAt), wdNo, uid, w.artistName ?? "", merchantId,
        "", "", "", "", "", w.totalAmount, w.itemCount,
      ]);
      // 子行：湊成該總額的每筆訂單（保留提款單號，方便在 Excel 重新排序後仍能歸戶）
      if (includeItems) {
        (w.items ?? []).forEach(it => {
          itemTotal++;
          rows.push([
            "　└ 訂單明細", "", wdNo, "", "", "",
            it.orderNo, it.productName, it.commissionerName,
            twDate(it.orderCreatedAt), twDate(it.orderCompletedAt), it.netAmount, "",
          ]);
        });
      }
    });
    const stamp = new Date().toLocaleDateString("en-CA", { timeZone: "Asia/Taipei" });
    csvDownload(`withdrawals_${stamp}.csv`, headers, rows);
    toast({
      title: "CSV 已匯出",
      message: `${target.length} 張提款單${includeItems ? ` · ${itemTotal} 筆訂單明細` : "（未含明細）"}`,
      icon: "download",
    });
  };

  // 勾選操作
  const allChecked = data.length > 0 && checkedIds.size === data.length;
  const toggleAll = (v) => setCheckedIds(v ? new Set(data.map(w => w.id)) : new Set());
  const toggleOne = (id) => setCheckedIds(s => {
    const n = new Set(s);
    n.has(id) ? n.delete(id) : n.add(id);
    return n;
  });

  const submitAction = async ({ reason }) => {
    if (!action) return;
    const res = await fetch(`/api/admin/withdrawals/${action.wd.id}`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ action: action.type, reason }),
    });
    setAction(null);
    if (res.ok) {
      toast({ title: action.type === "mark_paid" ? "已標記撥款" : "已退回提款申請", icon: "check" });
      load();
    } else {
      const d = await res.json().catch(() => ({}));
      toast({ title: "操作失敗", message: d.error ?? "請稍後再試", icon: "alert" });
    }
  };

  const totalPending = data
    .filter(w => w.status === "pending")
    .reduce((s, w) => s + (w.totalAmount ?? 0), 0);

  return (
    <div className="fade-in">
      <PageHeader
        title="提款申請"
        subtitle="創作者提領已完成訂單收入 · 每週轉出 CSV 給出納撥款"
        actions={<>
          <Select value={range} onChange={setRange} icon="calendar" options={WD_RANGE_OPTS}/>
          {range === "custom" && (
            <>
              <Input type="date" value={customFrom} onChange={e => setCustomFrom(e.target.value)} style={{ width: 150 }}/>
              <span style={{ color: "var(--ink-4)" }}>~</span>
              <Input type="date" value={customTo} onChange={e => setCustomTo(e.target.value)} style={{ width: 150 }}/>
            </>
          )}
          <Button variant="secondary" icon="refresh" onClick={load}>重新整理</Button>
          <label
            onClick={() => setIncludeItems(v => !v)}
            style={{ display: "flex", alignItems: "center", gap: 6, fontSize: 12.5, color: "var(--ink-3)", cursor: "pointer", userSelect: "none" }}
          >
            <Checkbox checked={includeItems} onChange={setIncludeItems}/>
            含訂單明細
          </label>
          <Button variant="primary" icon="download" onClick={handleExport}>
            匯出 CSV{checkedIds.size > 0 ? `（${checkedIds.size}）` : ""}
          </Button>
        </>}
      />

      <div style={{ marginBottom: 16 }}>
        <Tabs active={statusTab} onChange={setStatusTab} tabs={[
          { value: "pending",  label: "待撥款", count: counts.pending },
          { value: "paid",     label: "已撥款", count: counts.paid },
          { value: "rejected", label: "已退回", count: counts.rejected },
          { value: "all",      label: "全部",   count: counts.all },
        ]}/>
      </div>

      {/* 目前清單待撥款總額 + 全選 */}
      <div style={{ padding: "10px 16px", background: "var(--surface-2)", borderRadius: 10, marginBottom: 14, display: "flex", alignItems: "center", gap: 20, fontSize: 12.5 }}>
        <label style={{ display: "flex", alignItems: "center", gap: 8, cursor: data.length ? "pointer" : "default" }}>
          <Checkbox checked={allChecked} onChange={toggleAll}/>
          <span>{checkedIds.size > 0 ? `已勾選 ${checkedIds.size} / ${data.length}` : "全選"}</span>
        </label>
        <span style={{ color: "var(--ink-4)" }}>|</span>
        <span>{data.length} 張提款單</span>
        <span style={{ color: "var(--ink-4)" }}>|</span>
        <span>待撥款總額 <b className="mono" style={{ color: "var(--warn)" }}>NT$ {fmtNum(totalPending)}</b></span>
      </div>

      {loading ? (
        <div style={{ padding: 48, textAlign: "center", color: "var(--ink-3)" }}>載入中…</div>
      ) : data.length === 0 ? (
        <Card padding={48} style={{ textAlign: "center", color: "var(--ink-4)" }}>
          <Icon name="coin" size={26} style={{ marginBottom: 8 }}/>
          <div>目前沒有符合條件的提款申請</div>
        </Card>
      ) : (
        <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
          {data.map(w => {
            const meta = WD_STATUS[w.status] ?? WD_STATUS.pending;
            const open = !!expanded[w.id];
            return (
              <Card key={w.id} padding={0}>
                {/* header row */}
                <div style={{ display: "flex", alignItems: "center", gap: 14, padding: "14px 16px" }}>
                  <Checkbox checked={checkedIds.has(w.id)} onChange={() => toggleOne(w.id)}/>
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 3 }}>
                      <span style={{ fontSize: 14, fontWeight: 600 }}>{w.artistName || "創作者"}</span>
                      <Badge tone={meta.tone} size="sm">{meta.label}</Badge>
                    </div>
                    <div style={{ fontSize: 12, color: "var(--ink-3)" }} className="mono">
                      #{w.id.slice(0, 8).toUpperCase()} · UID {w.uid != null ? String(w.uid).padStart(8, "0") : "—"} · 申請於 {twDateTime(w.createdAt)}
                      {w.status === "paid" && w.paidAt && <> · 撥款於 {twDateTime(w.paidAt)}</>}
                    </div>
                  </div>
                  <div style={{ textAlign: "right" }}>
                    <div className="mono" style={{ fontSize: 15, fontWeight: 600 }}>NT$ {fmtNum(w.totalAmount)}</div>
                    <div style={{ fontSize: 11.5, color: "var(--ink-4)" }}>{w.itemCount} 筆訂單</div>
                  </div>
                  <Button size="sm" variant="ghost" icon={open ? "chevron-down" : "chevron-right"}
                    onClick={() => setExpanded(e => ({ ...e, [w.id]: !e[w.id] }))}>明細</Button>
                  {w.status === "pending" && (
                    <>
                      <Button size="sm" variant="secondary" onClick={() => setAction({ type: "reject", wd: w })}>退回</Button>
                      <Button size="sm" variant="primary" onClick={() => setAction({ type: "mark_paid", wd: w })}>標記已撥款</Button>
                    </>
                  )}
                </div>

                {/* detail items */}
                {open && (
                  <div style={{ borderTop: "1px solid var(--border)", padding: "4px 16px 12px" }}>
                    <Table
                      columns={[
                        { title: "訂單編號", render: it => <span className="mono" style={{ fontSize: 12 }}>{it.orderNo}</span> },
                        { title: "訂單名稱", render: it => <span style={{ fontSize: 13 }}>{it.productName}</span> },
                        { title: "委託人", render: it => <span style={{ fontSize: 13 }}>{it.commissionerName}</span> },
                        { title: "建立日", render: it => <span className="mono" style={{ fontSize: 12, color: "var(--ink-3)" }}>{twDate(it.orderCreatedAt)}</span> },
                        { title: "完成日", render: it => <span className="mono" style={{ fontSize: 12, color: "var(--ink-3)" }}>{twDate(it.orderCompletedAt)}</span> },
                        { title: "實領金額", align: "right", render: it => <span className="mono" style={{ fontWeight: 500 }}>NT$ {fmtNum(it.netAmount)}</span> },
                      ]}
                      rows={w.items ?? []}
                    />
                  </div>
                )}
              </Card>
            );
          })}
        </div>
      )}

      {action && (
        <ConfirmDialog
          open onClose={() => setAction(null)}
          variant={action.type === "mark_paid" ? "info" : "danger"}
          icon={action.type === "mark_paid" ? "check" : "alert"}
          confirmText={action.type === "mark_paid" ? "確認已撥款" : "確認退回"}
          requireReason={action.type === "reject"}
          reasonLabel="退回原因"
          reasonPlaceholder="例：收款資料不完整，請創作者補齊後再申請。"
          title={action.type === "mark_paid"
            ? `標記已撥款 · NT$ ${fmtNum(action.wd.totalAmount)}`
            : `退回提款申請 · NT$ ${fmtNum(action.wd.totalAmount)}`}
          description={action.type === "mark_paid"
            ? `確認出納已完成撥款給「${action.wd.artistName || "創作者"}」（${action.wd.itemCount} 筆訂單）。標記後創作者端狀態會變為「已撥款」。`
            : `退回後，此單的 ${action.wd.itemCount} 筆訂單將重新回到創作者的可提領款項，可再次申請。`}
          onConfirm={submitAction}
        />
      )}
    </div>
  );
};

window.WithdrawalsPage = WithdrawalsPage;
