import { useEffect, useMemo, useState } from "react";
import ImportSpreadsheetDialog from "@/components/ImportSpreadsheetDialog";
import { supabase } from "@/integrations/supabase/client";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Label } from "@/components/ui/label";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { Badge } from "@/components/ui/badge";
import { useToast } from "@/hooks/use-toast";
import { Download, Upload, Home as HomeIcon } from "lucide-react";

const PAGE_SIZE = 1000;

const normalize = (value: string | null | undefined) =>
  String(value ?? "").trim().replace(/\s+/g, " ").toLowerCase();

const nullable = (value: string | null | undefined) => {
  const trimmed = String(value ?? "").trim();
  return trimmed ? trimmed : null;
};

const parseBool = (value: string | null | undefined): boolean | null => {
  const v = normalize(value);
  if (!v) return null;
  if (["true", "yes", "y", "1", "rental"].includes(v)) return true;
  if (["false", "no", "n", "0", "owner-occupied", "owner occupied"].includes(v)) return false;
  return null;
};

interface Association { id: string; name: string }
interface UnitLookup {
  id: string;
  unit_number: string;
  address: string | null;
  account_number: string | null;
  parcel_id: string | null;
  lot: string | null;
  status: string | null;
  is_rental: boolean | null;
}

export default function BulkUnitUpdatesTab() {
  const { toast } = useToast();
  const [associations, setAssociations] = useState<Association[]>([]);
  const [selectedAssociation, setSelectedAssociation] = useState("");
  const [units, setUnits] = useState<UnitLookup[]>([]);
  const [loading, setLoading] = useState(false);
  const [importOpen, setImportOpen] = useState(false);
  const [lastResult, setLastResult] = useState<{ updated: number; skipped: number } | null>(null);

  useEffect(() => {
    supabase.from("associations").select("id, name").eq("status", "active").order("name").then(({ data }) => {
      setAssociations(data || []);
      if (data?.[0]) setSelectedAssociation(data[0].id);
    });
  }, []);

  useEffect(() => {
    if (selectedAssociation) fetchUnits();
  }, [selectedAssociation]);

  const fetchUnits = async () => {
    setLoading(true);
    const all: UnitLookup[] = [];
    for (let from = 0; ; from += PAGE_SIZE) {
      const { data, error } = await supabase
        .from("units")
        .select("id, unit_number, address, account_number, parcel_id, lot, status, is_rental")
        .eq("association_id", selectedAssociation)
        .neq("status", "archived")
        .order("unit_number")
        .range(from, from + PAGE_SIZE - 1);
      if (error) {
        toast({ title: "Error loading units", description: error.message, variant: "destructive" });
        break;
      }
      if (!data?.length) break;
      all.push(...(data as UnitLookup[]));
      if (data.length < PAGE_SIZE) break;
    }
    setUnits(all);
    setLoading(false);
  };

  const lookupMaps = useMemo(() => {
    const byId = new Map<string, string>();
    const byAccount = new Map<string, string>();
    const byUnitNumber = new Map<string, string>();
    const byAddress = new Map<string, string>();
    const byParcel = new Map<string, string>();
    units.forEach((u) => {
      byId.set(u.id, u.id);
      if (u.account_number) byAccount.set(normalize(u.account_number), u.id);
      if (u.unit_number) byUnitNumber.set(normalize(u.unit_number), u.id);
      if (u.address) byAddress.set(normalize(u.address), u.id);
      if (u.parcel_id) byParcel.set(normalize(u.parcel_id), u.id);
    });
    return { byId, byAccount, byUnitNumber, byAddress, byParcel };
  }, [units]);

  const handleImportUpdates = async (rows: Record<string, string>[]) => {
    const updates: Array<{ id: string; payload: Record<string, unknown> }> = [];
    let skipped = 0;

    rows.forEach((row) => {
      const id = nullable(row.unit_id);
      const matchedId =
        (id && lookupMaps.byId.get(id)) ||
        (nullable(row.account_number) && lookupMaps.byAccount.get(normalize(row.account_number))) ||
        (nullable(row.parcel_id) && lookupMaps.byParcel.get(normalize(row.parcel_id))) ||
        (nullable(row.unit_number) && lookupMaps.byUnitNumber.get(normalize(row.unit_number))) ||
        (nullable(row.address) && lookupMaps.byAddress.get(normalize(row.address)));

      if (!matchedId) {
        skipped += 1;
        return;
      }

      const payload: Record<string, unknown> = { updated_at: new Date().toISOString() };
      const newUnitNumber = nullable(row.new_unit_number);
      if (newUnitNumber) payload.unit_number = newUnitNumber;

      ["address", "city", "state", "zip", "account_number", "parcel_id", "lot", "image_url"].forEach((field) => {
        const value = nullable(row[field]);
        if (value !== null) payload[field] = value;
      });

      const status = nullable(row.status);
      if (status && ["active", "inactive", "delinquent", "archived"].includes(status.toLowerCase())) {
        payload.status = status.toLowerCase();
      }

      const rental = parseBool(row.is_rental);
      if (rental !== null) payload.is_rental = rental;

      ["bedrooms", "sqft"].forEach((field) => {
        const v = nullable(row[field]);
        if (v !== null && !Number.isNaN(Number(v))) payload[field] = Number(v);
      });
      const bath = nullable(row.bathrooms);
      if (bath !== null && !Number.isNaN(Number(bath))) payload.bathrooms = Number(bath);

      const monthly = nullable(row.monthly_assessment);
      if (monthly !== null && !Number.isNaN(Number(monthly))) payload.monthly_assessment = Number(monthly);

      if (Object.keys(payload).length > 1) updates.push({ id: matchedId, payload });
      else skipped += 1;
    });

    for (let i = 0; i < updates.length; i += 25) {
      const results = await Promise.all(updates.slice(i, i + 25).map(({ id, payload }) => supabase.from("units").update(payload).eq("id", id)));
      const failed = results.find((result) => result.error);
      if (failed?.error) throw failed.error;
    }

    setLastResult({ updated: updates.length, skipped });
    toast({ title: "Bulk update complete", description: `${updates.length} units updated, ${skipped} rows skipped.` });
    await fetchUnits();
  };

  const handleExportTemplate = async () => {
    const csv = [
      "Unit ID,Unit Number,New Unit Number,Account Number,Parcel ID,Lot,Address,City,State,Zip,Status,Is Rental,Bedrooms,Bathrooms,Sqft,Monthly Assessment,Image URL",
      ...units.map((u) => [
        u.id,
        u.unit_number || "",
        "",
        u.account_number || "",
        u.parcel_id || "",
        u.lot || "",
        u.address || "",
        "", "", "",
        u.status || "",
        u.is_rental ? "true" : "false",
        "", "", "", "", "",
      ].map((v) => `"${String(v).replace(/"/g, '""')}"`).join(",")),
    ].join("\n");
    const { saveFile } = await import("@/lib/saveFile");
    await saveFile(new Blob([csv], { type: "text/csv" }), { suggestedName: "bulk_unit_updates.csv", mimeType: "text/csv", description: "CSV file" });
  };

  return (
    <div className="space-y-6">
      <p className="text-sm text-muted-foreground">Update unit address, account number, parcel ID, rental status, and more from a spreadsheet without creating new unit records.</p>

      <Card>
        <CardHeader><CardTitle>Update Spreadsheet</CardTitle></CardHeader>
        <CardContent className="space-y-4">
          <div className="grid gap-4 md:grid-cols-[minmax(240px,360px)_1fr] md:items-end">
            <div className="space-y-2">
              <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 className="flex flex-wrap gap-2">
              <Button variant="outline" className="gap-2" onClick={handleExportTemplate} disabled={!units.length}><Download className="h-4 w-4" /> Export Update Template</Button>
              <Button className="gap-2" onClick={() => setImportOpen(true)} disabled={!selectedAssociation}><Upload className="h-4 w-4" /> Import Updates</Button>
            </div>
          </div>
          {lastResult && <Badge variant="secondary">Last import: {lastResult.updated} updated, {lastResult.skipped} skipped</Badge>}
        </CardContent>
      </Card>

      <Card>
        <CardHeader><CardTitle className="flex items-center gap-2"><HomeIcon className="h-5 w-5" /> Current Units ({units.length})</CardTitle></CardHeader>
        <CardContent>
          <div className="rounded-md border border-border overflow-x-auto">
            <Table>
              <TableHeader><TableRow><TableHead>Unit #</TableHead><TableHead>Account #</TableHead><TableHead>Parcel ID</TableHead><TableHead>Lot</TableHead><TableHead>Address</TableHead><TableHead>Status</TableHead><TableHead>Rental</TableHead></TableRow></TableHeader>
              <TableBody>
                {loading ? <TableRow><TableCell colSpan={7} className="text-center text-muted-foreground py-8">Loading units...</TableCell></TableRow> : units.slice(0, 50).map((u) => (
                  <TableRow key={u.id}>
                    <TableCell className="font-medium">{u.unit_number}</TableCell>
                    <TableCell>{u.account_number || "—"}</TableCell>
                    <TableCell>{u.parcel_id || "—"}</TableCell>
                    <TableCell>{u.lot || "—"}</TableCell>
                    <TableCell>{u.address || "—"}</TableCell>
                    <TableCell>{u.status || "—"}</TableCell>
                    <TableCell>{u.is_rental ? "Yes" : "No"}</TableCell>
                  </TableRow>
                ))}
              </TableBody>
            </Table>
            {units.length > 50 && <p className="text-xs text-muted-foreground p-2">Showing first 50 of {units.length} units.</p>}
          </div>
        </CardContent>
      </Card>

      <ImportSpreadsheetDialog
        open={importOpen}
        onOpenChange={setImportOpen}
        title="Import Unit Updates"
        description="Rows are matched to existing units by Unit ID first, then Account Number, Parcel ID, Unit Number, or Address. Blank update fields are ignored."
        templateFileName="bulk_unit_updates_template.xlsx"
        expectedColumns={[
          { key: "unit_id", label: "Unit ID", aliases: ["ID"] },
          { key: "unit_number", label: "Unit Number", aliases: ["Unit", "Unit #"] },
          { key: "new_unit_number", label: "New Unit Number" },
          { key: "account_number", label: "Account Number", aliases: ["Account", "Account #"] },
          { key: "parcel_id", label: "Parcel ID", aliases: ["Parcel", "Parcel Number", "APN"] },
          { key: "lot", label: "Lot", aliases: ["Lot Number", "Lot #"] },
          { key: "address", label: "Address" },
          { key: "city", label: "City" },
          { key: "state", label: "State" },
          { key: "zip", label: "Zip" },
          { key: "status", label: "Status" },
          { key: "is_rental", label: "Is Rental", aliases: ["Rental"] },
          { key: "bedrooms", label: "Bedrooms" },
          { key: "bathrooms", label: "Bathrooms" },
          { key: "sqft", label: "Sqft" },
          { key: "monthly_assessment", label: "Monthly Assessment" },
          { key: "image_url", label: "Image URL" },
        ]}
        onImport={handleImportUpdates}
      />
    </div>
  );
}
