import { useEffect, useState } from "react";
import { z } from "zod";
import AssociationDirectoryManager from "@/components/association/AssociationDirectoryManager";
import { useHomeowner } from "@/contexts/HomeownerContext";
import { useBoardAssociations } from "@/contexts/BoardAssociationContext";
import { supabase } from "@/integrations/supabase/client";
import { useToast } from "@/hooks/use-toast";
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import { Switch } from "@/components/ui/switch";
import { AlertCircle, Loader2, Save, Users, Briefcase } from "lucide-react";

const optInSchema = z.object({
  display_name: z.string().trim().min(1, "Name is required").max(150),
  title: z.string().trim().max(150).optional(),
  email: z.string().trim().max(255).optional().refine((value) => !value || z.string().email().safeParse(value).success, "Enter a valid email"),
  phone: z.string().trim().max(50).optional(),
  notes: z.string().trim().max(1000).optional(),
  optedIn: z.boolean(),
});

type OptInForm = z.infer<typeof optInSchema>;

type DirectoryEntry = {
  id: string;
  display_name: string;
  title: string | null;
  email: string | null;
  phone: string | null;
  notes: string | null;
};

export default function HomeownerDirectoryPage() {
  const { currentOwner, association, loading } = useHomeowner();
  const board = useBoardAssociations();
  const { toast } = useToast();
  const [entry, setEntry] = useState<DirectoryEntry | null>(null);
  const [form, setForm] = useState<OptInForm>({ display_name: "", title: "", email: "", phone: "", notes: "", optedIn: false });
  const [errors, setErrors] = useState<Record<string, string>>({});
  const [saving, setSaving] = useState(false);
  const [entryLoading, setEntryLoading] = useState(false);

  useEffect(() => {
    if (!currentOwner || !association) return;
    setForm({
      display_name: `${currentOwner.first_name || ""} ${currentOwner.last_name || ""}`.trim(),
      title: "",
      email: currentOwner.email || "",
      phone: currentOwner.phone || "",
      notes: "",
      optedIn: false,
    });
    void loadMyEntry();
  }, [currentOwner?.id, association?.id]);

  const loadMyEntry = async () => {
    if (!currentOwner || !association) return;
    setEntryLoading(true);
    const { data, error } = await (supabase as any)
      .from("association_directory_entries")
      .select("id, display_name, title, email, phone, notes")
      .eq("association_id", association.id)
      .eq("owner_id", currentOwner.id)
      .eq("is_owner_opt_in", true)
      .maybeSingle();
    if (!error && data) {
      setEntry(data);
      setForm({
        display_name: data.display_name || "",
        title: data.title || "",
        email: data.email || "",
        phone: data.phone || "",
        notes: data.notes || "",
        optedIn: true,
      });
    }
    setEntryLoading(false);
  };

  const validate = () => {
    const result = optInSchema.safeParse(form);
    if (result.success) {
      setErrors({});
      return result.data;
    }
    const nextErrors: Record<string, string> = {};
    result.error.issues.forEach((issue) => { nextErrors[String(issue.path[0])] = issue.message; });
    setErrors(nextErrors);
    return null;
  };

  const handleSave = async () => {
    if (!currentOwner || !association) return;
    const valid = validate();
    if (!valid) return;

    setSaving(true);
    if (!valid.optedIn) {
      if (entry) await (supabase as any).from("association_directory_entries").delete().eq("id", entry.id);
      setEntry(null);
      setSaving(false);
      toast({ title: "Directory opt-in removed" });
      return;
    }

    const payload = {
      association_id: association.id,
      owner_id: currentOwner.id,
      display_name: valid.display_name,
      title: valid.title || null,
      email: valid.email || null,
      phone: valid.phone || null,
      address: currentOwner.property_address || currentOwner.street_address || null,
      category: "Resident",
      notes: valid.notes || null,
      is_owner_opt_in: true,
      is_published: true,
    };

    const { data, error } = entry
      ? await (supabase as any).from("association_directory_entries").update(payload).eq("id", entry.id).select("id, display_name, title, email, phone, notes").single()
      : await (supabase as any).from("association_directory_entries").insert(payload).select("id, display_name, title, email, phone, notes").single();

    setSaving(false);
    if (error) {
      toast({ title: "Directory opt-in failed", description: error.message, variant: "destructive" });
      return;
    }
    setEntry(data);
    toast({ title: "Directory opt-in saved" });
  };

  if (loading || entryLoading || board.loading) return <div className="flex justify-center py-12"><Loader2 className="h-6 w-6 animate-spin text-muted-foreground" /></div>;

  const isBoard = (board.associationIds?.length ?? 0) > 0;

  // Board members who aren't owners still get the shared-vendor directory.
  if (!currentOwner || !association) {
    if (isBoard) {
      return (
        <div className="space-y-6">
          <div>
            <h1 className="text-2xl font-bold text-foreground flex items-center gap-2"><Users className="h-6 w-6" /> Directory</h1>
            <p className="text-muted-foreground mt-1">Vendor contacts shared with the board.</p>
          </div>
          <BoardVendorDirectory associationIds={board.associationIds} />
        </div>
      );
    }
    return <div className="text-center py-20 text-muted-foreground"><AlertCircle className="h-10 w-10 mx-auto mb-3 opacity-40" />No association is linked to your account.</div>;
  }

  return (
    <div className="space-y-6">
      <div>
        <h1 className="text-2xl font-bold text-foreground flex items-center gap-2"><Users className="h-6 w-6" /> Directory</h1>
        <p className="text-muted-foreground mt-1">View your association directory and choose whether your contact details appear.</p>
      </div>

      <Card>
        <CardHeader>
          <CardTitle>My Directory Listing</CardTitle>
          <CardDescription>Only opt in if you want this information visible to other signed-in members of your association.</CardDescription>
        </CardHeader>
        <CardContent className="space-y-4">
          <div className="flex items-center justify-between rounded-lg border bg-background p-3">
            <Label>Include me in the directory</Label>
            <Switch checked={form.optedIn} onCheckedChange={(checked) => setForm((prev) => ({ ...prev, optedIn: checked }))} />
          </div>
          {form.optedIn && (
            <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
              <Field label="Display Name" error={errors.display_name}><Input value={form.display_name} onChange={(event) => setForm((prev) => ({ ...prev, display_name: event.target.value }))} maxLength={150} /></Field>
              <Field label="Title" error={errors.title}><Input value={form.title || ""} onChange={(event) => setForm((prev) => ({ ...prev, title: event.target.value }))} maxLength={150} /></Field>
              <Field label="Email" error={errors.email}><Input type="email" value={form.email || ""} onChange={(event) => setForm((prev) => ({ ...prev, email: event.target.value }))} maxLength={255} /></Field>
              <Field label="Phone" error={errors.phone}><Input type="tel" value={form.phone || ""} onChange={(event) => setForm((prev) => ({ ...prev, phone: event.target.value }))} maxLength={50} /></Field>
              <Field label="Notes" error={errors.notes} className="md:col-span-2"><Textarea value={form.notes || ""} onChange={(event) => setForm((prev) => ({ ...prev, notes: event.target.value }))} maxLength={1000} rows={3} /></Field>
            </div>
          )}
          <div className="flex justify-end"><Button onClick={handleSave} disabled={saving} className="gap-2">{saving ? <Loader2 className="h-4 w-4 animate-spin" /> : <Save className="h-4 w-4" />} Save Directory Preference</Button></div>
        </CardContent>
      </Card>

      <AssociationDirectoryManager associationId={association.id} mode="readonly" title={`${association.name} Directory`} description="Published contacts for your association." />

      {isBoard && <BoardVendorDirectory associationIds={board.associationIds} />}
    </div>
  );
}

