import { useEffect, useState } from 'react';
import { useParams, Link, useNavigate } from 'react-router-dom';
import { getLedger, deleteLedger, SplintError } from '../api/client';
import { computeBalances, computeSettlements } from '@splint/shared';
import { addRecentLedger } from '../recent';
import type { LedgerData, LedgerMeta, Expense, Transfer } from '@splint/shared';
import { useLedger } from '../hooks/useLedger';
import { DebtGraph } from '../components/DebtGraph';
import { ExpenseTimeline } from '../components/ExpenseTimeline';
import { PeopleList } from '../components/PeopleList';
import { SettlementsList } from '../components/SettlementsList';
import { ExpensesList, ExpenseModal } from '../components/ExpensesList';
import { TransfersList, TransferModal } from '../components/TransfersList';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogDescription,
  DialogFooter,
} from '@/components/ui/dialog';
import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card';
import { Skeleton } from '@/components/ui/skeleton';
import { Loader2 } from 'lucide-react';
import { toast } from 'sonner';

// ── Outer component: handles loading, errors, and data-fetching ─────────────

export function LedgerView() {
  const { id } = useParams<{ id: string }>();
  const navigate = useNavigate();

  const [meta, setMeta] = useState<LedgerMeta | null>(null);
  const [data, setData] = useState<LedgerData | null>(null);
  const [error, setError] = useState('');
  const [loading, setLoading] = useState(true);
  const [needsKey, setNeedsKey] = useState(false);
  const [keyInput, setKeyInput] = useState('');
  const [keyError, setKeyError] = useState('');
  const [keyLoading, setKeyLoading] = useState(false);

  // ── UI toggles (owned here — layout-level state) ──────────────────────
  const [showGraph, setShowGraph] = useState(true);
  const [showTimeline, setShowTimeline] = useState(true);
  const [showDeleteLedgerModal, setShowDeleteLedgerModal] = useState(false);

  // ── Modal state (ownership shared with sub-components) ─────────────────
  const [showExpModal, setShowExpModal] = useState(false);
  const [editingExpense, setEditingExpense] = useState<Expense | null>(null);
  const [showTransferModal, setShowTransferModal] = useState(false);
  const [editingTransfer, setEditingTransfer] = useState<Transfer | null>(null);

  // ── Load ledger ────────────────────────────────────────────────────────
  useEffect(() => {
    if (!id) return;
    const key = localStorage.getItem(`splint-key:${id}`);
    if (!key) {
      setNeedsKey(true);
      setLoading(false);
      return;
    }
    getLedger(id, key)
      .then(({ meta, data }) => {
        setMeta(meta);
        setData(data);
        addRecentLedger({ id, name: meta.name });
        document.title = `${meta.name} - Splint`;
      })
      .catch((err) => {
        setError(
          err instanceof SplintError
            ? err.message
            : err instanceof Error
              ? err.message
              : 'Unknown error',
        );
      })
      .finally(() => setLoading(false));
    return () => {
      document.title = 'Splint';
    };
  }, [id]);

  // ── Key entry handler (shown when localStorage has no key) ──────────
  async function handleKeySubmit(e: React.FormEvent) {
    e.preventDefault();
    if (!id || !keyInput.trim()) return;
    setKeyError('');
    setKeyLoading(true);
    try {
      const { meta: ledgerMeta, data: ledgerData } = await getLedger(id, keyInput.trim());
      localStorage.setItem(`splint-key:${id}`, keyInput.trim());
      addRecentLedger({ id, name: ledgerMeta.name });
      setMeta(ledgerMeta);
      setData(ledgerData);
      setNeedsKey(false);
      setLoading(false);
      document.title = `${ledgerMeta.name} - Splint`;
    } catch (err) {
      setKeyError(
        err instanceof SplintError
          ? err.message
          : err instanceof Error
            ? err.message
            : 'Failed to decrypt — check the key and try again.',
      );
    } finally {
      setKeyLoading(false);
    }
  }

  // ── Modal handlers ─────────────────────────────────────────────────────
  function openNewExpense() {
    setEditingExpense(null);
    setShowExpModal(true);
  }

  function openEditExpense(expense: Expense) {
    setEditingExpense(expense);
    setShowExpModal(true);
  }

  function closeExpModal() {
    setShowExpModal(false);
  }

  function openNewTransfer() {
    setEditingTransfer(null);
    setShowTransferModal(true);
  }

  function openEditTransfer(transfer: Transfer) {
    setEditingTransfer(transfer);
    setShowTransferModal(true);
  }

  function closeTransferModal() {
    setShowTransferModal(false);
  }

  // ── Ledger-level actions ───────────────────────────────────────────────
  async function copyInviteLink() {
    if (!id) return;
    const url = `${window.location.origin}/ledger/${id}`;
    try {
      await navigator.clipboard.writeText(url);
      toast('Invite link copied!');
    } catch {
      prompt('Copy this invite link:', url);
    }
  }

  async function doDeleteLedger() {
    if (!id) return;
    try {
      await deleteLedger(id);
      localStorage.removeItem(`splint-key:${id}`);
      try {
        const raw = localStorage.getItem('splint-recent-ledgers');
        if (raw) {
          const list = JSON.parse(raw);
          localStorage.setItem(
            'splint-recent-ledgers',
            JSON.stringify(list.filter((e: { id: string }) => e.id !== id)),
          );
        }
      } catch {
        /* ignore */
      }
      navigate('/');
    } catch (err) {
      setError(
        err instanceof SplintError ? err.message : 'Failed to delete ledger.',
      );
    }
  }

  // ── Render states ──────────────────────────────────────────────────────
  if (needsKey) {
    return (
      <div className="flex items-center justify-center min-h-screen">
        <main className="container max-w-md mx-auto px-4">
          <Card>
            <CardHeader>
              <CardTitle>Enter encryption key</CardTitle>
            </CardHeader>
            <CardContent>
              <form onSubmit={handleKeySubmit} className="space-y-4">
                <p className="text-sm text-muted-foreground">
                  Enter the encryption key that was generated for this ledger.
                </p>
                <Input
                  type="password"
                  value={keyInput}
                  onChange={(e) => { setKeyInput(e.target.value); setKeyError(''); }}
                  placeholder="Paste the encryption key here"
                  autoFocus
                  disabled={keyLoading}
                />
                {keyError && (
                  <Card className="border-destructive">
                    <CardContent className="p-3 text-sm text-destructive">
                      {keyError}
                    </CardContent>
                  </Card>
                )}
                <div className="flex gap-2">
                  <Button type="submit" className="flex-1" disabled={keyLoading || !keyInput.trim()}>
                    {keyLoading ? 'Decrypting...' : 'Join ledger'}
                  </Button>
                  <Button type="button" variant="outline" asChild>
                    <Link to="/">Cancel</Link>
                  </Button>
                </div>
              </form>
            </CardContent>
          </Card>
        </main>
      </div>
    );
  }

  if (loading) return <LedgerSkeleton />;

  if (error) {
    return (
      <main className="container max-w-lg mx-auto px-4 mt-4">
        <p>
          <Link to="/">← Home</Link>
        </p>
        <Card className="border-destructive" role="alert">
          <CardContent className="pt-6">
            <p className="text-destructive">{error}</p>
            {error.includes('unreachable') && (
              <Button
                variant="outline"
                size="sm"
                className="mt-2"
                onClick={() => {
                  setError('');
                  setLoading(true);
                  window.location.reload();
                }}
              >
                Retry
              </Button>
            )}
          </CardContent>
        </Card>
      </main>
    );
  }

  if (!data || !meta) return null;

  return (
    <LedgerContent
      id={id!}
      meta={meta}
      data={data}
      showGraph={showGraph}
      showTimeline={showTimeline}
      showDeleteLedgerModal={showDeleteLedgerModal}
      showExpModal={showExpModal}
      editingExpense={editingExpense}
      showTransferModal={showTransferModal}
      editingTransfer={editingTransfer}
      onToggleGraph={() => setShowGraph((v) => !v)}
      onToggleTimeline={() => setShowTimeline((v) => !v)}
      onOpenDeleteLedger={() => setShowDeleteLedgerModal(true)}
      onCloseDeleteLedger={() => setShowDeleteLedgerModal(false)}
      onDeleteLedger={doDeleteLedger}
      onCopyInviteLink={copyInviteLink}
      onOpenNewExpense={openNewExpense}
      onOpenEditExpense={openEditExpense}
      onCloseExpModal={closeExpModal}
      onOpenNewTransfer={openNewTransfer}
      onOpenEditTransfer={openEditTransfer}
      onCloseTransferModal={closeTransferModal}
    />
  );
}

