import { useState } from "react";
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { Textarea } from "@/components/ui/textarea";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Label } from "@/components/ui/label";
import { Upload, Loader2, CheckCircle2, AlertTriangle } from "lucide-react";
import { supabase } from "@/integrations/supabase/client";
import { useToast } from "@/hooks/use-toast";

interface ParsedAccount {
  accountLabel: string;
  accountNumber: string;
  ownerNames: string;
  balance: number;
  assessments: number;
  lateFees: number;
  interest: number;
  legalFees: number;
  adminFees: number;
  violations: number;
}

interface BuildiumARImportDialogProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  associations: { id: string; name: string }[];
  onImportComplete: () => void;
}

const FEE_MAP: Record<string, keyof Omit<ParsedAccount, "accountLabel" | "accountNumber" | "ownerNames" | "balance">> = {
  "assessment": "assessments",
  "legal": "legalFees",
  "violation": "violations",
  "administrative": "adminFees",
  "admin": "adminFees",
  "interest": "interest",
  "late": "lateFees",
};

function classifyFeeType(label: string): keyof Omit<ParsedAccount, "accountLabel" | "accountNumber" | "ownerNames" | "balance"> | null {
  const lower = label.toLowerCase();
  for (const [keyword, field] of Object.entries(FEE_MAP)) {
    if (lower.includes(keyword)) return field;
  }
  return null;
}

function parseBuildiumAR(text: string): ParsedAccount[] {
  const lines = text.trim().split("\n");
  const accounts: ParsedAccount[] = [];
  let current: ParsedAccount | null = null;

  const FEE_PATTERNS: [RegExp, keyof Omit<ParsedAccount, "accountLabel" | "accountNumber" | "ownerNames" | "balance">][] = [
    [/^assessments?/i, "assessments"],
    [/^late\s*fee/i, "lateFees"],
    [/^interest/i, "interest"],
    [/^legal\s*fee/i, "legalFees"],
    [/^admin(istrative)?\s*fee/i, "adminFees"],
    [/^violation/i, "violations"],
  ];

  const skipLine = (s: string) =>
    /^(ACCOUNT|PAST DUE|0\s*-\s*30|31\s*-\s*60|61\s*-\s*90|90\+|BALANCE|IN FORECLOSURE|Sent on|Total|Grand Total)/i.test(s);

  for (const line of lines) {
    const trimmed = line.trim();
    if (!trimmed || skipLine(trimmed)) continue;

    // 1) Check if this is a standalone fee line like "Assessments $4,651.00"
    const feeLineMatch = trimmed.match(/^(.+?)\s+\$[\d,]+\.?\d*/);
    if (feeLineMatch) {
      const label = feeLineMatch[1].trim();
      const matched = FEE_PATTERNS.find(([re]) => re.test(label));
      if (matched && current) {
        const amountMatch = trimmed.match(/\$([\d,]+\.?\d*)/);
        const amount = amountMatch ? parseFloat(amountMatch[1].replace(/,/g, "")) : 0;
        current[matched[1]] += amount;
        continue;
      }
    }

    // 2) Check for "Operating Income" / "Other Income" sub-row format (legacy Buildium)
    const opIncomeMatch = trimmed.match(/^(?:Operating Income|Other Income)\s*-\s*\d+\s+(.*)/i);
    if (opIncomeMatch && current) {
      const feeLabel = opIncomeMatch[1];
      const amountMatch = trimmed.match(/\$([\d,]+\.?\d*)/);
      const amount = amountMatch ? parseFloat(amountMatch[1].replace(/,/g, "")) : 0;
      const field = classifyFeeType(feeLabel);
      if (field && amount > 0) current[field] += amount;
      continue;
    }

    // 3) Check if this is a dollar-amount row with account info before it
    const dollarAmounts = trimmed.match(/\$([\d,]+\.?\d*)/g);
    if (dollarAmounts && dollarAmounts.length >= 1) {
      const beforeDollar = trimmed.split(/\$[\d,]+\.?\d*/)[0].trim();
      if (beforeDollar.length > 3) {
        // Save previous account
        if (current) {
          if (current.balance === 0) {
            current.balance = current.assessments + current.lateFees + current.interest + current.legalFees + current.adminFees + current.violations;
          }
          accounts.push(current);
        }
        const acctNumMatch = beforeDollar.match(/\b(\d{5,10})\b/);
        const accountNumber = acctNumMatch ? acctNumMatch[1] : "";
        const pipeIdx = beforeDollar.indexOf("|");
        let ownerNames = "";
        let accountLabel = beforeDollar;
        if (pipeIdx > -1) {
          accountLabel = beforeDollar.substring(0, pipeIdx).trim();
          ownerNames = beforeDollar.substring(pipeIdx + 1).replace(/\d{5,10}/, "").trim();
        }
        const totalBalance = parseFloat(dollarAmounts[dollarAmounts.length - 1].replace(/[$,]/g, "")) || 0;
        current = { accountLabel, accountNumber, ownerNames, balance: totalBalance, assessments: 0, lateFees: 0, interest: 0, legalFees: 0, adminFees: 0, violations: 0 };
        continue;
      }
    }

    // 4) Account identifier line (no dollar sign) like "2455-VL 224897"
    if (!trimmed.includes("$")) {
      const acctNumMatch = trimmed.match(/\b(\d{5,10})\b/);
      // If it has an account number or looks like a unit identifier, start a new account
      if (acctNumMatch || /^[\w-]+\s+\d{4,}/.test(trimmed)) {
        if (current) {
          if (current.balance === 0) {
            current.balance = current.assessments + current.lateFees + current.interest + current.legalFees + current.adminFees + current.violations;
          }
          accounts.push(current);
        }
        const accountNumber = acctNumMatch ? acctNumMatch[1] : "";
        const accountLabel = trimmed.replace(accountNumber, "").trim();
        current = { accountLabel, accountNumber, ownerNames: "", balance: 0, assessments: 0, lateFees: 0, interest: 0, legalFees: 0, adminFees: 0, violations: 0 };
        continue;
      }
      // Standalone account number on its own line
      if (current && /^\d{5,10}$/.test(trimmed)) {
        current.accountNumber = trimmed;
        continue;
      }
    }
  }

  // Push last account
  if (current) {
    if (current.balance === 0) {
      current.balance = current.assessments + current.lateFees + current.interest + current.legalFees + current.adminFees + current.violations;
    }
    accounts.push(current);
  }

  return accounts;
}

