"use client";

import { useMemo, useState } from "react";
import { Card, CardContent } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Input } from "@/components/ui/input";
import { EmptyState } from "@/components/ui/empty-state";
import { Kpi, KpiStrip } from "@/components/ui/kpi";
import { useAlertConfirm } from "@/components/ui/alert-dialog";
import { useToast } from "@/components/ui/toast";
import { useLocalStorage } from "@/lib/hooks/use-local-storage";
import { ALL_ORGANIZATIONS, getOrganizationBySlug } from "@/lib/sag/entities";
import { formatCurrency } from "@/lib/utils";
import { lookupCancellation } from "@/lib/finance/cancel-urls";
import {
  amountToMonthly,
  monthlyToAmount,
  SUBSCRIPTIONS_STORAGE_KEY,
  type Cadence,
  type StoredSubscription,
  saveSubscription as persistSubscription,
  deleteSubscription as persistDelete,
} from "@/lib/finance/subscriptions-store";
import { logActivity } from "@/lib/activity/log";

/**
 * Manual subscription manager.
 *
 * Companion to `subscription-detector.tsx` (which clusters Plaid history).
 * This is the user-curated store — anything they want in the cash forecast
 * before, or instead of, what Plaid detects. Reads / writes to
 * `sag.subscriptions.v1` via `subscriptions-store.ts`.
 *
 * Layout:
 *   - KPI strip (count / monthly / annual / entities tagged)
 *   - filter bar (cadence + entity)
 *   - inline "Add subscription" form (toggled, not modal)
 *   - sortable table (by monthly $ desc)
 *   - delete uses `useAlertConfirm` for a non-destructive ack flow
 *   - empty state via `<EmptyState>` when the store is empty
 *   - cancel deep-link looked up from F2's `cancel-urls.ts` when available
 */

// ──────────────────────────────────────────────────────────────────────────
// Constants
// ──────────────────────────────────────────────────────────────────────────

const CADENCES: Cadence[] = [
  "weekly",
  "biweekly",
  "monthly",
  "quarterly",
  "annual",
  "irregular",
];

const CADENCE_LABEL: Record<Cadence, string> = {
  weekly: "Weekly",
  biweekly: "Biweekly",
  monthly: "Monthly",
  quarterly: "Quarterly",
  annual: "Annual",
  irregular: "Irregular",
};

type CadenceFilter = "all" | Cadence;
type EntityFilter = "all" | "__untagged__" | string;

interface UiState {
  cadenceFilter: CadenceFilter;
  entityFilter: EntityFilter;
}

const DEFAULT_UI_STATE: UiState = {
  cadenceFilter: "all",
  entityFilter: "all",
};

// ──────────────────────────────────────────────────────────────────────────
// Component
// ──────────────────────────────────────────────────────────────────────────

