import { useState, useEffect } from "react";
import { supabase } from "@/integrations/supabase/client";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Card, CardContent } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter } from "@/components/ui/dialog";
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle } from "@/components/ui/alert-dialog";
import { FileText, Search, Download, Eye, Trash2, DollarSign, ArrowUpFromLine, Loader2, RefreshCw, FileEdit } from "lucide-react";
import { format } from "date-fns";
import { useToast } from "@/components/ui/use-toast";
import { generateInvoicePdf } from "@/lib/generateInvoicePdf";
import { Checkbox } from "@/components/ui/checkbox";


type RegenItem = {
  id: string;
  billable_expense_id: string | null;
  include: boolean;
  date: string;
  description: string;
  category: string;
  address: string;
  vendor: string;
  quantity: number;
  unit_price: number;
  amount: number;
  is_credit: boolean;
  receipt_url?: string;
};

const statusColors: Record<string, string> = {
  sent: "bg-blue-100 text-blue-700",
  paid: "bg-emerald-100 text-emerald-700",
  overdue: "bg-red-100 text-red-700",
  draft: "bg-muted text-muted-foreground",
  void: "bg-muted text-muted-foreground line-through",
};

export default function ClientInvoicesPage() {
  const { toast } = useToast();
  const [invoices, setInvoices] = useState<any[]>([]);
  const [loading, setLoading] = useState(true);
  const [search, setSearch] = useState("");
  const [detailOpen, setDetailOpen] = useState(false);
  const [selectedInvoice, setSelectedInvoice] = useState<any>(null);
  const [lineItems, setLineItems] = useState<any[]>([]);

  // Regenerate (corrected invoice) state
  const [regenOpen, setRegenOpen] = useState(false);
  const [regenInvoice, setRegenInvoice] = useState<any>(null);
  const [regenItems, setRegenItems] = useState<RegenItem[]>([]);
  const [regenLoading, setRegenLoading] = useState(false);
  const [regenerating, setRegenerating] = useState(false);

  const fetchInvoices = async () => {
    setLoading(true);
    const { data, error } = await supabase
      .from("client_invoices")
      .select("*, associations(name, address, city, state, zip)")
      .order("created_at", { ascending: false });
    if (error) toast({ title: "Error", description: error.message, variant: "destructive" });
    else setInvoices(data || []);
    setLoading(false);
  };

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

  const viewDetails = async (inv: any) => {
    setSelectedInvoice(inv);
    const { data } = await supabase
      .from("client_invoice_items")
      .select("*")
      .eq("invoice_id", inv.id)
      .order("date", { ascending: true });
    setLineItems(data || []);
    setDetailOpen(true);
  };

  const downloadPdf = async (inv: any) => {
    const assoc = inv.associations;
    const { data: settings } = await supabase.from("company_settings").select("key, value");
    const getSetting = (key: string) => settings?.find((s: any) => s.key === key)?.value || "";

    await generateInvoicePdf({
      invoiceNumber: inv.invoice_number,
      invoiceDate: inv.issue_date || "",
      dueDate: inv.due_date || "",
      clientName: assoc?.name || "Client",
      clientAddress: assoc?.address || "",
      clientCity: assoc?.city || "",
      clientState: assoc?.state || "",
      clientZip: assoc?.zip || "",
      companyName: getSetting("company_name") || "ACM Community Management",
      companyAddress: getSetting("company_address") || "",
      companyEmail: getSetting("company_email") || assoc?.email || "",
      companyPhone: getSetting("company_phone") || assoc?.phone || "",
      companyWebsite: getSetting("company_website") || assoc?.website || "",
      logoUrl: getSetting("company_logo") || "",
      items: lineItems.length > 0 ? lineItems.map(li => ({
        date: li.date ? format(new Date(li.date), "MM/dd/yyyy") : "",
        description: li.description || "",
        category: li.category || "",
        quantity: Number(li.quantity || 1),
        unitPrice: Number(li.unit_price || 0),
        amount: Number(li.amount || 0),
        isCredit: li.is_credit || false,
      })) : [{
        date: inv.issue_date ? format(new Date(inv.issue_date), "MM/dd/yyyy") : "",
        description: "Invoice Total",
        category: "",
        quantity: 1,
        unitPrice: Number(inv.total || 0),
        amount: Number(inv.total || 0),
        isCredit: false,
      }],
    });
  };

  const openRegenerate = async (inv: any) => {
    setRegenInvoice(inv);
    setRegenOpen(true);
    setRegenLoading(true);
    try {
      const { data: items, error } = await supabase
        .from("client_invoice_items")
        .select("*")
        .eq("invoice_id", inv.id)
        .order("date", { ascending: true });
      if (error) throw error;

      const expenseIds = (items || []).map((i: any) => i.billable_expense_id).filter(Boolean);
      const receiptMap = new Map<string, string>();
      const addrMap = new Map<string, { address: string; vendor: string }>();
      if (expenseIds.length > 0) {
        const { data: exps } = await supabase
          .from("billable_expenses")
          .select("id, receipt_url, address, vendor_name")
          .in("id", expenseIds);
        (exps || []).forEach((e: any) => {
          if (e.receipt_url) receiptMap.set(e.id, e.receipt_url);
          addrMap.set(e.id, { address: e.address || "", vendor: e.vendor_name || "" });
        });
      }

      setRegenItems((items || []).map((li: any) => ({
        id: li.id,
        billable_expense_id: li.billable_expense_id,
        include: true,
        date: li.date || "",
        description: li.description || "",
        category: li.category || "",
        address: li.billable_expense_id ? (addrMap.get(li.billable_expense_id)?.address || "") : "",
        vendor: li.billable_expense_id ? (addrMap.get(li.billable_expense_id)?.vendor || "") : "",
        quantity: Number(li.quantity || 1),
        unit_price: Number(li.unit_price || 0),
        amount: Number(li.amount || 0),
        is_credit: !!li.is_credit,
        receipt_url: li.billable_expense_id ? receiptMap.get(li.billable_expense_id) : undefined,
      })));
    } catch (err: any) {
      toast({ title: "Failed to load invoice items", description: err.message, variant: "destructive" });
    } finally {
      setRegenLoading(false);
    }
  };

  const updateRegenItem = (idx: number, patch: Partial<RegenItem>) => {
    setRegenItems(prev => {
      const next = [...prev];
      next[idx] = { ...next[idx], ...patch };
      if (patch.quantity !== undefined || patch.unit_price !== undefined) {
        const it = next[idx];
        const calc = it.quantity * it.unit_price;
        next[idx].amount = it.is_credit ? -Math.abs(calc) : Math.abs(calc);
      }
      if (patch.is_credit !== undefined) {
        next[idx].amount = patch.is_credit ? -Math.abs(next[idx].amount) : Math.abs(next[idx].amount);
      }
      return next;
    });
  };

  const removeRegenItem = (idx: number) => {
    setRegenItems(prev => prev.filter((_, i) => i !== idx));
  };

  const handleRegenerate = async () => {
    if (!regenInvoice) return;
    const included = regenItems.filter(i => i.include);
    if (!included.length) {
      toast({ title: "No items selected", variant: "destructive" });
      return;
    }
    setRegenerating(true);
    try {
      const charges = included.filter(i => !i.is_credit).reduce((s, i) => s + Math.abs(i.amount), 0);
      const credits = included.filter(i => i.is_credit).reduce((s, i) => s + Math.abs(i.amount), 0);
      const total = charges - credits;

      const { error: invErr } = await supabase
        .from("client_invoices")
        .update({
          amount: charges,
          credits,
          total,
          zoho_sync_status: "pending",
          zoho_sync_error: null,
        })
        .eq("id", regenInvoice.id);
      if (invErr) throw invErr;

      await supabase.from("client_invoice_items").delete().eq("invoice_id", regenInvoice.id);
      await supabase.from("client_invoice_items").insert(
        included.map(i => ({
          invoice_id: regenInvoice.id,
          billable_expense_id: i.billable_expense_id,
          description: i.description,
          category: i.category,
          date: i.date || null,
          quantity: i.quantity,
          unit_price: i.unit_price,
          amount: i.amount,
          is_credit: i.is_credit,
        }))
      );

      await Promise.all(included
        .filter(i => i.billable_expense_id)
        .map(i => supabase.from("billable_expenses").update({
          description: i.description || null,
          category: i.category || null,
          address: i.address || null,
          vendor_name: i.vendor || null,
          quantity: i.quantity,
          unit_price: i.unit_price,
          amount: i.amount,
          is_credit: i.is_credit,
        }).eq("id", i.billable_expense_id!))
      );

      const assoc = regenInvoice.associations;
      const { data: settings } = await supabase.from("company_settings").select("key, value");
      const getSetting = (key: string) => settings?.find((s: any) => s.key === key)?.value || "";

      await generateInvoicePdf({
        invoiceNumber: regenInvoice.invoice_number,
        invoiceDate: regenInvoice.issue_date || new Date().toISOString().split("T")[0],
        dueDate: regenInvoice.due_date || "",
        clientName: assoc?.name || "Client",
        clientAddress: assoc?.address || "",
        clientCity: assoc?.city || "",
        clientState: assoc?.state || "",
        clientZip: assoc?.zip || "",
        companyName: getSetting("company_name") || "Avria Community Management, LLC",
        companyAddress: getSetting("company_address") || "",
        companyEmail: getSetting("company_email") || assoc?.email || "",
        companyPhone: getSetting("company_phone") || assoc?.phone || "",
        companyWebsite: getSetting("company_website") || assoc?.website || "",
        logoUrl: getSetting("company_logo") || "",
        items: included.map(i => ({
          date: i.date ? format(new Date(i.date + "T12:00:00"), "MM/dd/yyyy") : "",
          description: i.description,
          category: i.category,
          quantity: i.quantity,
          unitPrice: i.unit_price,
          amount: i.amount,
          isCredit: i.is_credit,
          address: i.address || undefined,
          vendor: i.vendor || undefined,
          receiptUrl: i.receipt_url || undefined,
        })),
      });

      toast({ title: "Corrected invoice generated", description: `${regenInvoice.invoice_number} — receipts attached` });
      setRegenOpen(false);
      setRegenInvoice(null);
      setRegenItems([]);
      fetchInvoices();
    } catch (err: any) {
      console.error(err);
      toast({ title: "Failed to regenerate invoice", description: err.message, variant: "destructive" });
    } finally {
      setRegenerating(false);
    }
  };

  const updateStatus = async (id: string, status: string) => {
    const payload: any = { status };
    if (status === "paid") payload.paid_date = new Date().toISOString().split("T")[0];
    await supabase.from("client_invoices").update(payload).eq("id", id);
    toast({ title: `Invoice marked as ${status}` });
    fetchInvoices();
  };

  const handleDelete = async (id: string) => {
    await supabase.from("client_invoices").delete().eq("id", id);
    toast({ title: "Invoice deleted" });
    fetchInvoices();
  };

  const filtered = invoices.filter(i =>
    (i.associations?.name || "").toLowerCase().includes(search.toLowerCase()) ||
    i.invoice_number.toLowerCase().includes(search.toLowerCase())
  );

  const fmtCurrency = (v: number) => new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" }).format(v);

  return (
    <div className="space-y-6">
      <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
        <div>
          <h1 className="text-2xl font-bold text-foreground flex items-center gap-2">
            <FileText className="h-6 w-6 text-primary" /> Client Invoices
          </h1>
          <p className="text-sm text-muted-foreground mt-1">
            Invoices generated from billable expenses and the invoicing form.
          </p>
        </div>
      </div>

      <div className="relative max-w-md">
        <Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
        <Input placeholder="Search by client or invoice #..." className="pl-10" value={search} onChange={(e) => setSearch(e.target.value)} />
      </div>

      {loading ? (
        <div className="flex justify-center py-12"><div className="h-8 w-8 animate-spin rounded-full border-4 border-primary border-t-transparent" /></div>
      ) : filtered.length === 0 ? (
        <Card><CardContent className="py-12 text-center text-muted-foreground">
          No client invoices yet. Generate one from Billable Expenses or the Invoicing form under Forms & Letters.
        </CardContent></Card>
      ) : (
        <Card>
          <Table>
            <TableHeader>
              <TableRow>
                <TableHead>Invoice #</TableHead>
                <TableHead>Client</TableHead>
                <TableHead>Source</TableHead>
                <TableHead>Issue Date</TableHead>
                <TableHead>Due Date</TableHead>
                <TableHead className="text-right">Amount</TableHead>
                <TableHead>Status</TableHead>
                <TableHead className="text-right">Actions</TableHead>
              </TableRow>
            </TableHeader>
            <TableBody>
              {filtered.map(inv => (
                <TableRow key={inv.id}>
                  <TableCell className="font-mono font-semibold">{inv.invoice_number}</TableCell>
                  <TableCell>{inv.associations?.name || "—"}</TableCell>
                  <TableCell>
                    <Badge variant="outline" className="text-xs capitalize">
                      {inv.source === "billable_expenses" ? "Billable Expenses" : "Forms & Letters"}
                    </Badge>
                  </TableCell>
                  <TableCell>{inv.issue_date ? format(new Date(inv.issue_date), "MMM d, yyyy") : "—"}</TableCell>
                  <TableCell>{inv.due_date ? format(new Date(inv.due_date), "MMM d, yyyy") : "—"}</TableCell>
                  <TableCell className="text-right font-semibold">{fmtCurrency(Number(inv.total || 0))}</TableCell>
                  <TableCell>
                    <Badge className={`${statusColors[inv.status] || statusColors.draft} border-0`}>
                      {inv.status}
                    </Badge>
                  </TableCell>
                  <TableCell className="text-right">
                    <div className="flex justify-end gap-1">
                      <Button variant="ghost" size="icon" className="h-8 w-8" onClick={() => viewDetails(inv)} title="View details">
                        <Eye className="h-4 w-4" />
                      </Button>
                      <Button variant="ghost" size="icon" className="h-8 w-8 text-blue-600" onClick={() => openRegenerate(inv)} title="Regenerate corrected invoice (keeps invoice #, attaches receipts)">
                        <FileEdit className="h-4 w-4" />
                      </Button>
                      {inv.status !== "paid" && (
                        <Button variant="ghost" size="icon" className="h-8 w-8 text-emerald-600" onClick={() => updateStatus(inv.id, "paid")} title="Mark paid">
                          <DollarSign className="h-4 w-4" />
                        </Button>
                      )}
                      <Button variant="ghost" size="icon" className="h-8 w-8 text-destructive" onClick={() => handleDelete(inv.id)} title="Delete">
                        <Trash2 className="h-4 w-4" />
                      </Button>
                    </div>
                  </TableCell>
                </TableRow>
              ))}
            </TableBody>
          </Table>
        </Card>
      )}

      {/* Detail Dialog */}
      <Dialog open={detailOpen} onOpenChange={setDetailOpen}>
        <DialogContent className="sm:max-w-[600px]">
          <DialogHeader>
            <DialogTitle>Invoice {selectedInvoice?.invoice_number}</DialogTitle>
          </DialogHeader>
          {selectedInvoice && (
            <div className="space-y-4">
              <div className="grid grid-cols-2 gap-4 text-sm">
                <div>
                  <span className="text-muted-foreground">Client:</span>
                  <p className="font-semibold">{selectedInvoice.associations?.name || "—"}</p>
                </div>
                <div>
                  <span className="text-muted-foreground">Status:</span>
                  <p><Badge className={`${statusColors[selectedInvoice.status] || statusColors.draft} border-0`}>{selectedInvoice.status}</Badge></p>
                </div>
                <div>
                  <span className="text-muted-foreground">Issue Date:</span>
                  <p>{selectedInvoice.issue_date ? format(new Date(selectedInvoice.issue_date), "MMM d, yyyy") : "—"}</p>
                </div>
                <div>
                  <span className="text-muted-foreground">Due Date:</span>
                  <p>{selectedInvoice.due_date ? format(new Date(selectedInvoice.due_date), "MMM d, yyyy") : "—"}</p>
                </div>
              </div>

              {lineItems.length > 0 && (
                <Table>
                  <TableHeader>
                    <TableRow>
                      <TableHead>Description</TableHead>
                      <TableHead>Category</TableHead>
                      <TableHead className="text-right">Qty</TableHead>
                      <TableHead className="text-right">Amount</TableHead>
                    </TableRow>
                  </TableHeader>
                  <TableBody>
                    {lineItems.map(li => (
                      <TableRow key={li.id}>
                        <TableCell className={li.is_credit ? "text-destructive" : ""}>{li.description || "—"}</TableCell>
                        <TableCell>{li.category || "—"}</TableCell>
                        <TableCell className="text-right">{li.quantity}</TableCell>
                        <TableCell className={`text-right font-semibold ${li.is_credit ? "text-destructive" : ""}`}>
                          {li.is_credit ? "-" : ""}{fmtCurrency(Math.abs(Number(li.amount)))}
                        </TableCell>
                      </TableRow>
                    ))}
                  </TableBody>
                </Table>
              )}

              <div className="flex justify-between items-center pt-2 border-t">
                <span className="font-semibold">Total</span>
                <span className="text-lg font-bold">{fmtCurrency(Number(selectedInvoice.total))}</span>
              </div>

              {selectedInvoice.notes && (
                <p className="text-sm text-muted-foreground">{selectedInvoice.notes}</p>
              )}
            </div>
          )}
          <DialogFooter>
            <Button variant="outline" onClick={() => { if (selectedInvoice) downloadPdf(selectedInvoice); }}>
              <Download className="h-4 w-4 mr-1.5" /> Download PDF
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      {/* Regenerate (Corrected Invoice) Dialog */}
      <Dialog open={regenOpen} onOpenChange={setRegenOpen}>
        <DialogContent className="max-w-6xl max-h-[90vh] overflow-y-auto">
          <DialogHeader>
            <DialogTitle>Regenerate Invoice — {regenInvoice?.invoice_number}</DialogTitle>
            <DialogDescription>
              Edit line items and regenerate a corrected PDF. The invoice number stays the same and receipts are reattached.
            </DialogDescription>
          </DialogHeader>

          {regenLoading ? (
            <div className="flex justify-center py-12"><Loader2 className="h-8 w-8 animate-spin text-muted-foreground" /></div>
          ) : (
            <div className="space-y-4">
              <Table>
                <TableHeader>
                  <TableRow>
                    <TableHead className="w-10"></TableHead>
                    <TableHead className="w-32">Date</TableHead>
                    <TableHead>Description</TableHead>
                    <TableHead className="w-32">Category</TableHead>
                    <TableHead className="w-20 text-right">Qty</TableHead>
                    <TableHead className="w-24 text-right">Unit Price</TableHead>
                    <TableHead className="w-24 text-right">Amount</TableHead>
                    <TableHead className="w-16">Credit</TableHead>
                    <TableHead className="w-20">Receipt</TableHead>
                    <TableHead className="w-10"></TableHead>
                  </TableRow>
                </TableHeader>
                <TableBody>
                  {regenItems.map((item, idx) => (
                    <TableRow key={item.id} className={!item.include ? "opacity-40" : ""}>
                      <TableCell>
                        <Checkbox checked={item.include} onCheckedChange={(c) => updateRegenItem(idx, { include: !!c })} />
                      </TableCell>
                      <TableCell>
                        <Input type="date" value={item.date} onChange={e => updateRegenItem(idx, { date: e.target.value })} className="h-8" />
                      </TableCell>
                      <TableCell>
                        <Input value={item.description} onChange={e => updateRegenItem(idx, { description: e.target.value })} className="h-8" />
                      </TableCell>
                      <TableCell>
                        <Input value={item.category} onChange={e => updateRegenItem(idx, { category: e.target.value })} className="h-8" />
                      </TableCell>
                      <TableCell>
                        <Input type="number" step="0.01" value={item.quantity} onChange={e => updateRegenItem(idx, { quantity: parseFloat(e.target.value) || 0 })} className="h-8 text-right" />
                      </TableCell>
                      <TableCell>
                        <Input type="number" step="0.01" value={item.unit_price} onChange={e => updateRegenItem(idx, { unit_price: parseFloat(e.target.value) || 0 })} className="h-8 text-right" />
                      </TableCell>
                      <TableCell className="text-right font-medium">{fmtCurrency(item.amount)}</TableCell>
                      <TableCell>
                        <Checkbox checked={item.is_credit} onCheckedChange={(c) => updateRegenItem(idx, { is_credit: !!c })} />
                      </TableCell>
                      <TableCell>
                        {item.receipt_url ? (
                          <Badge variant="secondary" className="text-xs">Attached</Badge>
                        ) : (
                          <span className="text-xs text-muted-foreground">—</span>
                        )}
                      </TableCell>
                      <TableCell>
                        <Button variant="ghost" size="icon" className="h-8 w-8" onClick={() => removeRegenItem(idx)}>
                          <Trash2 className="h-4 w-4 text-destructive" />
                        </Button>
                      </TableCell>
                    </TableRow>
                  ))}
                </TableBody>
              </Table>

              <div className="flex justify-between items-center pt-2 border-t">
                <p className="text-xs text-muted-foreground">
                  Receipts from billable expenses will be appended to the PDF automatically.
                </p>
                <div className="text-right">
                  <div className="text-sm text-muted-foreground">New Total</div>
                  <div className="text-xl font-bold">
                    {fmtCurrency(
                      regenItems.filter(i => i.include).reduce((s, i) => s + (i.is_credit ? -Math.abs(i.amount) : Math.abs(i.amount)), 0)
                    )}
                  </div>
                </div>
              </div>
            </div>
          )}

          <DialogFooter>
            <Button variant="outline" onClick={() => setRegenOpen(false)} disabled={regenerating}>Cancel</Button>
            <Button onClick={handleRegenerate} disabled={regenerating || regenLoading}>
              {regenerating ? <><Loader2 className="h-4 w-4 mr-2 animate-spin" /> Regenerating…</> : <><FileEdit className="h-4 w-4 mr-2" /> Regenerate Invoice</>}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  );
}
