import { useState, useCallback } from "react";
import { supabase } from "@/integrations/supabase/client";
import { useToast } from "@/hooks/use-toast";
import ImportSpreadsheetDialog from "@/components/ImportSpreadsheetDialog";
import { Upload } from "lucide-react";
import { Button } from "@/components/ui/button";

const EXPECTED_COLUMNS = [
  { key: "unit", label: "Unit", required: true },
  { key: "date", label: "Date", required: true },
  { key: "type", label: "Type", required: true },
  { key: "amount", label: "Amount", required: true },
  { key: "description", label: "Description", required: false },
  { key: "account", label: "Account", required: false },
];

interface LedgerCSVImportDialogProps {
  onSuccess?: () => void;
  associationId?: string;
  /** If provided, restricts import to this unit only */
  unitId?: string;
}

export default function LedgerCSVImportDialog({ onSuccess, associationId, unitId }: LedgerCSVImportDialogProps) {
  const [open, setOpen] = useState(false);
  const { toast } = useToast();

  const handleImport = useCallback(async (rows: Record<string, string>[]) => {
    // 1. Gather unique unit identifiers from CSV
    const unitIdentifiers = [...new Set(rows.map((r) => (r.unit || "").trim()).filter(Boolean))];

    if (unitIdentifiers.length === 0) {
      throw new Error("No valid unit identifiers found in the CSV.");
    }

    // 2. Look up units by unit_number or account_number
    const { data: units, error: unitError } = await supabase
      .from("units")
      .select("id, unit_number, account_number, association_id")
      .or(`unit_number.in.(${unitIdentifiers.map((u) => `"${u}"`).join(",")}),account_number.in.(${unitIdentifiers.map((u) => `"${u}"`).join(",")})`)

    if (unitError) throw new Error(`Failed to look up units: ${unitError.message}`);

    const unitMap = new Map<string, { id: string; association_id: string }>();
    (units || []).forEach((u) => {
      if (u.unit_number) unitMap.set(u.unit_number.toLowerCase(), { id: u.id, association_id: u.association_id });
      if (u.account_number) unitMap.set(u.account_number.toLowerCase(), { id: u.id, association_id: u.association_id });
    });

    // 3. Look up primary owners for matched units
    const unitIds = [...new Set([...unitMap.values()].map((u) => u.id))];
    const { data: owners } = await supabase
      .from("owners")
      .select("id, unit_id")
      .in("unit_id", unitIds)
      .eq("status", "active");

    const ownerMap = new Map<string, string>();
    (owners || []).forEach((o) => {
      if (o.unit_id && !ownerMap.has(o.unit_id)) {
        ownerMap.set(o.unit_id, o.id);
      }
    });

    // 4. Build insert records
    const entries: any[] = [];
    const errors: string[] = [];

    rows.forEach((row, idx) => {
      const unitKey = (row.unit || "").trim().toLowerCase();
      const matched = unitMap.get(unitKey);

      if (!matched) {
        errors.push(`Row ${idx + 2}: Unit "${row.unit}" not found`);
        return;
      }

      if (unitId && matched.id !== unitId) {
        errors.push(`Row ${idx + 2}: Unit "${row.unit}" does not match current unit`);
        return;
      }

      const ownerId = ownerMap.get(matched.id);
      if (!ownerId) {
        errors.push(`Row ${idx + 2}: No active owner found for unit "${row.unit}"`);
        return;
      }

      const rawAmount = parseFloat((row.amount || "0").replace(/[$,]/g, ""));
      if (isNaN(rawAmount) || rawAmount === 0) {
        errors.push(`Row ${idx + 2}: Invalid amount "${row.amount}"`);
        return;
      }

      const rawType = (row.type || "").toLowerCase().trim();
      let transactionType = rawType;
      let debit = 0;
      let credit = 0;

      // Normalize type and assign debit/credit
      const debitTypes = ["assessment", "charge", "late_fee", "late fee", "interest", "fine", "debit", "fee", "violation", "admin_fee", "admin fee", "legal_fee", "legal fee", "bank_fee", "bank fee", "special_assessment", "special assessment"];
      const creditTypes = ["payment", "credit", "refund", "adjustment", "discount", "waiver", "prepayment", "prepay", "overpayment"];

      if (debitTypes.includes(rawType)) {
        debit = Math.abs(rawAmount);
        if (!["assessment", "charge", "late_fee", "interest", "fine", "fee", "violation", "admin_fee", "legal_fee", "bank_fee", "special_assessment"].includes(rawType.replace(/ /g, "_"))) {
          transactionType = "charge";
        } else {
          transactionType = rawType.replace(/ /g, "_");
        }
      } else if (creditTypes.includes(rawType)) {
        credit = Math.abs(rawAmount);
        if (["prepayment", "prepay", "overpayment"].includes(rawType)) {
          transactionType = "Prepayment";
        } else if (!["payment", "credit", "refund", "adjustment"].includes(rawType)) {
          transactionType = "payment";
        }
      } else {
        // Default: positive = debit/charge, negative = credit/payment
        if (rawAmount > 0) {
          debit = rawAmount;
          transactionType = rawType || "charge";
        } else {
          credit = Math.abs(rawAmount);
          transactionType = rawType || "payment";
        }
      }

      entries.push({
        unit_id: matched.id,
        owner_id: ownerId,
        association_id: associationId || matched.association_id,
        date: row.date || new Date().toISOString().split("T")[0],
        transaction_type: transactionType,
        description: row.description || row.account || transactionType,
        debit,
        credit,
      });
    });

    if (entries.length === 0) {
      throw new Error(`No valid entries to import.\n${errors.slice(0, 5).join("\n")}`);
    }

    // 5. Insert in batches of 100
    const batchSize = 100;
    let inserted = 0;
    for (let i = 0; i < entries.length; i += batchSize) {
      const batch = entries.slice(i, i + batchSize);
      const { error: insertError } = await supabase.from("owner_ledger_entries").insert(batch);
      if (insertError) throw new Error(`Insert failed at batch ${Math.floor(i / batchSize) + 1}: ${insertError.message}`);
      inserted += batch.length;
    }

    const msg = `Successfully imported ${inserted} ledger entries.`;
    if (errors.length > 0) {
      toast({
        title: `${inserted} imported, ${errors.length} skipped`,
        description: errors.slice(0, 3).join("; "),
        variant: "default",
      });
    } else {
      toast({ title: "Import Complete", description: msg });
    }

    onSuccess?.();
  }, [toast, onSuccess, associationId, unitId]);

  return (
    <>
      <Button variant="outline" className="gap-2" onClick={() => setOpen(true)}>
        <Upload className="h-4 w-4" /> Import Ledger CSV
      </Button>
      <ImportSpreadsheetDialog
        open={open}
        onOpenChange={setOpen}
        title="Import Ledger Transactions"
        description="Upload a CSV or Excel file with columns: Unit, Date, Type, Amount, Description (optional), Account (optional). Unit can be unit number or account number."
        expectedColumns={EXPECTED_COLUMNS}
        onImport={handleImport}
        templateFileName="ledger_import_template.xlsx"
      />
    </>
  );
}