const fmt = (n: number) => `$${n.toLocaleString(undefined, { minimumFractionDigits: 2 })}`;

export default function BuildiumARImportDialog({ open, onOpenChange, associations, onImportComplete }: BuildiumARImportDialogProps) {
  const { toast } = useToast();
  const [csvText, setCsvText] = useState("");
  const [parsed, setParsed] = useState<ParsedAccount[]>([]);
  const [selectedAssociation, setSelectedAssociation] = useState("");
  const [importing, setImporting] = useState(false);
  const [imported, setImported] = useState(false);

  const handleParse = () => {
    const results = parseBuildiumAR(csvText);
    if (results.length === 0) {
      toast({ variant: "destructive", title: "No accounts found", description: "Could not parse any account data. Make sure you've pasted the Buildium AR aging data." });
      return;
    }
    setParsed(results);
    toast({ title: `Parsed ${results.length} account(s)` });
  };

  const handleImport = async () => {
    if (!selectedAssociation) {
      toast({ variant: "destructive", title: "Select an association" });
      return;
    }
    setImporting(true);
    try {
      // For each parsed account, find matching owner by unit account_number or name, then insert ledger entries
      const { data: owners } = await supabase
        .from("owners")
        .select("id, first_name, last_name, association_id, unit_id, units(account_number)")
        .eq("association_id", selectedAssociation)
        .neq("status", "archived");

      const entries: any[] = [];
      const unmatched: string[] = [];

      for (const acct of parsed) {
        // Try to match by unit account number first, then by name
        let matchedOwner = (owners || []).find((o: any) => {
          const unitAcct = o.units?.account_number;
          return unitAcct && unitAcct === acct.accountNumber;
        });
        if (!matchedOwner && acct.ownerNames) {
          const nameLower = acct.ownerNames.toLowerCase();
          matchedOwner = (owners || []).find((o: any) => {
            return nameLower.includes((o.last_name || "").toLowerCase()) && nameLower.includes((o.first_name || "").toLowerCase());
          });
        }

        if (!matchedOwner) {
          unmatched.push(acct.ownerNames || acct.accountNumber || acct.accountLabel);
          continue;
        }

        const ownerId = (matchedOwner as any).id;
        const today = new Date().toISOString().split("T")[0];

        const feeTypes = [
          { type: "Assessment", amount: acct.assessments },
          { type: "Late Fee", amount: acct.lateFees },
          { type: "Interest", amount: acct.interest },
          { type: "Legal Fee", amount: acct.legalFees },
          { type: "Admin Fee", amount: acct.adminFees },
          { type: "Violation", amount: acct.violations },
        ];

        for (const fee of feeTypes) {
          if (fee.amount > 0) {
            entries.push({
              owner_id: ownerId,
              association_id: selectedAssociation,
              transaction_type: fee.type,
              description: `Buildium AR Import - ${fee.type}`,
              debit: fee.amount,
              credit: 0,
              date: today,
            });
          }
        }
      }

      if (entries.length > 0) {
        const { error } = await supabase.from("owner_ledger_entries").insert(entries);
        if (error) throw error;
      }

      // Update owner balances
      const ownerIds = [...new Set(entries.map(e => e.owner_id))];
      for (const oid of ownerIds) {
        const { data: ledger } = await supabase
          .from("owner_ledger_entries")
          .select("debit, credit")
          .eq("owner_id", oid);
        const bal = (ledger || []).reduce((s, e) => s + (e.debit || 0) - (e.credit || 0), 0);
        await supabase.from("owners").update({ balance: bal }).eq("id", oid);
      }

      let msg = `Imported ${entries.length} ledger entries for ${ownerIds.length} owner(s).`;
      if (unmatched.length > 0) {
        msg += ` ${unmatched.length} account(s) could not be matched: ${unmatched.join(", ")}`;
      }
      toast({ title: "Import Complete", description: msg });
      setImported(true);
      onImportComplete();
    } catch (err: any) {
      toast({ variant: "destructive", title: "Import Error", description: err.message });
    } finally {
      setImporting(false);
    }
  };

  const handleClose = (val: boolean) => {
    if (!val) {
      setCsvText("");
      setParsed([]);
      setImported(false);
      setSelectedAssociation("");
    }
    onOpenChange(val);
  };

  return (
    <Dialog open={open} onOpenChange={handleClose}>
      <DialogContent className="max-w-4xl max-h-[85vh] overflow-y-auto">
        <DialogHeader>
          <DialogTitle>Import Buildium AR Aging</DialogTitle>
          <DialogDescription>
            Paste the Buildium Outstanding Balances / AR Aging data directly from the Buildium page. The system will parse account rows and fee category breakdowns.
          </DialogDescription>
        </DialogHeader>

        <div className="space-y-4">
          <div>
            <Label>Association</Label>
            <Select value={selectedAssociation} onValueChange={setSelectedAssociation}>
              <SelectTrigger><SelectValue placeholder="Select association..." /></SelectTrigger>
              <SelectContent>
                {associations.map(a => (
                  <SelectItem key={a.id} value={a.id}>{a.name}</SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>

          <div>
            <Label>Paste Buildium Data</Label>
            <Textarea
              placeholder="Paste the Buildium AR aging table content here..."
              value={csvText}
              onChange={(e) => { setCsvText(e.target.value); setParsed([]); setImported(false); }}
              rows={8}
            />
          </div>

          <Button onClick={handleParse} className="gap-2" disabled={!csvText.trim()}>
            <Upload className="h-4 w-4" /> Parse Data
          </Button>

          {parsed.length > 0 && (
            <div className="space-y-3">
              <p className="text-sm font-medium">{parsed.length} account(s) found:</p>
              <div className="overflow-x-auto border rounded-md">
                <Table>
                  <TableHeader>
                    <TableRow>
                      <TableHead>Account / Owner</TableHead>
                      <TableHead className="text-right">Assessments</TableHead>
                      <TableHead className="text-right">Late Fees</TableHead>
                      <TableHead className="text-right">Interest</TableHead>
                      <TableHead className="text-right">Legal</TableHead>
                      <TableHead className="text-right">Admin</TableHead>
                      <TableHead className="text-right">Violations</TableHead>
                      <TableHead className="text-right">Balance</TableHead>
                    </TableRow>
                  </TableHeader>
                  <TableBody>
                    {parsed.map((a, i) => (
                      <TableRow key={i}>
                        <TableCell>
                          <div className="font-medium text-sm">{a.ownerNames || a.accountLabel}</div>
                          {a.accountNumber && <div className="text-xs text-muted-foreground">Acct: {a.accountNumber}</div>}
                        </TableCell>
                        <TableCell className="text-right tabular-nums">{fmt(a.assessments)}</TableCell>
                        <TableCell className="text-right tabular-nums">{fmt(a.lateFees)}</TableCell>
                        <TableCell className="text-right tabular-nums">{fmt(a.interest)}</TableCell>
                        <TableCell className="text-right tabular-nums">{fmt(a.legalFees)}</TableCell>
                        <TableCell className="text-right tabular-nums">{fmt(a.adminFees)}</TableCell>
                        <TableCell className="text-right tabular-nums">{fmt(a.violations)}</TableCell>
                        <TableCell className="text-right tabular-nums font-semibold">{fmt(a.balance)}</TableCell>
                      </TableRow>
                    ))}
                  </TableBody>
                </Table>
              </div>

              {imported ? (
                <div className="flex items-center gap-2 text-emerald-600">
                  <CheckCircle2 className="h-5 w-5" /> Successfully imported!
                </div>
              ) : (
                <Button onClick={handleImport} disabled={importing || !selectedAssociation} className="gap-2">
                  {importing ? <Loader2 className="h-4 w-4 animate-spin" /> : <Upload className="h-4 w-4" />}
                  {importing ? "Importing..." : "Import All"}
                </Button>
              )}
            </div>
          )}
        </div>
      </DialogContent>
    </Dialog>
  );
}