// ── Inner component: ledger is loaded, hooks are safe ───────────────────────

interface LedgerContentProps {
  id: string;
  meta: LedgerMeta;
  data: LedgerData;
  showGraph: boolean;
  showTimeline: boolean;
  showDeleteLedgerModal: boolean;
  showExpModal: boolean;
  editingExpense: Expense | null;
  showTransferModal: boolean;
  editingTransfer: Transfer | null;
  onToggleGraph: () => void;
  onToggleTimeline: () => void;
  onOpenDeleteLedger: () => void;
  onCloseDeleteLedger: () => void;
  onDeleteLedger: () => Promise<void>;
  onCopyInviteLink: () => Promise<void>;
  onOpenNewExpense: () => void;
  onOpenEditExpense: (expense: Expense) => void;
  onCloseExpModal: () => void;
  onOpenNewTransfer: () => void;
  onOpenEditTransfer: (transfer: Transfer) => void;
  onCloseTransferModal: () => void;
}

function LedgerContent({
  id,
  meta,
  data,
  showGraph,
  showTimeline,
  showDeleteLedgerModal,
  showExpModal,
  editingExpense,
  showTransferModal,
  editingTransfer,
  onToggleGraph,
  onToggleTimeline,
  onOpenDeleteLedger,
  onCloseDeleteLedger,
  onDeleteLedger,
  onCopyInviteLink,
  onOpenNewExpense,
  onOpenEditExpense,
  onCloseExpModal,
  onOpenNewTransfer,
  onOpenEditTransfer,
  onCloseTransferModal,
}: LedgerContentProps) {
  // ── Hook ───────────────────────────────────────────────────────────────
  const ledger = useLedger(data, id);

  // ── Derived data ───────────────────────────────────────────────────────
  const balances = computeBalances(
    ledger.data.people.map((p) => p.id),
    ledger.data.expenses,
    ledger.data.transfers,
  );
  const settlements = computeSettlements(balances);

  return (
    <div>
      {/* ════ Modals ══════════════════════════════════════════════════════ */}

      {showExpModal && (
        <ExpenseModal
          key={editingExpense?.id ?? 'new'}
          people={ledger.data.people}
          editingExpense={editingExpense}
          onSave={async (fields) => {
            if (editingExpense) {
              await ledger.updateExpense(editingExpense.id, fields);
            } else {
              await ledger.addExpense(fields);
            }
          }}
          onClose={onCloseExpModal}
          saving={ledger.saving}
        />
      )}

      {showTransferModal && (
        <TransferModal
          key={editingTransfer?.id ?? 'new'}
          people={ledger.data.people}
          editingTransfer={editingTransfer}
          onSave={async (fields) => {
            if (editingTransfer) {
              await ledger.updateTransfer(editingTransfer.id, fields);
            } else {
              await ledger.addTransfer(fields);
            }
          }}
          onClose={onCloseTransferModal}
          saving={ledger.saving}
        />
      )}

      <Dialog open={showDeleteLedgerModal} onOpenChange={(open) => !open && onCloseDeleteLedger()}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Delete this ledger?</DialogTitle>
            <DialogDescription>
              This cannot be undone. All data will be permanently lost.
            </DialogDescription>
          </DialogHeader>
          <DialogFooter>
            <Button
              variant="destructive"
              onClick={onDeleteLedger}
              disabled={ledger.saving}
            >
              Yes, delete it
            </Button>
            <Button variant="outline" onClick={onCloseDeleteLedger}>
              Cancel
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      {/* ════ Top bar ══════════════════════════════════════════════════════ */}

      <header className="sticky top-0 z-10 flex items-center justify-between gap-3 flex-wrap p-3 bg-card border-b">
        <div className="flex items-center gap-2">
          <Button variant="ghost" size="sm" asChild>
            <Link to="/" aria-label="Back to home">
              ← Home
            </Link>
          </Button>
          <span className="font-semibold">{meta.name}</span>
        </div>
        <div className="flex gap-2">
          <Button onClick={onCopyInviteLink} aria-label="Copy invite link">
            Copy invite link
          </Button>
          <Button variant="outline" onClick={onOpenNewExpense} aria-label="Add expense">
            + Expense
          </Button>
          <Button variant="outline" onClick={onOpenNewTransfer} aria-label="Record transfer">
            + Transfer
          </Button>
          <Button variant="destructive" onClick={onOpenDeleteLedger} aria-label="Delete ledger">
            Delete
          </Button>
        </div>
      </header>

      {ledger.saving && (
        <p className="text-sm text-muted-foreground px-4 pt-2" role="status">
          Saving...
        </p>
      )}

      {/* ════ Two-panel grid ═══════════════════════════════════════════════ */}

      <div className="container max-w-7xl mx-auto px-4 mt-4">
        <div className="grid grid-cols-1 lg:grid-cols-[280px_1fr] gap-6">
          {/* Left panel */}
          <div className="space-y-4">
            <PeopleList
              people={ledger.data.people}
              expenses={ledger.data.expenses}
              transfers={ledger.data.transfers}
              onAdd={ledger.addPerson}
              onUpdate={ledger.updatePerson}
              onRemove={ledger.removePerson}
              saving={ledger.saving}
            />

            <SettlementsList
              settlements={settlements}
              people={ledger.data.people}
            />

            {/* ── Views nav (hidden — showGraph/showTimeline now always default on) ──────
            <Card>
              <CardHeader>
                <CardTitle>Views</CardTitle>
              </CardHeader>
              <CardContent className="flex flex-wrap gap-2">
                <Button
                  variant={showGraph ? 'default' : 'outline'}
                  size="sm"
                  onClick={onToggleGraph}
                  aria-label="Toggle money flow graph"
                >
                  Money Flow
                </Button>
                <Button
                  variant={showTimeline ? 'default' : 'outline'}
                  size="sm"
                  onClick={onToggleTimeline}
                  aria-label="Toggle expense timeline"
                >
                  Timeline
                </Button>
              </CardContent>
            </Card>
            ──────────────────────────────────────────────────────── */}
          </div>

          {/* Right panel */}
          <div className="space-y-4">
            {showGraph && (
              <Card>
                <CardHeader>
                  <CardTitle>Money Flow</CardTitle>
                </CardHeader>
                <CardContent>
                  <DebtGraph
                    people={ledger.data.people}
                    expenses={ledger.data.expenses}
                    transfers={ledger.data.transfers}
                    balances={balances}
                  />
                </CardContent>
              </Card>
            )}

            {showTimeline && (
              <Card>
                <CardHeader>
                  <CardTitle>Expense Timeline</CardTitle>
                </CardHeader>
                <CardContent>
                  <ExpenseTimeline
                    expenses={ledger.data.expenses}
                    people={ledger.data.people}
                    transfers={ledger.data.transfers}
                    onEditExpense={onOpenEditExpense}
                    onDeleteExpense={ledger.deleteExpense}
                    onEditTransfer={onOpenEditTransfer}
                    onDeleteTransfer={ledger.deleteTransfer}
                  />
                </CardContent>
              </Card>
            )}

            {/* ── ExpensesList (hidden — now driven by ExpenseTimeline) ──────
            <ExpensesList
              expenses={ledger.data.expenses}
              people={ledger.data.people}
              onEditExpense={onOpenEditExpense}
              onRequestAdd={onOpenNewExpense}
              onDelete={ledger.deleteExpense}
              saving={ledger.saving}
            />
            ──────────────────────────────────────────────────────── */}

            {/* ── TransfersList (hidden) ──────
            {ledger.data.transfers.length > 0 && (
              <TransfersList
                transfers={ledger.data.transfers}
                people={ledger.data.people}
                onRequestAdd={onOpenNewTransfer}
                onDelete={ledger.deleteTransfer}
                saving={ledger.saving}
              />
            )}
            ──────────────────────────────────────── */}
          </div>
        </div>
      </div>
    </div>
  );
}