export function SubscriptionManager() {
  // Subscriptions persisted by `subscriptions-store.ts`. Using
  // `useLocalStorage` here gives us the reactive read; writes still go
  // through the helper so the cash-forecast / detector see a consistent
  // record shape.
  const [subs, setSubs] = useLocalStorage<StoredSubscription[]>(
    SUBSCRIPTIONS_STORAGE_KEY,
    []
  );
  const [ui, setUi] = useLocalStorage<UiState>(
    "sag.subscriptions.manager.ui",
    DEFAULT_UI_STATE
  );
  const [adding, setAdding] = useState(false);
  const [editingId, setEditingId] = useState<string | null>(null);
  const { toast } = useToast();
  const { confirm: confirmAlert, AlertConfirmPortal } = useAlertConfirm();

  // ── Filtering & sorting ──────────────────────────────────────────────
  const visible = useMemo(() => {
    const filtered = subs.filter((s) => {
      if (ui.cadenceFilter !== "all" && s.cadence !== ui.cadenceFilter) return false;
      if (ui.entityFilter !== "all") {
        if (ui.entityFilter === "__untagged__") {
          if (s.entitySlug) return false;
        } else if (s.entitySlug !== ui.entityFilter) return false;
      }
      return true;
    });
    return [...filtered].sort((a, b) => b.monthlyAmount - a.monthlyAmount);
  }, [subs, ui]);

  // Only show entities that have at least one tracked sub in the entity filter.
  const entityOptions = useMemo(() => {
    const slugs = new Set<string>();
    for (const s of subs) {
      if (s.entitySlug) slugs.add(s.entitySlug);
    }
    return Array.from(slugs)
      .map((slug) => ALL_ORGANIZATIONS.find((o) => o.slug === slug))
      .filter((o): o is NonNullable<typeof o> => !!o)
      .sort((a, b) => a.name.localeCompare(b.name));
  }, [subs]);

  // ── KPIs ─────────────────────────────────────────────────────────────
  const kpis = useMemo(() => {
    let monthly = 0;
    const taggedEntities = new Set<string>();
    for (const s of visible) {
      monthly += s.monthlyAmount;
      if (s.entitySlug) taggedEntities.add(s.entitySlug);
    }
    return {
      count: visible.length,
      monthly,
      annual: monthly * 12,
      entityCount: taggedEntities.size,
    };
  }, [visible]);

  // ── Mutations ────────────────────────────────────────────────────────
  function applySave(
    input: Parameters<typeof persistSubscription>[0]
  ): StoredSubscription {
    const saved = persistSubscription(input);
    setSubs((prev) => {
      const idx = prev.findIndex((s) => s.id === saved.id);
      if (idx >= 0) {
        const next = [...prev];
        next[idx] = saved;
        return next;
      }
      return [saved, ...prev];
    });
    return saved;
  }

  function handleCreate(form: FormValues) {
    const monthly = amountToMonthly(form.perPeriodAmount, form.cadence);
    const saved = applySave({
      vendor: form.vendor,
      monthlyAmount: monthly,
      cadence: form.cadence,
      entitySlug: form.entitySlug || undefined,
      paymentMethod: form.paymentMethod || undefined,
      nextRenewalDate: form.nextRenewalDate || undefined,
      notes: form.notes || undefined,
    });
    setAdding(false);
    toast({
      title: "Subscription added",
      description: `${form.vendor} · ${formatCurrency(monthly)}/mo`,
      variant: "success",
    });
    try {
      const fromDetector = Boolean(saved.confirmedFromDetected);
      logActivity({
        source: "subscriptions",
        verb: fromDetector ? "confirmed" : "created",
        title: fromDetector
          ? `Confirmed ${form.vendor} from detector`
          : `Added subscription ${form.vendor}`,
        entitySlug: saved.entitySlug,
        amount: monthly,
        href: "/app/finance/subscriptions",
        meta: { cadence: form.cadence, monthlyAmount: monthly },
      });
    } catch {
      // fire-and-forget
    }
  }

  function handleUpdate(id: string, form: FormValues) {
    const monthly = amountToMonthly(form.perPeriodAmount, form.cadence);
    const saved = applySave({
      id,
      vendor: form.vendor,
      monthlyAmount: monthly,
      cadence: form.cadence,
      entitySlug: form.entitySlug || undefined,
      paymentMethod: form.paymentMethod || undefined,
      nextRenewalDate: form.nextRenewalDate || undefined,
      notes: form.notes || undefined,
    });
    setEditingId(null);
    toast({
      title: "Subscription updated",
      description: `${form.vendor} · ${formatCurrency(monthly)}/mo`,
      variant: "success",
    });
    try {
      logActivity({
        source: "subscriptions",
        verb: "updated",
        title: `Updated subscription ${form.vendor}`,
        entitySlug: saved.entitySlug,
        amount: monthly,
        href: "/app/finance/subscriptions",
        meta: { cadence: form.cadence, monthlyAmount: monthly },
      });
    } catch {
      // fire-and-forget
    }
  }

  async function handleDelete(sub: StoredSubscription) {
    const ok = await confirmAlert({
      title: `Delete ${sub.vendor}?`,
      description:
        "This removes the subscription from your cash-forecast burn. The detector will resurface it from your Plaid history if it's still recurring.",
      actionLabel: "Delete",
      destructive: true,
    });
    if (!ok) return;
    persistDelete(sub.id);
    setSubs((prev) => prev.filter((s) => s.id !== sub.id));
    toast({
      title: "Subscription deleted",
      description: sub.vendor,
      variant: "success",
    });
    try {
      logActivity({
        source: "subscriptions",
        verb: "deleted",
        title: `Deleted subscription ${sub.vendor}`,
        entitySlug: sub.entitySlug,
        amount: sub.monthlyAmount,
        href: "/app/finance/subscriptions",
      });
    } catch {
      // fire-and-forget
    }
  }

  const hasAny = subs.length > 0;

  // ────────────────────────────────────────────────────────────────────────
  // Render
  // ────────────────────────────────────────────────────────────────────────

  return (
    <>
      <div className="space-y-6 max-w-6xl">
        {/* Filter / action bar */}
        <Card>
          <CardContent className="p-5">
            <div className="flex flex-wrap items-end gap-4">
              <div className="flex flex-col gap-1">
                <label className="section-label">Cadence</label>
                <select
                  value={ui.cadenceFilter}
                  onChange={(e) =>
                    setUi({
                      ...ui,
                      cadenceFilter: e.target.value as CadenceFilter,
                    })
                  }
                  className="h-9 rounded-md border border-input bg-background px-3 text-sm"
                >
                  <option value="all">All cadences</option>
                  {CADENCES.map((c) => (
                    <option key={c} value={c}>
                      {CADENCE_LABEL[c]}
                    </option>
                  ))}
                </select>
              </div>

              <div className="flex flex-col gap-1">
                <label className="section-label">Entity</label>
                <select
                  value={ui.entityFilter}
                  onChange={(e) => setUi({ ...ui, entityFilter: e.target.value })}
                  className="h-9 rounded-md border border-input bg-background px-3 text-sm min-w-[14rem]"
                >
                  <option value="all">All entities</option>
                  <option value="__untagged__">Untagged</option>
                  {entityOptions.map((o) => (
                    <option key={o.slug} value={o.slug}>
                      {o.emoji} {o.name}
                    </option>
                  ))}
                </select>
              </div>

              <div className="ml-auto">
                <Button
                  size="sm"
                  variant={adding ? "brand" : "outline"}
                  onClick={() => {
                    setEditingId(null);
                    setAdding((v) => !v);
                  }}
                >
                  {adding ? "Cancel" : "+ Add subscription"}
                </Button>
              </div>
            </div>

            <div className="mt-3 text-[11px] text-muted-foreground">
              Tracked subscriptions persist at{" "}
              <code className="text-foreground">{SUBSCRIPTIONS_STORAGE_KEY}</code> and
              feed the cash-forecast burn alongside the F1 detector.
            </div>
          </CardContent>
        </Card>

        {/* KPI strip */}
        <KpiStrip cols={4}>
          <Kpi label="Tracked subscriptions" value={String(kpis.count)} />
          <Kpi label="Monthly burn" value={formatCurrency(kpis.monthly)} />
          <Kpi label="Annual projection" value={formatCurrency(kpis.annual)} />
          <Kpi
            label="Entities tagged"
            value={String(kpis.entityCount)}
            hint={kpis.entityCount === 0 ? "Tag entities to feed the forecast" : undefined}
          />
        </KpiStrip>

        {/* Inline add form */}
        {adding && (
          <SubscriptionForm
            mode="create"
            onSubmit={(form) => handleCreate(form)}
            onCancel={() => setAdding(false)}
          />
        )}

        {/* Table */}
        <Card>
          <CardContent className="p-5">
            <div className="flex items-center justify-between mb-3">
              <div>
                <h2 className="text-sm font-semibold">Tracked subscriptions</h2>
                <p className="text-[11px] text-muted-foreground">
                  Sorted by monthly burn. Edit to change cadence, retag the entity,
                  or update the renewal date.
                </p>
              </div>
              <Badge variant="outline" className="text-[10px]">
                {visible.length} of {subs.length}
              </Badge>
            </div>

            {!hasAny ? (
              <EmptyState
                icon="📝"
                size="compact"
                title="No subscriptions tracked yet"
                description="Add the recurring vendors you pay on a personal card, ad-hoc invoice, or any account not yet linked to Plaid. Your cash forecast will pull from here in real time."
                action={
                  <Button variant="brand" size="sm" onClick={() => setAdding(true)}>
                    + Add your first subscription
                  </Button>
                }
              />
            ) : visible.length === 0 ? (
              <p className="py-10 text-center text-xs text-muted-foreground">
                Subscriptions exist but the current filters hide them. Adjust the
                cadence or entity filter above.
              </p>
            ) : (
              <div className="overflow-x-auto">
                <table className="w-full min-w-[720px] text-xs">
                  <thead className="section-label border-b">
                    <tr>
                      <th className="py-2 pr-3 text-left font-medium">Vendor</th>
                      <th className="py-2 px-2 text-left font-medium">Entity</th>
                      <th className="py-2 px-2 text-left font-medium">Cadence</th>
                      <th className="py-2 px-2 text-right font-medium">Monthly</th>
                      <th className="py-2 px-2 text-right font-medium">Annual</th>
                      <th className="py-2 px-2 text-left font-medium">Payment</th>
                      <th className="py-2 px-2 text-left font-medium">Next renewal</th>
                      <th className="py-2 px-2 text-left font-medium">Cancel</th>
                      <th className="py-2 pl-2 text-right font-medium">Actions</th>
                    </tr>
                  </thead>
                  <tbody>
                    {visible.map((sub) =>
                      editingId === sub.id ? (
                        <tr key={sub.id} className="border-b last:border-0">
                          <td colSpan={9} className="py-3 bg-muted/30">
                            <SubscriptionForm
                              mode="edit"
                              initial={sub}
                              onSubmit={(form) => handleUpdate(sub.id, form)}
                              onCancel={() => setEditingId(null)}
                            />
                          </td>
                        </tr>
                      ) : (
                        <SubscriptionRow
                          key={sub.id}
                          sub={sub}
                          onEdit={() => {
                            setAdding(false);
                            setEditingId(sub.id);
                          }}
                          onDelete={() => handleDelete(sub)}
                        />
                      )
                    )}
                  </tbody>
                </table>
              </div>
            )}
          </CardContent>
        </Card>

        {/* Footnote */}
        <Card className="border-dashed">
          <CardContent className="p-4 text-[11px] text-muted-foreground space-y-1.5">
            <div>
              Monthly amount is the canonical figure. The cadence picker is a
              convenience — picking <em>Annual</em> with $120 stores $10/mo. The
              cash forecast reads <code className="text-foreground">monthlyAmount</code>{" "}
              directly and slices it across 30 days.
            </div>
            <div>
              Confirmations from the <strong>Detected</strong> tab land here with{" "}
              <code className="text-foreground">confirmedFromDetected</code> set, which
              filters that cluster out of the detector on the next render.
            </div>
          </CardContent>
        </Card>
      </div>
      <AlertConfirmPortal />
    </>
  );
}

