import { useState, useEffect, useMemo, useRef } from "react";
import { supabase } from "@/integrations/supabase/client";
import { useToast } from "@/hooks/use-toast";
import { Card, CardContent } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog";
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle } from "@/components/ui/alert-dialog";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { BookOpen, Download, Search, Printer, PlusCircle, ArrowUpDown, Loader2, Pencil, Trash2, AlertCircle } from "lucide-react";
import { format } from "date-fns";
import type { Tables } from "@/integrations/supabase/types";

const PRINT_STYLE = `
@media print {
  body * { visibility: hidden !important; }
  #gl-print-area, #gl-print-area * { visibility: visible !important; }
  #gl-print-area { position: absolute; left: 0; top: 0; width: 100%; }
  .no-print { display: none !important; }
  @page { size: letter landscape; margin: 0.5in; }
}
`;

type Account = { id: string; account_number: string; account_name: string; account_type: string; association_id: string };
type JournalEntry = {
  id: string; date: string; description: string | null; amount: number; type: string;
  chart_of_account_id: string | null; association_id: string; created_at: string;
  chart_of_accounts: { account_number: string; account_name: string; account_type: string } | null;
  debit: number; credit: number; accountName: string; runningBalance: number;
};

const emptyForm = { date: "", description: "", amount: "", type: "debit" as string, chart_of_account_id: "" };

