"use client";

import { useTranslations } from "next-intl";
import { useEffect, useState, useCallback } from "react";
import { BudgetEditableCard } from "@/components/dashboard/budget-editable-card";

interface DailyUsage {
  date: string;
  inputTokens: number;
  outputTokens: number;
  spend: number;
}

interface UsageData {
  month: string;
  currentPeriod: {
    inputTokens: number;
    outputTokens: number;
    totalSpend: number;
    requestCount: number;
  };
  budget: {
    maxBudget: number | null;
    spend: number;
    remaining: number | null;
    /**
     * Feature 7: budget reset cadence as stored on LiteLLM.
     * Strings: "30d" / "1mo" / "1y" / null (no reset). UI maps these
     * to user-friendly labels.
     */
    budgetDuration: string | null;
  };
  rateLimits: { rpm: number | null; tpm: number | null };
  dailyUsage: DailyUsage[];
}

function fmt(n: number): string {
  if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`;
  if (n >= 1_000) return `${(n / 1_000).toFixed(0)}k`;
  return n.toString();
}

/**
 * Format a numeric amount as CHF.
 *
 * Note on currency labelling: LiteLLM stores raw cost numbers it
 * receives from upstream (OpenAI/Anthropic), which originate as USD.
 * The PieCed pricing config (Slice 5) converts those numbers to
 * CHF before LiteLLM persists them, so the values flowing through
 * here are already CHF amounts. We label them as such in the UI;
 * "USD" or "$" anywhere in the customer-facing experience would
 * be misleading.
 *
 * Precision is adaptive:
 *   - Amounts ≥ 1 CHF: 2 decimals (typical money formatting).
 *   - Smaller amounts:  4 decimals — per-request inference costs are
 *                       routinely sub-rappen, and rounding to 2dp
 *                       would render CHF 0.0042 as "CHF 0.00",
 *                       which obscures real costs from customers
 *                       looking at the daily breakdown.
 *
 * This is a customer-facing display helper; for storage and
 * comparisons keep using the raw number.
 */
function chf(n: number): string {
  const decimals = Math.abs(n) >= 1 ? 2 : 4;
  return `CHF ${n.toFixed(decimals)}`;
}

function getCurrentMonth(): string {
  const now = new Date();
  return `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}`;
}

function shiftMonth(month: string, delta: number): string {
  const [y, m] = month.split("-").map(Number);
  const d = new Date(y, m - 1 + delta, 1);
  return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}`;
}

function formatMonth(month: string, locale: string): string {
  const [y, m] = month.split("-").map(Number);
  return new Date(y, m - 1).toLocaleDateString(locale, { year: "numeric", month: "long" });
}

function UsageChart({ data }: { data: DailyUsage[] }) {
  if (!data.length) return null;
  const maxTokens = Math.max(...data.map((d) => d.inputTokens + d.outputTokens), 1);
  const barW = Math.max(4, Math.floor(600 / data.length) - 2);
  const h = 120;

  return (
    <div className="overflow-x-auto">
      <svg
        viewBox={`0 0 ${Math.max(data.length * (barW + 2), 600)} ${h + 24}`}
        className="w-full h-36"
        preserveAspectRatio="xMinYMid meet"
      >
        {data.map((d, i) => {
          const total = d.inputTokens + d.outputTokens;
          const totalH = (total / maxTokens) * h;
          const inputH = (d.inputTokens / maxTokens) * h;
          const x = i * (barW + 2);
          return (
            <g key={d.date}>
              <title>{d.date}: {fmt(d.inputTokens)} in / {fmt(d.outputTokens)} out — {chf(d.spend)}</title>
              <rect x={x} y={h - totalH} width={barW} height={totalH - inputH} rx={1} fill="var(--color-accent)" opacity={0.3} />
              <rect x={x} y={h - inputH} width={barW} height={inputH} rx={1} fill="var(--color-accent)" opacity={0.7} />
              {i % 7 === 0 && (
                <text x={x + barW / 2} y={h + 14} textAnchor="middle" fill="var(--color-text-muted)" fontSize="8">{d.date.slice(8)}</text>
              )}
            </g>
          );
        })}
      </svg>
      <div className="flex items-center gap-4 text-xs text-text-muted mt-1">
        <span className="flex items-center gap-1">
          <span className="inline-block h-2 w-2 rounded-sm bg-accent opacity-70" /> Input
        </span>
        <span className="flex items-center gap-1">
          <span className="inline-block h-2 w-2 rounded-sm bg-accent opacity-30" /> Output
        </span>
      </div>
    </div>
  );
}

/**
 * Usage display widget.
 *
 * Pass `tenant=<name>` for the canonical path — works for both
 * customers and admins, the API resolves team+alias from the tenant
 * CR's status. The visibility check on the API ensures users can't
 * query tenants they shouldn't see.
 *
 * `teamId`/`keyAlias` remain available as a platform-admin escape
 * hatch for cross-org debugging, but the tenant-detail and dashboard
 * paths should always use `tenant`.
 *
 * Bug 19 fix: previous version omitted both props for customer
 * sessions, expecting the API to "figure it out". The API's fallback
 * was "first visible tenant", which meant siblings in the same org
 * showed identical numbers regardless of which detail page was open.
 * Now the page passes the tenant name explicitly; no fallback exists.
 */
