import { useEffect, useMemo, useState } from "react";
import { useNavigate, useSearchParams } from "react-router-dom";
import { supabase } from "@/integrations/supabase/client";
import { invokeEdgeFunction } from "@/lib/edgeFunctionUtils";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { Checkbox } from "@/components/ui/checkbox";
import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs";
import { ScrollArea } from "@/components/ui/scroll-area";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { useToast } from "@/hooks/use-toast";
import { ArrowLeft, CheckCircle2, XCircle, Loader2, RefreshCw, Trash2 } from "lucide-react";

type StagingRow = {
  id: string;
  batch_id: string;
  association_id: string | null;
  kind: "unit" | "owner" | "gl_account" | "ledger_entry" | "arc_application";
  action: "create" | "update" | "unchanged";
  external_id: string | null;
  match_id: string | null;
  summary: string | null;
  payload: any;
  diff: any;
  status: "pending" | "approved" | "rejected" | "applied" | "failed";
  apply_error: string | null;
  created_at: string;
};

const KIND_LABELS: Record<string, string> = {
  unit: "Units",
  owner: "Owners",
  gl_account: "GL Accounts",
  ledger_entry: "Ledger Entries",
  arc_application: "ARC Applications",
};

const STATUS_VARIANTS: Record<string, "default" | "secondary" | "destructive" | "outline"> = {
  pending: "secondary",
  approved: "default",
  rejected: "outline",
  applied: "default",
  failed: "destructive",
};