export default function GeneralLedgerPage() {
  const { toast } = useToast();
  const printRef = useRef<HTMLDivElement>(null);

  const [loading, setLoading] = useState(true);
  const [transactions, setTransactions] = useState<JournalEntry[]>([]);
  const [associations, setAssociations] = useState<Tables<"associations">[]>([]);
  const [accounts, setAccounts] = useState<Account[]>([]);

  const [selectedAssocId, setSelectedAssocId] = useState("all");
  const [selectedAccountId, setSelectedAccountId] = useState("all");
  const [startDate, setStartDate] = useState("");
  const [endDate, setEndDate] = useState("");
  const [searchQuery, setSearchQuery] = useState("");
  const [sortOrder, setSortOrder] = useState<"asc" | "desc">("desc");

  // Add/Edit
  const [formOpen, setFormOpen] = useState(false);
  const [editingId, setEditingId] = useState<string | null>(null);
  const [form, setForm] = useState(emptyForm);
  const [saving, setSaving] = useState(false);

  // Delete
  const [deletingId, setDeletingId] = useState<string | null>(null);
  const [isDeleting, setIsDeleting] = useState(false);

  useEffect(() => {
    const style = document.createElement("style");
    style.innerHTML = PRINT_STYLE;
    document.head.appendChild(style);
    return () => { document.head.removeChild(style); };
  }, []);

  useEffect(() => { fetchInitialData(); }, []);
  useEffect(() => { fetchTransactions(); }, [selectedAssocId]);

  const fetchInitialData = async () => {
    const [assocRes, acctRes] = await Promise.all([
      supabase.from("associations").select("id, name").eq("status", "active").order("name"),
      supabase.from("chart_of_accounts").select("id, account_number, account_name, account_type, association_id").order("account_number"),
    ]);
    if (assocRes.data) setAssociations(assocRes.data as Tables<"associations">[]);
    if (acctRes.data) setAccounts(acctRes.data as Account[]);
  };

  const fetchTransactions = async () => {
    setLoading(true);
    let query = supabase
      .from("journal_entries")
      .select("id, date, description, amount, type, chart_of_account_id, association_id, created_at, chart_of_accounts(account_number, account_name, account_type)");

    if (selectedAssocId !== "all") query = query.eq("association_id", selectedAssocId);

    const { data, error } = await query;
    if (error) {
      toast({ variant: "destructive", title: "Error", description: "Failed to load journal entries." });
      setLoading(false);
      return;
    }

    const formatted = (data || []).map((t: any) => {
      const isDebit = t.type === "debit";
      const amt = parseFloat(t.amount || 0);
      return {
        ...t,
        debit: isDebit ? amt : 0,
        credit: !isDebit ? amt : 0,
        accountName: t.chart_of_accounts
          ? `${t.chart_of_accounts.account_number} - ${t.chart_of_accounts.account_name}`
          : "Uncategorized",
        runningBalance: 0,
      };
    });
    setTransactions(formatted);
    setLoading(false);
  };

  const processedTransactions = useMemo(() => {
    let result = [...transactions];
    if (selectedAccountId !== "all") result = result.filter(t => t.chart_of_account_id === selectedAccountId);
    if (startDate) result = result.filter(t => t.date >= startDate);
    if (endDate) result = result.filter(t => t.date <= endDate);
    if (searchQuery.trim()) {
      const q = searchQuery.toLowerCase();
      result = result.filter(t => (t.description || "").toLowerCase().includes(q) || t.accountName.toLowerCase().includes(q));
    }
    result.sort((a, b) => {
      const d = new Date(a.date).getTime() - new Date(b.date).getTime();
      return d !== 0 ? d : new Date(a.created_at).getTime() - new Date(b.created_at).getTime();
    });
    let bal = 0;
    result = result.map(t => { bal += t.debit - t.credit; return { ...t, runningBalance: bal }; });
    if (sortOrder === "desc") result.reverse();
    return result;
  }, [transactions, selectedAccountId, startDate, endDate, searchQuery, sortOrder]);

  const totals = useMemo(() =>
    processedTransactions.reduce((a, t) => ({ debit: a.debit + t.debit, credit: a.credit + t.credit, net: a.net + t.debit - t.credit }), { debit: 0, credit: 0, net: 0 }),
    [processedTransactions]);

  const filteredAccounts = accounts.filter(a => selectedAssocId === "all" || a.association_id === selectedAssocId);

  // CSV Export
  const exportCSV = async () => {
    if (!processedTransactions.length) return;
    const rows = [
      ["Date", "Account", "Description", "Type", "Debit", "Credit", "Balance"].join(","),
      ...processedTransactions.map(t => [t.date, `"${t.accountName}"`, `"${(t.description || "").replace(/"/g, '""')}"`, t.type, t.debit.toFixed(2), t.credit.toFixed(2), t.runningBalance.toFixed(2)].join(","))
    ].join("\n");
    const { saveCsv } = await import("@/lib/saveFile");
    await saveCsv(rows, `General_Ledger_${format(new Date(), "yyyy-MM-dd")}.csv`);
  };

  // Form handlers
  const openAdd = () => {
    if (selectedAssocId === "all") {
      toast({ variant: "destructive", title: "Select an association first" });
      return;
    }
    setEditingId(null);
    setForm({ ...emptyForm, date: format(new Date(), "yyyy-MM-dd") });
    setFormOpen(true);
  };

  const openEdit = (t: JournalEntry) => {
    setEditingId(t.id);
    setForm({ date: t.date, description: t.description || "", amount: String(t.debit || t.credit), type: t.type, chart_of_account_id: t.chart_of_account_id || "" });
    setFormOpen(true);
  };

  const handleSave = async () => {
    if (!form.date || !form.amount) {
      toast({ variant: "destructive", title: "Date and amount are required" });
      return;
    }
    setSaving(true);
    const payload = {
      date: form.date,
      description: form.description || null,
      amount: parseFloat(form.amount),
      type: form.type,
      chart_of_account_id: form.chart_of_account_id || null,
      association_id: selectedAssocId,
    };

    const { error } = editingId
      ? await supabase.from("journal_entries").update(payload).eq("id", editingId)
      : await supabase.from("journal_entries").insert(payload);

    if (error) {
      toast({ variant: "destructive", title: "Error", description: error.message });
    } else {
      toast({ title: editingId ? "Entry updated" : "Entry added" });
      setFormOpen(false);
      fetchTransactions();
    }
    setSaving(false);
  };

  const handleDelete = async () => {
    if (!deletingId) return;
    setIsDeleting(true);
    const { error } = await supabase.from("journal_entries").delete().eq("id", deletingId);
    if (error) {
      toast({ variant: "destructive", title: "Error", description: error.message });
    } else {
      toast({ title: "Entry deleted" });
      fetchTransactions();
    }
    setIsDeleting(false);
    setDeletingId(null);
  };

  const fmtMoney = (v: number) => `$${Math.abs(v).toFixed(2)}${v < 0 ? " CR" : ""}`;

  return (
    <div className="space-y-6 max-w-7xl mx-auto pb-12 min-h-screen p-6">
      {/* Header */}
      <div className="flex items-center gap-3">
        <div className="p-2.5 rounded-xl bg-primary/10">
          <BookOpen className="h-6 w-6 text-primary" />
        </div>
        <div>
          <h1 className="text-2xl font-bold text-foreground">General Ledger</h1>
          <p className="text-sm text-muted-foreground">Journal entries and account activity</p>
        </div>
      </div>

      {/* Actions */}
      <div className="no-print flex flex-wrap gap-2">
        <Button onClick={openAdd} className="gap-2"><PlusCircle className="h-4 w-4" /> Add Entry</Button>
        <Button variant="outline" onClick={() => window.print()} className="gap-2"><Printer className="h-4 w-4" /> Print</Button>
        <Button variant="outline" onClick={exportCSV} className="gap-2"><Download className="h-4 w-4" /> Export CSV</Button>
      </div>

      {/* Filters */}
      <Card className="no-print">
        <CardContent className="p-4">
          <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-5 gap-4">
            <div className="space-y-1.5">
              <Label className="text-xs font-semibold text-muted-foreground uppercase">Association</Label>
              <Select value={selectedAssocId} onValueChange={setSelectedAssocId}>
                <SelectTrigger><SelectValue placeholder="All Associations" /></SelectTrigger>
                <SelectContent>
                  <SelectItem value="all">All Associations</SelectItem>
                  {associations.map(a => <SelectItem key={a.id} value={a.id}>{a.name}</SelectItem>)}
                </SelectContent>
              </Select>
            </div>
            <div className="space-y-1.5">
              <Label className="text-xs font-semibold text-muted-foreground uppercase">Account</Label>
              <Select value={selectedAccountId} onValueChange={setSelectedAccountId}>
                <SelectTrigger><SelectValue placeholder="All Accounts" /></SelectTrigger>
                <SelectContent>
                  <SelectItem value="all">All Accounts</SelectItem>
                  {filteredAccounts.map(a => <SelectItem key={a.id} value={a.id}>{a.account_number} - {a.account_name}</SelectItem>)}
                </SelectContent>
              </Select>
            </div>
            <div className="space-y-1.5">
              <Label className="text-xs font-semibold text-muted-foreground uppercase">Start Date</Label>
              <Input type="date" value={startDate} onChange={e => setStartDate(e.target.value)} />
            </div>
            <div className="space-y-1.5">
              <Label className="text-xs font-semibold text-muted-foreground uppercase">End Date</Label>
              <Input type="date" value={endDate} onChange={e => setEndDate(e.target.value)} />
            </div>
            <div className="space-y-1.5 sm:col-span-2 lg:col-span-1">
              <Label className="text-xs font-semibold text-muted-foreground uppercase">Search</Label>
              <div className="relative">
                <Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
                <Input placeholder="Search..." value={searchQuery} onChange={e => setSearchQuery(e.target.value)} className="pl-9" />
              </div>
            </div>
          </div>
        </CardContent>
      </Card>

      {/* Table */}
      <div className="rounded-lg border bg-card overflow-hidden no-print">
        <Table>
          <TableHeader>
            <TableRow>
              <TableHead className="w-32">
                <Button variant="ghost" size="sm" onClick={() => setSortOrder(s => s === "desc" ? "asc" : "desc")} className="gap-1 -ml-3 text-xs font-bold uppercase">
                  Date <ArrowUpDown className="h-3 w-3" />
                </Button>
              </TableHead>
              <TableHead className="text-xs font-bold uppercase">Account</TableHead>
              <TableHead className="text-xs font-bold uppercase">Description</TableHead>
              <TableHead className="text-right text-xs font-bold uppercase">Debit</TableHead>
              <TableHead className="text-right text-xs font-bold uppercase">Credit</TableHead>
              <TableHead className="text-right text-xs font-bold uppercase">Balance</TableHead>
              <TableHead className="w-24 text-right text-xs font-bold uppercase">Actions</TableHead>
            </TableRow>
          </TableHeader>
          <TableBody>
            {loading ? (
              <TableRow><TableCell colSpan={7} className="text-center py-16 text-muted-foreground"><Loader2 className="h-8 w-8 animate-spin mx-auto mb-3" />Loading...</TableCell></TableRow>
            ) : processedTransactions.length === 0 ? (
              <TableRow><TableCell colSpan={7} className="text-center py-16 text-muted-foreground"><BookOpen className="h-10 w-10 mx-auto mb-3 opacity-30" />No transactions found.</TableCell></TableRow>
            ) : processedTransactions.map(t => (
              <TableRow key={t.id} className="group">
                <TableCell className="text-sm font-medium whitespace-nowrap">{t.date ? format(new Date(t.date), "MMM dd, yyyy") : "—"}</TableCell>
                <TableCell className="text-sm font-semibold">{t.accountName === "Uncategorized" ? <span className="text-amber-600 bg-amber-500/10 px-2 py-0.5 rounded">{t.accountName}</span> : t.accountName}</TableCell>
                <TableCell className="text-sm text-muted-foreground">{t.description}</TableCell>
                <TableCell className="text-right text-sm font-mono">{t.debit > 0 ? `$${t.debit.toFixed(2)}` : "—"}</TableCell>
                <TableCell className="text-right text-sm font-mono">{t.credit > 0 ? `$${t.credit.toFixed(2)}` : "—"}</TableCell>
                <TableCell className={`text-right text-sm font-mono font-bold ${t.runningBalance < 0 ? "text-destructive" : ""}`}>{fmtMoney(t.runningBalance)}</TableCell>
                <TableCell className="text-right">
                  <div className="flex justify-end gap-1">
                    <Button variant="ghost" size="icon" className="h-8 w-8" onClick={() => openEdit(t)}><Pencil className="h-4 w-4" /></Button>
                    <Button variant="ghost" size="icon" className="h-8 w-8 text-destructive hover:text-destructive" onClick={() => setDeletingId(t.id)}><Trash2 className="h-4 w-4" /></Button>
                  </div>
                </TableCell>
              </TableRow>
            ))}
          </TableBody>
        </Table>

        {!loading && processedTransactions.length > 0 && (
          <div className="bg-muted/50 p-4 border-t flex justify-end gap-10 font-mono text-sm">
            <div className="text-right">
              <p className="text-[10px] uppercase font-bold text-muted-foreground mb-0.5">Total Debits</p>
              <p className="font-bold text-lg">${totals.debit.toFixed(2)}</p>
            </div>
            <div className="text-right">
              <p className="text-[10px] uppercase font-bold text-muted-foreground mb-0.5">Total Credits</p>
              <p className="font-bold text-lg">${totals.credit.toFixed(2)}</p>
            </div>
            <div className="text-right">
              <p className="text-[10px] uppercase font-bold text-muted-foreground mb-0.5">Net Balance</p>
              <p className={`font-bold text-lg ${totals.net < 0 ? "text-destructive" : ""}`}>{fmtMoney(totals.net)}</p>
            </div>
          </div>
        )}
      </div>

      {/* Print area */}
      <div id="gl-print-area" ref={printRef} className="bg-background p-6 rounded-lg">
        <div className="mb-6 border-b-2 border-primary pb-4">
          <h2 className="text-2xl font-bold text-primary">General Ledger</h2>
          <p className="text-muted-foreground">
            {selectedAssocId === "all" ? "All Associations" : associations.find(a => a.id === selectedAssocId)?.name}
            {startDate && endDate && ` | ${startDate} to ${endDate}`}
          </p>
        </div>
        <table className="w-full border-collapse text-xs">
          <thead>
            <tr className="border-b">
              <th className="text-left p-2">Date</th><th className="text-left p-2">Account</th><th className="text-left p-2">Description</th>
              <th className="text-right p-2">Debit</th><th className="text-right p-2">Credit</th><th className="text-right p-2">Balance</th>
            </tr>
          </thead>
          <tbody>
            {processedTransactions.map(t => (
              <tr key={t.id} className="border-b border-border/50">
                <td className="p-2">{t.date ? format(new Date(t.date), "MM/dd/yyyy") : "—"}</td>
                <td className="p-2 font-medium">{t.accountName}</td>
                <td className="p-2">{t.description}</td>
                <td className="p-2 text-right">{t.debit > 0 ? t.debit.toFixed(2) : ""}</td>
                <td className="p-2 text-right">{t.credit > 0 ? t.credit.toFixed(2) : ""}</td>
                <td className={`p-2 text-right font-medium ${t.runningBalance < 0 ? "text-destructive" : ""}`}>{fmtMoney(t.runningBalance)}</td>
              </tr>
            ))}
          </tbody>
          {processedTransactions.length > 0 && (
            <tfoot>
              <tr className="border-t-2">
                <td colSpan={3} className="text-right p-2 font-bold">Totals:</td>
                <td className="text-right p-2 font-bold">{totals.debit.toFixed(2)}</td>
                <td className="text-right p-2 font-bold">{totals.credit.toFixed(2)}</td>
                <td className={`text-right p-2 font-bold ${totals.net < 0 ? "text-destructive" : ""}`}>{fmtMoney(totals.net)}</td>
              </tr>
            </tfoot>
          )}
        </table>
      </div>

      {/* Add/Edit Dialog */}
      <Dialog open={formOpen} onOpenChange={setFormOpen}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>{editingId ? "Edit Journal Entry" : "Add Journal Entry"}</DialogTitle>
          </DialogHeader>
          <div className="space-y-4">
            <div className="grid grid-cols-2 gap-4">
              <div className="space-y-2">
                <Label>Date</Label>
                <Input type="date" value={form.date} onChange={e => setForm({ ...form, date: e.target.value })} />
              </div>
              <div className="space-y-2">
                <Label>Type</Label>
                <Select value={form.type} onValueChange={v => setForm({ ...form, type: v })}>
                  <SelectTrigger><SelectValue /></SelectTrigger>
                  <SelectContent>
                    <SelectItem value="debit">Debit</SelectItem>
                    <SelectItem value="credit">Credit</SelectItem>
                  </SelectContent>
                </Select>
              </div>
            </div>
            <div className="space-y-2">
              <Label>Amount</Label>
              <Input type="number" step="0.01" min="0" value={form.amount} onChange={e => setForm({ ...form, amount: e.target.value })} placeholder="0.00" />
            </div>
            <div className="space-y-2">
              <Label>Account</Label>
              <Select value={form.chart_of_account_id} onValueChange={v => setForm({ ...form, chart_of_account_id: v })}>
                <SelectTrigger><SelectValue placeholder="Select account" /></SelectTrigger>
                <SelectContent>
                  {filteredAccounts.map(a => <SelectItem key={a.id} value={a.id}>{a.account_number} - {a.account_name}</SelectItem>)}
                </SelectContent>
              </Select>
            </div>
            <div className="space-y-2">
              <Label>Description</Label>
              <Input value={form.description} onChange={e => setForm({ ...form, description: e.target.value })} placeholder="Transaction description" />
            </div>
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setFormOpen(false)}>Cancel</Button>
            <Button onClick={handleSave} disabled={saving} className="gap-2">
              {saving && <Loader2 className="h-4 w-4 animate-spin" />}
              {editingId ? "Update" : "Add Entry"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      {/* Delete Confirmation */}
      <AlertDialog open={!!deletingId} onOpenChange={o => !o && setDeletingId(null)}>
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle className="text-destructive flex items-center gap-2">
              <AlertCircle className="h-5 w-5" /> Delete Ledger Entry
            </AlertDialogTitle>
            <AlertDialogDescription>This will permanently remove the journal entry and affect balances.</AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel disabled={isDeleting}>Cancel</AlertDialogCancel>
            <AlertDialogAction disabled={isDeleting} onClick={handleDelete} className="bg-destructive text-destructive-foreground hover:bg-destructive/90 gap-2">
              {isDeleting ? <Loader2 className="h-4 w-4 animate-spin" /> : <Trash2 className="h-4 w-4" />} Delete
            </AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>
    </div>
  );
}