/** Vendor contacts a manager has shared with the board. Board members only; RLS
 *  ensures only shared vendors for the member's association(s) are returned. */
function BoardVendorDirectory({ associationIds }: { associationIds: string[] }) {
  const [vendors, setVendors] = useState<any[]>([]);
  const [loaded, setLoaded] = useState(false);

  useEffect(() => {
    if (!associationIds?.length) { setLoaded(true); return; }
    let cancelled = false;
    (async () => {
      const { data } = await (supabase as any)
        .from("vendors")
        .select("id, name, contact_name, email, phone, address")
        .eq("share_with_board", true)
        .order("name");
      if (!cancelled) { setVendors(data ?? []); setLoaded(true); }
    })();
    return () => { cancelled = true; };
  }, [associationIds?.join(",")]);

  if (loaded && vendors.length === 0) return null;

  return (
    <Card>
      <CardHeader>
        <CardTitle className="flex items-center gap-2"><Briefcase className="h-5 w-5" /> Vendors</CardTitle>
        <CardDescription>Vendor contacts shared with the board.</CardDescription>
      </CardHeader>
      <CardContent className="space-y-2">
        {vendors.map((v) => (
          <div key={v.id} className="rounded-md border bg-background p-3">
            <div className="font-medium text-foreground">{v.name}</div>
            <div className="text-sm text-muted-foreground">
              {[v.contact_name, v.phone, v.email].filter(Boolean).join(" · ") || "—"}
            </div>
            {v.address && <div className="text-xs text-muted-foreground mt-0.5">{v.address}</div>}
          </div>
        ))}
      </CardContent>
    </Card>
  );
}

function Field({ label, error, className, children }: { label: string; error?: string; className?: string; children: React.ReactNode }) {
  return <div className={`space-y-1.5 ${className || ""}`}><Label>{label}</Label>{children}{error && <p className="text-xs text-destructive">{error}</p>}</div>;
}