export default function BuildiumImportReviewPage() {
  const navigate = useNavigate();
  const [searchParams] = useSearchParams();
  const initialBatch = searchParams.get("batch_id") || "";
  const { toast } = useToast();

  const [batches, setBatches] = useState<{ batch_id: string; created_at: string; total: number; pending: number }[]>([]);
  const [batchId, setBatchId] = useState<string>(initialBatch);
  const [rows, setRows] = useState<StagingRow[]>([]);
  const [loading, setLoading] = useState(false);
  const [applying, setApplying] = useState(false);
  const [selected, setSelected] = useState<Set<string>>(new Set());
  const [activeKind, setActiveKind] = useState<string>("unit");

  async function loadBatches() {
    const { data } = await supabase
      .from("buildium_import_staging")
      .select("batch_id, created_at, status")
      .order("created_at", { ascending: false })
      .limit(2000);
    const map = new Map<string, { created_at: string; total: number; pending: number }>();
    for (const r of (data || []) as any[]) {
      const m = map.get(r.batch_id) || { created_at: r.created_at, total: 0, pending: 0 };
      m.total += 1;
      if (r.status === "pending") m.pending += 1;
      if (r.created_at > m.created_at) m.created_at = r.created_at;
      map.set(r.batch_id, m);
    }
    const list = Array.from(map.entries()).map(([batch_id, v]) => ({ batch_id, ...v }));
    list.sort((a, b) => (a.created_at < b.created_at ? 1 : -1));
    setBatches(list);
    if (!batchId && list.length > 0) setBatchId(list[0].batch_id);
  }

  async function loadRows(bId: string) {
    if (!bId) return;
    setLoading(true);
    const { data, error } = await supabase
      .from("buildium_import_staging")
      .select("*")
      .eq("batch_id", bId)
      .order("kind", { ascending: true })
      .order("created_at", { ascending: true })
      .limit(10000);
    if (error) {
      toast({ variant: "destructive", title: "Load failed", description: error.message });
    } else {
      setRows((data || []) as StagingRow[]);
    }
    setSelected(new Set());
    setLoading(false);
  }

  useEffect(() => { loadBatches(); }, []);
  useEffect(() => { if (batchId) loadRows(batchId); }, [batchId]);

  const counts = useMemo(() => {
    const c: Record<string, { total: number; pending: number; approved: number; rejected: number; applied: number; failed: number }> = {};
    for (const k of Object.keys(KIND_LABELS)) c[k] = { total: 0, pending: 0, approved: 0, rejected: 0, applied: 0, failed: 0 };
    for (const r of rows) {
      if (!c[r.kind]) continue;
      c[r.kind].total += 1;
      c[r.kind][r.status as keyof typeof c[string]] += 1;
    }
    return c;
  }, [rows]);

  const visibleRows = useMemo(() => rows.filter((r) => r.kind === activeKind), [rows, activeKind]);

  const toggleAll = () => {
    const visible = visibleRows.filter((r) => r.status === "pending");
    if (visible.every((r) => selected.has(r.id))) {
      const next = new Set(selected);
      for (const r of visible) next.delete(r.id);
      setSelected(next);
    } else {
      const next = new Set(selected);
      for (const r of visible) next.add(r.id);
      setSelected(next);
    }
  };

  async function setStatus(ids: string[], status: "approved" | "rejected" | "pending") {
    if (ids.length === 0) return;
    const { error } = await supabase
      .from("buildium_import_staging")
      .update({ status, reviewed_at: new Date().toISOString() })
      .in("id", ids);
    if (error) {
      toast({ variant: "destructive", title: "Update failed", description: error.message });
      return;
    }
    setRows((prev) => prev.map((r) => (ids.includes(r.id) ? { ...r, status } : r)));
  }

  async function approveAllPendingForKind() {
    const ids = visibleRows.filter((r) => r.status === "pending").map((r) => r.id);
    await setStatus(ids, "approved");
    toast({ title: `Approved ${ids.length} ${KIND_LABELS[activeKind]}` });
  }

  async function rejectAllPendingForKind() {
    const ids = visibleRows.filter((r) => r.status === "pending").map((r) => r.id);
    await setStatus(ids, "rejected");
    toast({ title: `Rejected ${ids.length} ${KIND_LABELS[activeKind]}` });
  }

  async function applyApproved() {
    setApplying(true);
    try {
      const { data, error } = await invokeEdgeFunction("buildium-import-apply", {
        body: { batch_id: batchId },
      });
      if (error) throw error;
      toast({
        title: "Apply complete",
        description: `${data.applied} applied, ${data.failed} failed`,
      });
      await loadRows(batchId);
      await loadBatches();
    } catch (e: any) {
      toast({ variant: "destructive", title: "Apply failed", description: e?.message || String(e) });
    } finally {
      setApplying(false);
    }
  }

  async function deleteBatch() {
    if (!batchId) return;
    if (!confirm("Discard this entire review batch? Approved/applied rows will also be removed.")) return;
    const { error } = await supabase.from("buildium_import_staging").delete().eq("batch_id", batchId);
    if (error) {
      toast({ variant: "destructive", title: "Delete failed", description: error.message });
      return;
    }
    toast({ title: "Batch discarded" });
    setBatchId("");
    setRows([]);
    await loadBatches();
  }

  const totalPending = rows.filter((r) => r.status === "pending").length;
  const totalApproved = rows.filter((r) => r.status === "approved").length;

  return (
    <div className="space-y-6">
      <div className="flex items-center gap-2">
        <Button variant="ghost" size="sm" onClick={() => navigate("/dashboard/settings/buildium")}>
          <ArrowLeft className="h-4 w-4 mr-1" /> Back
        </Button>
        <h1 className="text-2xl font-bold">Review Buildium Imports</h1>
      </div>

      <Card>
        <CardHeader>
          <CardTitle className="text-base">Batch</CardTitle>
        </CardHeader>
        <CardContent className="space-y-3">
          {batches.length === 0 ? (
            <p className="text-sm text-muted-foreground">No staged imports yet. Run a Pull from the Buildium settings page.</p>
          ) : (
            <>
              <div className="flex flex-wrap gap-2">
                {batches.slice(0, 8).map((b) => (
                  <Button
                    key={b.batch_id}
                    size="sm"
                    variant={b.batch_id === batchId ? "default" : "outline"}
                    onClick={() => setBatchId(b.batch_id)}
                  >
                    {new Date(b.created_at).toLocaleString()} <span className="ml-2 text-xs opacity-70">({b.pending}/{b.total})</span>
                  </Button>
                ))}
              </div>
              {batchId && (
                <div className="flex flex-wrap items-center gap-2">
                  <Button size="sm" variant="outline" onClick={() => loadRows(batchId)} disabled={loading}>
                    <RefreshCw className="h-4 w-4 mr-1" /> Refresh
                  </Button>
                  <Button size="sm" onClick={applyApproved} disabled={applying || totalApproved === 0}>
                    {applying ? <Loader2 className="h-4 w-4 mr-1 animate-spin" /> : <CheckCircle2 className="h-4 w-4 mr-1" />}
                    Apply {totalApproved} approved
                  </Button>
                  <Button size="sm" variant="ghost" onClick={deleteBatch}>
                    <Trash2 className="h-4 w-4 mr-1" /> Discard batch
                  </Button>
                  <span className="ml-auto text-sm text-muted-foreground">
                    {totalPending} pending · {totalApproved} approved
                  </span>
                </div>
              )}
            </>
          )}
        </CardContent>
      </Card>

      {batchId && rows.length > 0 && (
        <Tabs value={activeKind} onValueChange={setActiveKind}>
          <TabsList>
            {Object.entries(KIND_LABELS).map(([k, label]) => (
              <TabsTrigger key={k} value={k}>
                {label} <Badge variant="secondary" className="ml-2">{counts[k]?.total || 0}</Badge>
              </TabsTrigger>
            ))}
          </TabsList>

          {Object.keys(KIND_LABELS).map((k) => (
            <TabsContent key={k} value={k} className="space-y-3">
              <div className="flex flex-wrap items-center gap-2">
                <Button size="sm" variant="outline" onClick={approveAllPendingForKind} disabled={counts[k]?.pending === 0}>
                  Approve all pending ({counts[k]?.pending || 0})
                </Button>
                <Button size="sm" variant="outline" onClick={rejectAllPendingForKind} disabled={counts[k]?.pending === 0}>
                  Reject all pending
                </Button>
                {selected.size > 0 && (
                  <>
                    <Button size="sm" onClick={() => setStatus(Array.from(selected), "approved")}>
                      Approve selected ({selected.size})
                    </Button>
                    <Button size="sm" variant="outline" onClick={() => setStatus(Array.from(selected), "rejected")}>
                      Reject selected
                    </Button>
                  </>
                )}
              </div>

              <Card>
                <ScrollArea className="h-[60vh]">
                  <Table>
                    <TableHeader>
                      <TableRow>
                        <TableHead className="w-10">
                          <Checkbox
                            checked={visibleRows.length > 0 && visibleRows.filter((r) => r.status === "pending").every((r) => selected.has(r.id))}
                            onCheckedChange={toggleAll}
                          />
                        </TableHead>
                        <TableHead>Action</TableHead>
                        <TableHead>Summary</TableHead>
                        <TableHead>Changes</TableHead>
                        <TableHead>Status</TableHead>
                        <TableHead className="text-right">Decision</TableHead>
                      </TableRow>
                    </TableHeader>
                    <TableBody>
                      {visibleRows.length === 0 ? (
                        <TableRow>
                          <TableCell colSpan={6} className="text-center text-sm text-muted-foreground">
                            No {KIND_LABELS[k]} in this batch.
                          </TableCell>
                        </TableRow>
                      ) : (
                        visibleRows.map((r) => (
                          <TableRow key={r.id}>
                            <TableCell>
                              <Checkbox
                                disabled={r.status !== "pending"}
                                checked={selected.has(r.id)}
                                onCheckedChange={(c) => {
                                  const next = new Set(selected);
                                  if (c) next.add(r.id); else next.delete(r.id);
                                  setSelected(next);
                                }}
                              />
                            </TableCell>
                            <TableCell>
                              <Badge variant={r.action === "create" ? "default" : "outline"}>{r.action}</Badge>
                            </TableCell>
                            <TableCell className="max-w-md truncate" title={r.summary || ""}>
                              {r.summary}
                            </TableCell>
                            <TableCell className="text-xs max-w-sm">
                              {r.action === "create" ? (
                                <span className="text-muted-foreground">New record</span>
                              ) : r.diff ? (
                                <div className="space-y-0.5">
                                  {Object.entries(r.diff as Record<string, { from: any; to: any }>).slice(0, 4).map(([field, d]) => (
                                    <div key={field}>
                                      <span className="font-medium">{field}:</span>{" "}
                                      <span className="text-muted-foreground line-through">{String(d.from ?? "—")}</span>{" → "}
                                      <span>{String(d.to ?? "—")}</span>
                                    </div>
                                  ))}
                                  {Object.keys(r.diff).length > 4 && (
                                    <div className="text-muted-foreground">+{Object.keys(r.diff).length - 4} more</div>
                                  )}
                                </div>
                              ) : null}
                            </TableCell>
                            <TableCell>
                              <Badge variant={STATUS_VARIANTS[r.status] || "secondary"}>{r.status}</Badge>
                              {r.apply_error && (
                                <div className="text-xs text-destructive mt-1 max-w-xs truncate" title={r.apply_error}>
                                  {r.apply_error}
                                </div>
                              )}
                            </TableCell>
                            <TableCell className="text-right">
                              {r.status === "pending" && (
                                <div className="flex justify-end gap-1">
                                  <Button size="sm" variant="ghost" onClick={() => setStatus([r.id], "approved")}>
                                    <CheckCircle2 className="h-4 w-4 text-green-600" />
                                  </Button>
                                  <Button size="sm" variant="ghost" onClick={() => setStatus([r.id], "rejected")}>
                                    <XCircle className="h-4 w-4 text-destructive" />
                                  </Button>
                                </div>
                              )}
                              {(r.status === "approved" || r.status === "rejected") && (
                                <Button size="sm" variant="ghost" onClick={() => setStatus([r.id], "pending")}>
                                  Reset
                                </Button>
                              )}
                            </TableCell>
                          </TableRow>
                        ))
                      )}
                    </TableBody>
                  </Table>
                </ScrollArea>
              </Card>
            </TabsContent>
          ))}
        </Tabs>
      )}
    </div>
  );
}