// ──────────────────────────────────────────────────────────────────────────
// Row
// ──────────────────────────────────────────────────────────────────────────

function SubscriptionRow({
  sub,
  onEdit,
  onDelete,
}: {
  sub: StoredSubscription;
  onEdit: () => void;
  onDelete: () => void;
}) {
  const entity = sub.entitySlug ? getOrganizationBySlug(sub.entitySlug) : undefined;
  const guide = lookupCancellation(sub.vendor);
  const annual = sub.monthlyAmount * 12;

  return (
    <tr className="border-b last:border-0 align-middle">
      <td className="py-2 pr-3">
        <div className="font-medium truncate max-w-[14rem]" title={sub.vendor}>
          {sub.vendor}
        </div>
        {sub.notes && (
          <div
            className="text-[10px] text-muted-foreground truncate max-w-[14rem]"
            title={sub.notes}
          >
            {sub.notes}
          </div>
        )}
        {sub.confirmedFromDetected && (
          <div className="mt-0.5">
            <Badge variant="info" className="text-[9px] px-1 py-0">
              from detector
            </Badge>
          </div>
        )}
      </td>
      <td className="py-2 px-2">
        {entity ? (
          <span className="truncate inline-block max-w-[10rem]" title={entity.name}>
            {entity.emoji ?? "🏢"} {entity.name}
          </span>
        ) : (
          <span className="text-muted-foreground">—</span>
        )}
      </td>
      <td className="py-2 px-2">
        <CadenceBadge cadence={sub.cadence} />
      </td>
      <td className="py-2 px-2 text-right font-mono tabular-nums font-semibold">
        {formatCurrency(sub.monthlyAmount)}
      </td>
      <td className="py-2 px-2 text-right font-mono tabular-nums">
        {formatCurrency(annual)}
      </td>
      <td className="py-2 px-2">
        {sub.paymentMethod ? (
          <span className="truncate inline-block max-w-[8rem]" title={sub.paymentMethod}>
            {sub.paymentMethod}
          </span>
        ) : (
          <span className="text-muted-foreground">—</span>
        )}
      </td>
      <td className="py-2 px-2 font-mono text-[11px] tabular-nums whitespace-nowrap">
        {sub.nextRenewalDate ?? <span className="text-muted-foreground">—</span>}
      </td>
      <td className="py-2 px-2">
        {guide ? (
          <a
            href={guide.cancellationUrl}
            target="_blank"
            rel="noopener noreferrer"
            className="text-primary underline-offset-2 hover:underline"
            title={guide.notes}
          >
            {guide.vendor}
          </a>
        ) : (
          <span className="text-muted-foreground">No guide</span>
        )}
      </td>
      <td className="py-2 pl-2 text-right">
        <div className="inline-flex items-center gap-1 justify-end">
          <Button
            variant="ghost"
            size="sm"
            onClick={onEdit}
            className="h-7 px-2 text-[10px]"
          >
            Edit
          </Button>
          <Button
            variant="ghost"
            size="sm"
            onClick={onDelete}
            className="h-7 px-2 text-[10px] text-destructive hover:text-destructive"
          >
            Delete
          </Button>
        </div>
      </td>
    </tr>
  );
}

