"use client";

import { useCallback, useEffect, useState } from "react";
import { usePlaidLink } from "react-plaid-link";
import { Card, CardContent } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { useAlertConfirm } from "@/components/ui/alert-dialog";
import { useLocalStorage } from "@/lib/hooks/use-local-storage";
import { ALL_ORGANIZATIONS } from "@/lib/sag/entities";
import { formatCurrency } from "@/lib/utils";

interface ConnectedAccount {
  accountId: string;
  name: string;
  officialName?: string;
  type?: string;
  subtype?: string;
  mask?: string;
  balance?: number | null;
  currency?: string | null;
  institution?: string;
  itemId: string;
  entitySlug?: string;
  connectedAt: string;
}

export function PlaidConnect() {
  const [accounts, setAccounts] = useLocalStorage<ConnectedAccount[]>("sag.plaid.accounts", []);
  const [accessTokens, setAccessTokens] = useLocalStorage<Record<string, string>>("sag.plaid.accessTokens", {});
  const [linkToken, setLinkToken] = useState<string | null>(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string>("");
  const { confirm: confirmAlert, AlertConfirmPortal } = useAlertConfirm();

  const fetchLinkToken = useCallback(async () => {
    setLoading(true);
    setError("");
    try {
      const resp = await fetch("/api/plaid/link-token", {
        method: "POST",
        headers: { "content-type": "application/json" },
        body: JSON.stringify({}),
      });
      const data = await resp.json();
      if (!resp.ok) throw new Error(data.error || "Failed");
      setLinkToken(data.linkToken);
    } catch (e) {
      setError(e instanceof Error ? e.message : "Unknown error");
    } finally {
      setLoading(false);
    }
  }, []);

  const onSuccess = useCallback(
    async (publicToken: string) => {
      setLoading(true);
      try {
        const resp = await fetch("/api/plaid/exchange", {
          method: "POST",
          headers: { "content-type": "application/json" },
          body: JSON.stringify({ publicToken }),
        });
        const data = await resp.json();
        if (!resp.ok) throw new Error(data.error || "Failed");
        const newAccounts: ConnectedAccount[] = data.accounts.map((a: ConnectedAccount) => ({
          ...a,
          itemId: data.itemId,
          institution: data.institution,
          connectedAt: new Date().toISOString(),
        }));
        setAccounts([...accounts, ...newAccounts]);
        if (data.accessToken && data.itemId) {
          setAccessTokens({ ...accessTokens, [data.itemId]: data.accessToken });
        }
        setLinkToken(null);
      } catch (e) {
        setError(e instanceof Error ? e.message : "Exchange failed");
      } finally {
        setLoading(false);
      }
    },
    [accounts, accessTokens, setAccounts, setAccessTokens]
  );

  const { open, ready } = usePlaidLink({
    token: linkToken,
    onSuccess: (public_token) => onSuccess(public_token),
    onExit: () => setLinkToken(null),
  });

  useEffect(() => {
    if (linkToken && ready) open();
  }, [linkToken, ready, open]);

  function setEntityForAccount(accountId: string, entitySlug: string) {
    setAccounts(accounts.map((a) => (a.accountId === accountId ? { ...a, entitySlug } : a)));
  }

  async function disconnect(accountId: string) {
    const ok = await confirmAlert({
      title: "Remove this connected account?",
      description: "This permanently removes the record. Cannot be undone.",
      actionLabel: "Remove",
      destructive: true,
    });
    if (!ok) return;
    setAccounts(accounts.filter((a) => a.accountId !== accountId));
  }

  const totalBalance = accounts.reduce((a, x) => a + (x.balance ?? 0), 0);

  return (
    <>
    <div className="space-y-6">
      <Card>
        <CardContent className="p-6 flex items-center justify-between flex-wrap gap-3">
          <div>
            <div className="flex items-center gap-2 mb-1">
              <Badge variant="info">Plaid</Badge>
              {accounts.length > 0 ? (
                <span className="text-xs text-muted-foreground">
                  {accounts.length} accounts · {formatCurrency(totalBalance)} total
                </span>
              ) : (
                <span className="text-xs text-muted-foreground">No accounts yet</span>
              )}
            </div>
            <h2 className="text-lg font-semibold">Connect a bank account</h2>
            <p className="text-sm text-muted-foreground mt-1 max-w-2xl">
              Connect Truist (or any Plaid-supported institution) to pull balances and transactions per entity. Sandbox supported for testing — switch <code className="text-xs">PLAID_ENV</code> in <code className="text-xs">.env.local</code>.
            </p>
          </div>
          <Button
            variant="brand"
            disabled={loading}
            onClick={fetchLinkToken}
          >
            {loading ? "Opening..." : "+ Connect bank"}
          </Button>
        </CardContent>
      </Card>

      {error && (
        <Card>
          <CardContent className="p-4 text-sm text-destructive">
            {error}
          </CardContent>
        </Card>
      )}

      {accounts.length > 0 && (
        <Card>
          <CardContent className="p-0">
            <div className="overflow-x-auto">
              <table className="w-full text-sm">
                <thead className="border-b bg-muted/40">
                  <tr>
                    <th className="text-left p-3 font-medium">Account</th>
                    <th className="text-left p-3 font-medium">Type</th>
                    <th className="text-right p-3 font-medium">Balance</th>
                    <th className="text-left p-3 font-medium">Entity</th>
                    <th className="p-3"></th>
                  </tr>
                </thead>
                <tbody>
                  {accounts.map((a) => (
                    <tr key={a.accountId} className="border-b last:border-b-0 hover:bg-muted/20">
                      <td className="p-3">
                        <div className="font-medium">{a.name}</div>
                        {a.officialName && <div className="text-xs text-muted-foreground">{a.officialName}</div>}
                        {a.mask && <div className="text-[10px] text-muted-foreground">····{a.mask}</div>}
                      </td>
                      <td className="p-3 text-xs">
                        <Badge variant="outline" className="text-[10px]">{a.type}{a.subtype ? ` · ${a.subtype}` : ""}</Badge>
                      </td>
                      <td className="p-3 text-right font-mono tabular-nums">
                        {a.balance != null ? formatCurrency(a.balance) : "—"}
                      </td>
                      <td className="p-3">
                        <select
                          value={a.entitySlug ?? ""}
                          onChange={(e) => setEntityForAccount(a.accountId, e.target.value)}
                          className="h-9 rounded-md border border-input bg-background px-2 text-xs"
                        >
                          <option value="">Unassigned</option>
                          {ALL_ORGANIZATIONS.map((o) => (
                            <option key={o.slug} value={o.slug}>{o.emoji} {o.name}</option>
                          ))}
                        </select>
                      </td>
                      <td className="p-3 text-right">
                        <Button variant="ghost" size="sm" onClick={() => disconnect(a.accountId)}>×</Button>
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          </CardContent>
        </Card>
      )}
    </div>
    <AlertConfirmPortal />
    </>
  );
}
