import { useCallback, useEffect, useMemo, useState } from "react";
import { Link, useLocation, useNavigate } from "react-router-dom";
import { useAuth } from "../auth/AuthContext";
import { PageHeader } from "../components/layout/PageHeader";
import { UsageLedger } from "../components/usage/UsageLedger";
import { UsageMeterBars } from "../components/usage/UsageMeterBars";
import { UsageSeriesChart } from "../components/usage/UsageSeriesChart";
import { Badge, Button, Card, EmptyState, Pager, Select } from "../components/ui";
import { useData, useRepos } from "../data/DataContext";
import { useI18n } from "../i18n/I18nContext";
import { memberRoleSummary } from "../lib/memberRole";
import { pageSlice } from "../lib/pagination";
import { getPlanRights } from "../lib/planRights";
import {
  METER_META,
  PLANS,
  usageWarning,
  type PlanId,
  type TenantUsageAnalytics,
  type UsageGranularity,
  type UsageMeter,
  type UsageMonthSummary,
} from "../lib/usageMeter";

const LEDGER_PAGE = 10;
const MEMBER_PAGE = 10;

type UsageTab = "mine" | "tenant";

function localDateKey(d: Date): string {
  return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
}

function defaultFromFor(g: UsageGranularity): string {
  const to = new Date();
  if (g === "day") {
    const d = new Date(to.getFullYear(), to.getMonth(), to.getDate() - 29);
    return localDateKey(d);
  }
  if (g === "year") {
    return `${to.getFullYear() - 2}-01-01`;
  }
  const d = new Date(to.getFullYear(), to.getMonth() - 11, 1);
  return localDateKey(d);
}

function todayKey(): string {
  return localDateKey(new Date());
}

/**
 * 用量首頁：只回答「我用了多少／還剩多少」。
 * 換方案 → /usage/plans → checkout（一般 SaaS 路徑）。
 */
