import { useState, useEffect, useMemo } from "react";
import { supabase } from "@/integrations/supabase/client";
import { useToast } from "@/hooks/use-toast";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Button } from "@/components/ui/button";
import { Label } from "@/components/ui/label";
import { Badge } from "@/components/ui/badge";
import { Input } from "@/components/ui/input";
import { Loader2, Save, ArrowRight, Search } from "lucide-react";

interface GLAccount {
  id: string;
  name: string;
  parentId: string | null;
  depth: number;
}

interface UnitRow {
  unit_id: string;
  unit_number: string;
  address: string;
  charge_type: string;
  buildium_gl_account_id: string;
  buildium_gl_account_name: string;
}

interface Props {
  associations: { id: string; name: string }[];
}

const CHARGE_TYPES = [
  { value: "assessment", label: "Assessment" },
  { value: "late_fee", label: "Late Fee" },
  { value: "interest", label: "Interest" },
  { value: "admin_fee", label: "Admin Fee" },
  { value: "legal_fee", label: "Legal Fee" },
  { value: "violation", label: "Violation Fine" },
  { value: "bank_fee", label: "Bank Fee" },
  { value: "special_assessment", label: "Special Assessment" },
];

export default function BuildiumUnitMappingCard({ associations }: Props) {
  const { toast } = useToast();
  const [selectedAssociation, setSelectedAssociation] = useState("");
  const [selectedChargeType, setSelectedChargeType] = useState("assessment");
  const [units, setUnits] = useState<{ id: string; unit_number: string; address: string }[]>([]);
  const [mappings, setMappings] = useState<UnitRow[]>([]);
  const [glAccounts, setGlAccounts] = useState<GLAccount[]>([]);
  const [loading, setLoading] = useState(false);
  const [saving, setSaving] = useState(false);
  const [search, setSearch] = useState("");

  useEffect(() => {
    if (!selectedAssociation) {
      setUnits([]);
      setMappings([]);
      setGlAccounts([]);
      return;
    }
    loadUnits(selectedAssociation);
    loadGLAccounts(selectedAssociation);
  }, [selectedAssociation]);

  useEffect(() => {
    if (!selectedAssociation) return;
    loadMappings(selectedAssociation, selectedChargeType);
  }, [selectedAssociation, selectedChargeType]);

  const loadUnits = async (assocId: string) => {
    const { data } = await supabase
      .from("units")
      .select("id, unit_number, address")
      .eq("association_id", assocId)
      .neq("status", "archived")
      .order("unit_number");
    setUnits(data || []);
  };

  const loadGLAccounts = async (assocId: string) => {
    const { data } = await supabase
      .from("chart_of_accounts")
      .select("id, account_number, account_name, account_type, parent_account_id")
      .eq("is_active", true)
      .eq("account_type", "income")
      .order("account_number");

    const allAccounts = data || [];
    const result: GLAccount[] = [];
    const tops = allAccounts.filter(a => !a.parent_account_id);
    const children = allAccounts.filter(a => a.parent_account_id);

    for (const parent of tops) {
      result.push({
        id: parent.account_number || parent.id,
        name: `${parent.account_number} - ${parent.account_name}`,
        parentId: null,
        depth: 0,
      });
      for (const child of children.filter(c => c.parent_account_id === parent.id)) {
        result.push({
          id: child.account_number || child.id,
          name: `${child.account_number} - ${child.account_name}`,
          parentId: parent.id,
          depth: 1,
        });
      }
    }

    const addedChildIds = new Set(result.filter(r => r.parentId).map(r => r.id));
    for (const child of children) {
      const childKey = child.account_number || child.id;
      if (!addedChildIds.has(childKey)) {
        result.push({
          id: childKey,
          name: `${child.account_number} - ${child.account_name}`,
          parentId: child.parent_account_id,
          depth: 1,
        });
      }
    }

    setGlAccounts(result);
  };

  const loadMappings = async (assocId: string, chargeType: string) => {
    setLoading(true);
    try {
      const { data, error } = await supabase
        .from("buildium_gl_mappings")
        .select("unit_id, charge_type, buildium_gl_account_id, buildium_gl_account_name")
        .eq("association_id", assocId)
        .eq("charge_type", chargeType)
        .not("unit_id", "is", null);
      if (error) throw error;
      setMappings((data || []).map((m: any) => ({
        unit_id: m.unit_id,
        unit_number: "",
        address: "",
        charge_type: m.charge_type,
        buildium_gl_account_id: m.buildium_gl_account_id || "",
        buildium_gl_account_name: m.buildium_gl_account_name || "",
      })));
    } catch (err: any) {
      toast({ variant: "destructive", title: "Error loading mappings", description: err.message });
    } finally {
      setLoading(false);
    }
  };

  const getUnitMapping = (unitId: string) => {
    return mappings.find(m => m.unit_id === unitId);
  };

  const updateUnitMapping = (unitId: string, glAccountId: string) => {
    const gl = glAccounts.find(g => String(g.id) === glAccountId);
    setMappings(prev => {
      const existing = prev.findIndex(m => m.unit_id === unitId);
      if (glAccountId === "" || glAccountId === "__none__") {
        return prev.filter(m => m.unit_id !== unitId);
      }
      if (existing >= 0) {
        const next = [...prev];
        next[existing] = {
          ...next[existing],
          buildium_gl_account_id: glAccountId,
          buildium_gl_account_name: gl?.name || "",
        };
        return next;
      }
      return [...prev, {
        unit_id: unitId,
        unit_number: "",
        address: "",
        charge_type: selectedChargeType,
        buildium_gl_account_id: glAccountId,
        buildium_gl_account_name: gl?.name || "",
      }];
    });
  };

  const saveMappings = async () => {
    if (!selectedAssociation) return;
    setSaving(true);
    try {
      // Delete existing unit mappings for this association + charge type
      await supabase
        .from("buildium_gl_mappings")
        .delete()
        .eq("association_id", selectedAssociation)
        .eq("charge_type", selectedChargeType)
        .not("unit_id", "is", null);

      const inserts = mappings
        .filter(m => m.buildium_gl_account_id)
        .map(m => ({
          association_id: selectedAssociation,
          charge_type: selectedChargeType,
          unit_id: m.unit_id,
          buildium_gl_account_id: m.buildium_gl_account_id,
          buildium_gl_account_name: m.buildium_gl_account_name || null,
          amount_min: null,
          amount_max: null,
        }));

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

      toast({ title: "Unit mappings saved", description: `${inserts.length} unit GL mapping(s) saved for ${CHARGE_TYPES.find(c => c.value === selectedChargeType)?.label}.` });
    } catch (err: any) {
      toast({ variant: "destructive", title: "Save failed", description: err.message });
    } finally {
      setSaving(false);
    }
  };

  const filteredUnits = useMemo(() => {
    if (!search) return units;
    const s = search.toLowerCase();
    return units.filter(u =>
      u.unit_number?.toLowerCase().includes(s) ||
      u.address?.toLowerCase().includes(s)
    );
  }, [units, search]);

  const mappedCount = mappings.filter(m => m.buildium_gl_account_id).length;

  return (
    <Card>
      <CardHeader>
        <CardTitle className="text-lg">Unit GL Account Mapping</CardTitle>
        <CardDescription>
          Assign specific GL accounts to individual units. These override the association-level mapping for the selected charge type.
        </CardDescription>
      </CardHeader>
      <CardContent className="space-y-4">
        {/* Association + Charge Type selectors */}
        <div className="flex flex-wrap items-center gap-3">
          <Select value={selectedAssociation} onValueChange={setSelectedAssociation}>
            <SelectTrigger className="w-[300px]">
              <SelectValue placeholder="Select association..." />
            </SelectTrigger>
            <SelectContent>
              {associations.map(a => (
                <SelectItem key={a.id} value={a.id}>{a.name}</SelectItem>
              ))}
            </SelectContent>
          </Select>
          {selectedAssociation && (
            <Select value={selectedChargeType} onValueChange={setSelectedChargeType}>
              <SelectTrigger className="w-[200px]">
                <SelectValue />
              </SelectTrigger>
              <SelectContent>
                {CHARGE_TYPES.map(ct => (
                  <SelectItem key={ct.value} value={ct.value}>{ct.label}</SelectItem>
                ))}
              </SelectContent>
            </Select>
          )}
          {selectedAssociation && (
            <Badge variant="outline" className="text-xs">
              {mappedCount} unit override(s)
            </Badge>
          )}
        </div>

        {selectedAssociation && (
          <>
            {loading ? (
              <div className="flex items-center gap-2 text-sm text-muted-foreground py-4">
                <Loader2 className="h-4 w-4 animate-spin" /> Loading...
              </div>
            ) : (
              <div className="space-y-3">
                {units.length === 0 ? (
                  <p className="text-sm text-muted-foreground bg-muted p-3 rounded-lg">
                    No units found for this association. Sync units from Buildium first.
                  </p>
                ) : (
                  <>
                    {/* Search */}
                    <div className="relative">
                      <Search className="absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground" />
                      <Input
                        placeholder="Search units..."
                        value={search}
                        onChange={e => setSearch(e.target.value)}
                        className="pl-9 h-9"
                      />
                    </div>

                    {/* Unit list */}
                    <div className="border rounded-lg divide-y max-h-[400px] overflow-y-auto">
                      {filteredUnits.map(unit => {
                        const mapping = getUnitMapping(unit.id);
                        return (
                          <div key={unit.id} className="flex items-center gap-3 px-3 py-2">
                            <div className="w-[120px] shrink-0">
                              <Label className="text-sm font-medium">{unit.unit_number}</Label>
                              {unit.address && (
                                <p className="text-xs text-muted-foreground truncate">{unit.address}</p>
                              )}
                            </div>
                            <ArrowRight className="h-4 w-4 text-muted-foreground shrink-0" />
                            <Select
                              value={mapping?.buildium_gl_account_id || "__none__"}
                              onValueChange={v => updateUnitMapping(unit.id, v === "__none__" ? "" : v)}
                            >
                              <SelectTrigger className="flex-1 h-8 text-xs">
                                <SelectValue placeholder="Use association default" />
                              </SelectTrigger>
                              <SelectContent>
                                <SelectItem value="__none__">— Use association default —</SelectItem>
                                {glAccounts.map(gl => (
                                  <SelectItem key={gl.id} value={String(gl.id)}>
                                    {gl.depth > 0 ? `  ↳ ${gl.name}` : gl.name}
                                  </SelectItem>
                                ))}
                              </SelectContent>
                            </Select>
                          </div>
                        );
                      })}
                    </div>

                    <div className="flex justify-end pt-2">
                      <Button onClick={saveMappings} disabled={saving} className="gap-2">
                        {saving ? <Loader2 className="h-4 w-4 animate-spin" /> : <Save className="h-4 w-4" />}
                        Save Unit Mappings
                      </Button>
                    </div>
                  </>
                )}
              </div>
            )}
          </>
        )}
      </CardContent>
    </Card>
  );
}