function CadenceBadge({ cadence }: { cadence: Cadence }) {
  const variant: React.ComponentProps<typeof Badge>["variant"] =
    cadence === "irregular"
      ? "warning"
      : cadence === "annual"
        ? "info"
        : "secondary";
  return (
    <Badge variant={variant} className="text-[10px]">
      {CADENCE_LABEL[cadence]}
    </Badge>
  );
}

// ──────────────────────────────────────────────────────────────────────────
// Inline form (add + edit share the same component)
// ──────────────────────────────────────────────────────────────────────────

interface FormValues {
  vendor: string;
  perPeriodAmount: number;
  cadence: Cadence;
  entitySlug: string;
  paymentMethod: string;
  nextRenewalDate: string;
  notes: string;
}

function SubscriptionForm({
  mode,
  initial,
  onSubmit,
  onCancel,
}: {
  mode: "create" | "edit";
  initial?: StoredSubscription;
  onSubmit: (values: FormValues) => void;
  onCancel: () => void;
}) {
  const [vendor, setVendor] = useState(initial?.vendor ?? "");
  const initialCadence: Cadence = initial?.cadence ?? "monthly";
  const [cadence, setCadence] = useState<Cadence>(initialCadence);
  // The form input is the "per-period charge" — what they actually pay each
  // hit — but the store normalizes to monthly. On edit we invert to fill in.
  const [perPeriodAmount, setPerPeriodAmount] = useState<string>(
    initial ? String(monthlyToAmount(initial.monthlyAmount, initialCadence)) : ""
  );
  const [entitySlug, setEntitySlug] = useState(initial?.entitySlug ?? "");
  const [paymentMethod, setPaymentMethod] = useState(initial?.paymentMethod ?? "");
  const [nextRenewalDate, setNextRenewalDate] = useState(
    initial?.nextRenewalDate ?? ""
  );
  const [notes, setNotes] = useState(initial?.notes ?? "");

  function handleCadenceChange(next: Cadence) {
    // Re-express the typed amount under the new cadence so the user sees
    // their effective monthly burn change in real time without losing the
    // figure they typed.
    setCadence(next);
  }

  const parsedAmount = parseFloat(perPeriodAmount);
  const monthlyPreview = isFinite(parsedAmount)
    ? amountToMonthly(parsedAmount, cadence)
    : 0;

  function submit(e: React.FormEvent) {
    e.preventDefault();
    const n = parseFloat(perPeriodAmount);
    if (!vendor.trim() || !isFinite(n) || n < 0) return;
    onSubmit({
      vendor: vendor.trim(),
      perPeriodAmount: n,
      cadence,
      entitySlug: entitySlug.trim(),
      paymentMethod: paymentMethod.trim(),
      nextRenewalDate: nextRenewalDate.trim(),
      notes: notes.trim(),
    });
  }

  return (
    <Card>
      <CardContent className="p-6">
        <form onSubmit={submit} className="grid gap-3 md:grid-cols-2">
          <Field label="Vendor">
            <Input
              value={vendor}
              onChange={(e) => setVendor(e.target.value)}
              placeholder="e.g. Anthropic"
              required
              autoFocus
            />
          </Field>
          <Field label={`Amount per ${CADENCE_LABEL[cadence].toLowerCase()}`}>
            <Input
              type="number"
              step="0.01"
              min="0"
              value={perPeriodAmount}
              onChange={(e) => setPerPeriodAmount(e.target.value)}
              placeholder="0.00"
              required
            />
            {parsedAmount > 0 && cadence !== "monthly" && (
              <p className="mt-1 text-[10px] text-muted-foreground">
                ≈ {formatCurrency(monthlyPreview)} / month stored
              </p>
            )}
          </Field>
          <Field label="Cadence">
            <select
              value={cadence}
              onChange={(e) => handleCadenceChange(e.target.value as Cadence)}
              className="w-full h-10 rounded-md border border-input bg-background px-3 text-sm"
            >
              {CADENCES.map((c) => (
                <option key={c} value={c}>
                  {CADENCE_LABEL[c]}
                </option>
              ))}
            </select>
          </Field>
          <Field label="Entity">
            <select
              value={entitySlug}
              onChange={(e) => setEntitySlug(e.target.value)}
              className="w-full h-10 rounded-md border border-input bg-background px-3 text-sm"
            >
              <option value="">— Untagged —</option>
              {ALL_ORGANIZATIONS.map((o) => (
                <option key={o.slug} value={o.slug}>
                  {o.emoji} {o.name}
                </option>
              ))}
            </select>
          </Field>
          <Field label="Payment method (optional)">
            <Input
              value={paymentMethod}
              onChange={(e) => setPaymentMethod(e.target.value)}
              placeholder='e.g. "Truist 9472" or "AmEx Plat"'
            />
          </Field>
          <Field label="Next renewal (optional)">
            <Input
              type="date"
              value={nextRenewalDate}
              onChange={(e) => setNextRenewalDate(e.target.value)}
            />
          </Field>
          <Field label="Notes" className="md:col-span-2">
            <textarea
              value={notes}
              onChange={(e) => setNotes(e.target.value)}
              className="w-full rounded-md border border-input bg-background p-2 text-sm"
              rows={2}
              placeholder="e.g. Annual prepay; renews from credit"
            />
          </Field>
          <div className="md:col-span-2 flex items-center justify-end gap-2">
            <Button variant="ghost" size="sm" onClick={onCancel} type="button">
              Cancel
            </Button>
            <Button variant="brand" size="sm" type="submit">
              {mode === "create" ? "Add subscription" : "Save changes"}
            </Button>
          </div>
        </form>
      </CardContent>
    </Card>
  );
}

function Field({
  label,
  children,
  className,
}: {
  label: string;
  children: React.ReactNode;
  className?: string;
}) {
  return (
    <div className={className}>
      <label className="text-xs text-muted-foreground">{label}</label>
      <div className="mt-1">{children}</div>
    </div>
  );
}