export function UsageDisplay({
  tenant,
  teamId,
  keyAlias,
  canEditBudget = false,
}: {
  tenant?: string | null;
  teamId?: string | null;
  keyAlias?: string | null;
  /**
   * Feature 7: when true, the Budget StatCard becomes clickable and
   * opens the budget editor. Off by default — owners and platform
   * admins get it on; `user` role customers see the budget read-only.
   * Server component decides this via canMutate(user).
   */
  canEditBudget?: boolean;
}) {
  const t = useTranslations("usage");
  const [month, setMonth] = useState(getCurrentMonth);
  const [data, setData] = useState<UsageData | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  const isCurrentMonth = month === getCurrentMonth();

  const fetchUsage = useCallback(() => {
    setLoading(true);
    setError(null);

    const params = new URLSearchParams({ month });
    if (tenant) {
      params.set("tenant", tenant);
    } else if (teamId) {
      // Admin escape hatch — only honoured by the API when the
      // viewer is platform-role.
      params.set("teamId", teamId);
      if (keyAlias) params.set("keyAlias", keyAlias);
    }

    fetch(`/api/usage?${params}`)
      .then((res) => { if (!res.ok) throw new Error(`${res.status}`); return res.json(); })
      .then(setData)
      .catch((e) => setError(e.message))
      .finally(() => setLoading(false));
  }, [tenant, teamId, keyAlias, month]);

  useEffect(() => { fetchUsage(); }, [fetchUsage]);

  return (
    <div className="space-y-4">
      {/* Month selector */}
      <div className="flex items-center justify-between">
        <button
          onClick={() => setMonth((m) => shiftMonth(m, -1))}
          className="rounded-md px-2 py-1 text-xs text-text-secondary hover:text-text-primary hover:bg-surface-2 transition-colors cursor-pointer"
        >
          ←
        </button>
        <span className="font-display text-sm font-medium text-text-primary">
          {formatMonth(month, "en")}
        </span>
        <button
          onClick={() => setMonth((m) => shiftMonth(m, 1))}
          disabled={isCurrentMonth}
          className="rounded-md px-2 py-1 text-xs text-text-secondary hover:text-text-primary hover:bg-surface-2 transition-colors cursor-pointer disabled:opacity-30 disabled:cursor-not-allowed"
        >
          →
        </button>
      </div>

      {loading ? (
        <div className="bg-surface-1 border border-border rounded-xl p-6 animate-pulse">
          <div className="h-4 w-32 bg-surface-3 rounded mb-4" />
          <div className="h-36 bg-surface-2 rounded" />
        </div>
      ) : error || !data ? (
        <div className="bg-surface-1 border border-border rounded-xl p-6">
          <p className="text-sm text-text-secondary">{error || t("noData")}</p>
        </div>
      ) : (
        <>
          <div className="grid grid-cols-2 md:grid-cols-4 gap-3">
            <StatCard label={t("inputTokens")} value={fmt(data.currentPeriod.inputTokens)} />
            <StatCard label={t("outputTokens")} value={fmt(data.currentPeriod.outputTokens)} />
            <StatCard label={t("totalSpend")} value={chf(data.currentPeriod.totalSpend)} accent />
            {canEditBudget && tenant ? (
              <BudgetEditableCard
                tenantName={tenant}
                maxBudget={data.budget.maxBudget}
                remaining={data.budget.remaining}
                budgetDuration={data.budget.budgetDuration}
                onSaved={fetchUsage}
              />
            ) : (
              <StatCard
                label={t("budget")}
                value={
                  data.budget.remaining !== null
                    ? chf(data.budget.remaining)
                    : t("noLimit")
                }
              />
            )}
          </div>

          <div className="bg-surface-1 border border-border rounded-xl p-5">
            <div className="flex items-center justify-between mb-3">
              <h3 className="text-xs font-semibold uppercase tracking-wider text-text-muted">
                {t("dailyBreakdown")}
              </h3>
              <span className="text-xs text-text-muted tabular-nums">
                {data.currentPeriod.requestCount} {t("requests")}
              </span>
            </div>
            <UsageChart data={data.dailyUsage} />
          </div>
        </>
      )}
    </div>
  );
}

function StatCard({ label, value, accent }: { label: string; value: string; accent?: boolean }) {
  return (
    <div className="bg-surface-1 border border-border rounded-xl p-4">
      <div className="text-xs text-text-muted mb-1">{label}</div>
      <div className={`font-display text-lg font-semibold tabular-nums ${accent ? "text-accent" : "text-text-primary"}`}>{value}</div>
    </div>
  );
}