// ── Loading skeleton ────────────────────────────────────────────────────────

function LedgerSkeleton() {
  return (
    <div>
      <header className="sticky top-0 z-10 flex items-center justify-between gap-3 flex-wrap p-3 bg-card border-b">
        <div className="flex items-center gap-2">
          <Skeleton className="h-7 w-[60px]" />
          <Skeleton className="h-5 w-[120px]" />
        </div>
        <div className="flex gap-2">
          <Skeleton className="h-8 w-[120px]" />
          <Skeleton className="h-8 w-[100px]" />
        </div>
      </header>

      <div className="container max-w-7xl mx-auto px-4 mt-4">
        <div className="grid grid-cols-1 lg:grid-cols-[280px_1fr] gap-6">
          <div className="space-y-4">
            <Card>
              <CardHeader>
                <Skeleton className="h-5 w-[80px]" />
              </CardHeader>
              <CardContent className="space-y-2">
                {[1, 2, 3].map((i) => (
                  <div key={i} className="flex items-center justify-between py-2 border-b border-border last:border-0">
                    <Skeleton className="h-4 w-[100px]" />
                    <Skeleton className="h-5 w-[60px]" />
                  </div>
                ))}
              </CardContent>
            </Card>
            <Card>
              <CardHeader>
                <Skeleton className="h-5 w-[110px]" />
              </CardHeader>
              <CardContent>
                <Skeleton className="h-4 w-full" />
              </CardContent>
            </Card>
          </div>
          <div>
            <Card>
              <CardHeader className="flex flex-row items-center justify-between">
                <Skeleton className="h-5 w-[100px]" />
                <Skeleton className="h-7 w-[60px]" />
              </CardHeader>
              <CardContent className="space-y-2">
                {[1, 2, 3].map((i) => (
                  <div key={i} className="flex flex-col gap-1 py-2 border-b border-border last:border-0">
                    <div className="flex justify-between w-full">
                      <Skeleton className="h-4 w-[140px]" />
                      <Skeleton className="h-4 w-[60px]" />
                    </div>
                    <Skeleton className="h-3 w-[200px]" />
                  </div>
                ))}
              </CardContent>
            </Card>
          </div>
        </div>
      </div>
    </div>
  );
}