export function UsagePage() {
  const repos = useRepos();
  const { member } = useAuth();
  const { tick, refresh } = useData();
  const { t, formatPlanPrice } = useI18n();
  const navigate = useNavigate();
  const location = useLocation();
  const isAdmin = memberRoleSummary(member).isAdmin;

  const [tab, setTab] = useState<UsageTab>("mine");
  const [summary, setSummary] = useState<UsageMonthSummary | null>(null);
  const [outcomeSummary, setOutcomeSummary] = useState<{
    reach: number;
    conversations: number;
    conversions: number;
    conversion_amount: number;
  } | null>(null);
  const [tenant, setTenant] = useState<TenantUsageAnalytics | null>(null);
  const [ledgerPage, setLedgerPage] = useState(1);
  const [memberPage, setMemberPage] = useState(1);
  const [busy, setBusy] = useState("");
  const [message, setMessage] = useState("");
  const [error, setError] = useState("");
  const [showLedger, setShowLedger] = useState(false);

  const [granularity, setGranularity] = useState<UsageGranularity>("month");
  const [fromDraft, setFromDraft] = useState(() => defaultFromFor("month"));
  const [toDraft, setToDraft] = useState(() => todayKey());
  const [applied, setApplied] = useState(() => ({
    granularity: "month" as UsageGranularity,
    from: defaultFromFor("month"),
    to: todayKey(),
  }));

  const loadMine = useCallback(async () => {
    try {
      setSummary(await repos.usage.getSummary());
      const oc = await repos.growth.getOutcomeSummary("month").catch(() => null);
      setOutcomeSummary(
        oc
          ? {
              reach: oc.reach,
              conversations: oc.conversations,
              conversions: oc.conversions,
              conversion_amount: oc.conversion_amount,
            }
          : null,
      );
      setError("");
    } catch (e) {
      setError(e instanceof Error ? e.message : t("usage.fail"));
    }
  }, [repos.usage, repos.growth, t]);

  /** 失敗會 throw：呼叫端的存檔流程要能知道刷新沒成功，不能自己吞掉。 */
  async function loadTenant(query = applied) {
    if (!isAdmin) return;
    setTenant(
      await repos.usage.getTenantAnalytics({
        granularity: query.granularity,
        from: query.from,
        to: query.to,
      }),
    );
  }

  useEffect(() => {
    const st = location.state as { purchaseOk?: PlanId } | null;
    if (st?.purchaseOk && PLANS[st.purchaseOk]) {
      setMessage(t("usage.subscribed", { name: PLANS[st.purchaseOk].name }));
      setTab("mine");
      navigate(location.pathname, { replace: true, state: null });
      void loadMine();
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [location.state]);

  useEffect(() => {
    void loadMine();
  }, [loadMine, tick]);

  useEffect(() => {
    if (tab !== "tenant" || !isAdmin) return;
    void loadTenant(applied).then(
      () => setError(""),
      (e: unknown) => setError(e instanceof Error ? e.message : t("usage.fail")),
    );
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [tab, isAdmin, repos.usage, tick, applied]);

  useEffect(() => {
    const onStore = () => refresh();
    window.addEventListener("harbor:store", onStore);
    return () => window.removeEventListener("harbor:store", onStore);
  }, [refresh]);

  function onGranularityChange(g: UsageGranularity) {
    const from = defaultFromFor(g);
    const to = todayKey();
    setGranularity(g);
    setFromDraft(from);
    setToDraft(to);
    commitRange({ granularity: g, from, to });
  }

  function commitRange(next?: {
    granularity?: UsageGranularity;
    from?: string;
    to?: string;
  }) {
    const g = next?.granularity ?? granularity;
    const from = next?.from ?? (fromDraft || defaultFromFor(g));
    const to = next?.to ?? (toDraft || todayKey());
    setMemberPage(1);
    setApplied({ granularity: g, from, to });
  }

  const warn = useMemo(() => (summary ? usageWarning(summary, t) : null), [summary, t]);
  const planRights = useMemo(
    () => (summary ? getPlanRights(summary.plan.id as PlanId, t, formatPlanPrice) : null),
    [summary, t, formatPlanPrice],
  );

  const meterRows = useMemo(() => {
    if (!summary) return [];
    return (Object.keys(METER_META) as UsageMeter[]).map((m) => ({
      meter: m,
      credits: summary.by_meter[m].credits,
      count: summary.by_meter[m].count,
      soft_cap: summary.by_meter[m].soft_cap,
    }));
  }, [summary]);

  async function toggleUnlimited(uid: string, unlimited: boolean) {
    setBusy(`unl:${uid}`);
    setError("");
    try {
      await repos.usage.setMemberPrefs(uid, { unlimited });
      await loadTenant(applied);
      if (uid === member?.uid) await loadMine();
      setMessage(unlimited ? t("usage.unlimitedSet") : t("usage.limitedSet"));
    } catch (e) {
      setError(e instanceof Error ? e.message : t("usage.fail"));
    } finally {
      setBusy("");
    }
  }

  async function setMemberPlan(uid: string, plan_id: PlanId) {
    setBusy(`plan:${uid}`);
    setError("");
    try {
      await repos.usage.setMemberPrefs(uid, { plan_id });
      await loadTenant(applied);
      if (uid === member?.uid) await loadMine();
      setMessage(t("usage.planUpdated", { name: PLANS[plan_id].name }));
    } catch (e) {
      setError(e instanceof Error ? e.message : t("usage.fail"));
    } finally {
      setBusy("");
    }
  }

  if (!summary) {
    return (
      <>
        <PageHeader title={t("usage.title")} />
        {error ? (
          <p className="hb-form-error" role="alert">{error}</p>
        ) : (
          <p className="text-muted">{t("common.loading")}</p>
        )}
      </>
    );
  }

  const pagedMembers = tenant ? pageSlice(tenant.members, memberPage, MEMBER_PAGE) : [];
  // total_credits = 已用；配給一律用目前方案 monthly_credits（PLANS）
  const usedCredits = summary.platform?.credits_used ?? summary.total_credits;
  const capCredits = summary.plan.monthly_credits;
  const remainCredits = summary.unlimited
    ? summary.remaining_credits
    : Math.max(0, capCredits - usedCredits);
  const usedPct = Math.min(
    100,
    summary.pct > 0
      ? Math.min(100, summary.pct)
      : capCredits > 0
        ? Math.round((usedCredits / capCredits) * 100)
        : 0,
  );
  const barTone =
    usedCredits > capCredits ? " is-danger" : usedPct >= 70 ? " is-warn" : "";

  return (
    <>
      <PageHeader title={t("usage.title")} />

      {message ? (
        <p className="hb-banner-ok" role="status">
          {message}
        </p>
      ) : null}
      {error ? (
        <p className="hb-form-error" role="alert">
          {error}
        </p>
      ) : null}
      {warn && tab === "mine" ? (
        <p className="hb-banner-warn" role="status">
          {warn}
        </p>
      ) : null}

      {isAdmin ? (
        <div className="hb-tabs" role="tablist">
          <button
            type="button"
            className={`hb-tab ${tab === "mine" ? "is-active" : ""}`}
            onClick={() => setTab("mine")}
          >
            {t("usage.tabMine")}
          </button>
          <button
            type="button"
            className={`hb-tab ${tab === "tenant" ? "is-active" : ""}`}
            onClick={() => setTab("tenant")}
          >
            {t("usage.tabTenant")}
          </button>
        </div>
      ) : null}

      {tab === "mine" || !isAdmin ? (
        <div className="hb-stack hb-usage-mine">
          {/* 訂閱狀態列：一眼知道方案 + 換方案 */}
          <Card className="hb-usage-sub">
            <div className="hb-usage-sub__row">
              <div className="hb-usage-sub__info">
                <span className="hb-usage-sub__label">{t("usage.currentPlan")}</span>
                <div className="hb-usage-sub__plan">
                  <strong>{summary.plan.name}</strong>
                  {summary.unlimited ? <Badge tone="brand">∞</Badge> : null}
                </div>
                <p className="hb-usage-sub__meta">
                  {formatPlanPrice(summary.plan.price_twd)}
                  {t("usage.planMeta", { n: summary.plan.monthly_credits })}
                </p>
                {planRights ? (
                  <>
                    <p className="hb-usage-sub__caps">{planRights.approxCallsLine}</p>
                    <p className="hb-usage-sub__caps hb-usage-sub__caps--pts">
                      {planRights.softCapsLine}
                    </p>
                  </>
                ) : null}
              </div>
              <Button type="button" onClick={() => navigate("/app/usage/plans")}>
                {summary.plan.id === "free" ? t("usage.upgradePlan") : t("usage.changePlan")}
              </Button>
            </div>
          </Card>

          <Card title={t("usage.outcome.title")}>
            <p className="text-muted" style={{ margin: 0 }}>
              {t("usage.outcome.summary", {
                reach: outcomeSummary?.reach ?? 0,
                conversations: outcomeSummary?.conversations ?? 0,
                conversions: outcomeSummary?.conversions ?? 0,
              })}
              {outcomeSummary?.conversion_amount
                ? t("usage.outcome.amount", { amount: Math.round(outcomeSummary.conversion_amount) })
                : ""}
            </p>
            {!outcomeSummary?.reach && !outcomeSummary?.conversations && !outcomeSummary?.conversions ? (
              <p className="text-muted" style={{ margin: "0.35rem 0 0", fontSize: "var(--hb-text-xs)" }}>
                {t("usage.outcome.emptyHint")}
              </p>
            ) : null}
          </Card>

          {/* 本月用量：進度為主 */}
          <Card>
            <div className="hb-usage-status">
              <div className="hb-usage-status__nums">
                <div>
                  <span className="hb-usage-chart__name">{t("usage.usedThisMonth")}</span>
                  <p className="hb-usage-status__big">
                    {usedCredits}
                    <span className="text-muted"> / {capCredits}</span>
                  </p>
                </div>
                <div className="hb-usage-status__remain">
                  <span className="hb-usage-chart__name">{t("usage.remainLabel")}</span>
                  <p className="hb-usage-status__big">
                    {summary.unlimited ? "∞" : remainCredits}
                  </p>
                </div>
              </div>
              <div className="hb-progress" aria-hidden>
                <div
                  className={`hb-progress__bar hb-progress__bar--use${barTone}`}
                  style={{ width: `${usedPct}%` }}
                />
              </div>
              <div className="hb-usage-status__foot">
                <span className="text-muted">{usedPct}%</span>
                <span className="hb-usage-side-metrics" style={{ margin: 0, border: 0, padding: 0 }}>
                  <span title={t("usage.side.aiCredits")}>
                    AI <strong>{summary.ai_calls}</strong>
                    <span className="text-muted">{t("usage.meter.pt")}</span>
                  </span>
                  <span title={t("usage.side.searchCredits")}>
                    Search <strong>{summary.search_calls}</strong>
                    <span className="text-muted">{t("usage.meter.pt")}</span>
                  </span>
                </span>
              </div>
            </div>
          </Card>

          <Card>
            <UsageMeterBars rows={meterRows} unlimited={summary.unlimited} />
          </Card>

          <Card>
            <div className="hb-list-row">
              <div>
                <strong>{t("usage.byok.title")}</strong>
                <p className="text-muted">{t("usage.byok.hint")}</p>
              </div>
              <Badge tone="neutral">{t("usage.meter.timesShort", { n: summary.byok.call_count })}</Badge>
            </div>
            <ul className="hb-usage-byok-list">
              {(Object.keys(METER_META) as UsageMeter[])
                .sort((a, b) => METER_META[a].order - METER_META[b].order)
                .map((meter) => (
                  <li key={meter}>
                    <span>{t(`usage.meter.${meter}`)}</span>
                    <strong>{t("usage.meter.timesShort", { n: summary.byok.by_meter[meter].count })}</strong>
                  </li>
                ))}
            </ul>
          </Card>

          <Card>
            <button
              type="button"
              className="hb-usage-disclosure"
              onClick={() => setShowLedger((v) => !v)}
              aria-expanded={showLedger}
            >
              <span>{t("usage.ledgerToggle")}</span>
              <span className="text-muted">
                {showLedger ? t("usage.collapse") : t("usage.eventsCount", { n: summary.events.length })}
              </span>
            </button>
            {showLedger ? (
              <div style={{ marginTop: "0.75rem" }}>
                <UsageLedger
                  events={summary.events}
                  page={ledgerPage}
                  pageSize={LEDGER_PAGE}
                  onPageChange={setLedgerPage}
                  pageSlice={pageSlice}
                  emptyAction={
                    <div className="hb-wizard-actions">
                      <Link to="/app/studio">
                        <Button type="button" variant="ghost">
                          {t("nav.studio")}
                        </Button>
                      </Link>
                    </div>
                  }
                />
              </div>
            ) : null}
          </Card>
        </div>
      ) : (
        <>
          {!tenant ? (
            <p className="text-muted">{t("common.loading")}</p>
          ) : (
            <div className="hb-stack hb-usage-tenant">
              <div className="hb-usage-toolbar">
                <div className="hb-usage-filters__gran" role="group" aria-label={t("usage.granularity")}>
                  {(
                    [
                      ["day", "usage.day"],
                      ["month", "usage.monthUnit"],
                      ["year", "usage.year"],
                    ] as const
                  ).map(([id, labelKey]) => (
                    <button
                      key={id}
                      type="button"
                      className={`hb-tab ${granularity === id ? "is-active" : ""}`}
                      onClick={() => onGranularityChange(id)}
                    >
                      {t(labelKey)}
                    </button>
                  ))}
                </div>
                <div className="hb-usage-toolbar__dates">
                  <input
                    className="hb-input hb-usage-toolbar__date"
                    type="date"
                    aria-label={t("usage.from")}
                    value={fromDraft}
                    onChange={(e) => {
                      const v = e.target.value;
                      setFromDraft(v);
                      if (v) commitRange({ from: v });
                    }}
                  />
                  <span className="hb-usage-toolbar__dash" aria-hidden>
                    –
                  </span>
                  <input
                    className="hb-input hb-usage-toolbar__date"
                    type="date"
                    aria-label={t("usage.to")}
                    value={toDraft}
                    onChange={(e) => {
                      const v = e.target.value;
                      setToDraft(v);
                      if (v) commitRange({ to: v });
                    }}
                  />
                </div>
              </div>

              <Card>
                <UsageSeriesChart
                  series={tenant.series}
                  totals={{
                    purchased: tenant.purchased_credits,
                    consumed: tenant.consumed_credits,
                  }}
                />
                <div className="hb-usage-side-metrics" aria-label={t("usage.callCounts")}>
                  <span title="AI">
                    AI <strong>{tenant.ai_calls}</strong>
                  </span>
                  <span title="Search">
                    Search <strong>{tenant.search_calls}</strong>
                  </span>
                </div>
              </Card>

              <Card>
                {tenant.members.length === 0 ? (
                  <EmptyState title={t("usage.noMembers")} />
                ) : (
                  <div className="hb-stack">
                    <ul className="hb-usage-member-list">
                      {pagedMembers.map((row) => {
                        const usePct =
                          row.purchased_credits > 0
                            ? Math.min(
                                100,
                                Math.round((row.total_credits / row.purchased_credits) * 100),
                              )
                            : 0;
                        return (
                          <li key={row.uid} className="hb-usage-member-row">
                            <div
                              className="hb-usage-member-row__main"
                              title={`${row.email}\n${row.uid}`}
                            >
                              <strong>{row.display_name}</strong>
                              <div
                                className="hb-usage-member-bar"
                                title={`${row.total_credits} / ${row.purchased_credits}`}
                              >
                                <div className="hb-progress hb-progress--sm" aria-hidden>
                                  <div
                                    className={`hb-progress__bar hb-progress__bar--use${
                                      usePct >= 100 ? " is-danger" : usePct >= 70 ? " is-warn" : ""
                                    }`}
                                    style={{ width: `${usePct}%` }}
                                  />
                                </div>
                                <span className="hb-usage-member-bar__nums">
                                  <strong>{row.total_credits}</strong>
                                  <span className="text-muted">/{row.purchased_credits}</span>
                                </span>
                              </div>
                            </div>
                            <div className="hb-usage-member-row__actions">
                              {row.unlimited ? <Badge tone="brand">∞</Badge> : null}
                              <Select
                                label=""
                                aria-label={t("usage.planAria", { name: row.display_name })}
                                value={row.plan_id}
                                disabled={Boolean(busy)}
                                onChange={(e) =>
                                  void setMemberPlan(row.uid, e.target.value as PlanId)
                                }
                              >
                                {(Object.keys(PLANS) as PlanId[]).map((id) => (
                                  <option key={id} value={id}>
                                    {t("admin.users.planOption", {
                                      name: PLANS[id].name,
                                      credits: PLANS[id].monthly_credits,
                                    })}
                                  </option>
                                ))}
                              </Select>
                              <Button
                                type="button"
                                variant={row.unlimited ? "secondary" : "ghost"}
                                disabled={Boolean(busy)}
                                onClick={() => void toggleUnlimited(row.uid, !row.unlimited)}
                                title={t("usage.unlimitedTitle")}
                                aria-label={
                                  row.unlimited ? t("usage.setLimited") : t("usage.setUnlimited")
                                }
                              >
                                {row.unlimited ? t("usage.limitShort") : "∞"}
                              </Button>
                            </div>
                          </li>
                        );
                      })}
                    </ul>
                    <Pager
                      total={tenant.members.length}
                      page={memberPage}
                      pageSize={MEMBER_PAGE}
                      onPageChange={setMemberPage}
                    />
                  </div>
                )}
              </Card>
            </div>
          )}
        </>
      )}
    </>
  );
}
