import { useEffect, useState } from "react";
import { supabase } from "@/integrations/supabase/client";
import { useToast } from "@/hooks/use-toast";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Label } from "@/components/ui/label";
import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
import { Switch } from "@/components/ui/switch";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Loader2, Save, Printer, Upload, Trash2, Copy } from "lucide-react";
import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
} from "@/components/ui/alert-dialog";
import {
  downloadChecksPdf,
  type CheckLayout,
  type CheckFieldKey,
  type CheckFieldPosition,
  DEFAULT_FIELD_POSITIONS,
  FIELD_LABELS,
  AVAILABLE_FONTS,
} from "@/utils/checkPdfGenerator";

interface Props {
  associationId: string;
  associationName?: string;
  /** When 'company', reads/writes company_check_layouts (no association_id required, associationId may be any string identifier). */
  mode?: "association" | "company";
}

const DEFAULTS: CheckLayout = {
  check_position: "top",
  offset_x: 0,
  offset_y: 0,
  show_payer_block: true,
  show_logo: true,
  payer_name: "",
  payer_address: "",
  show_signature_line: true,
  signature_image_url: "",
  signature_label: "Authorized Signature",
  memo_prefix: "",
  footer_text: "",
  show_field_labels: false,
  font_family: "helvetica",
  field_positions: {},
  logo_url: "",
  micr_gap_1: 3,
  micr_gap_2: 3,
};

const FIELD_ORDER: CheckFieldKey[] = [
  "payer", "logo", "date", "check_number",
  "payee_label", "payee", "payee_address",
  "amount_box_label", "amount_box", "amount_words",
  "memo_label", "memo",
  "signature_line", "signature_image", "signature_label",
  "footer", "micr",
];

export default function CheckLayoutEditor({ associationId, associationName, mode = "association" }: Props) {
  const isCompany = mode === "company";
  const tableName = isCompany ? "company_check_layouts" : "check_layouts";
  const { toast } = useToast();
  const [loading, setLoading] = useState(true);
  const [saving, setSaving] = useState(false);
  const [uploading, setUploading] = useState(false);
  const [uploadingLogo, setUploadingLogo] = useState(false);
  const [layoutId, setLayoutId] = useState<string | null>(null);
  const [layout, setLayout] = useState<CheckLayout>(DEFAULTS);
  const [otherLayouts, setOtherLayouts] = useState<Array<{ id: string; association_id: string; association_name: string }>>([]);
  const [copyFromId, setCopyFromId] = useState<string>("");
  const [confirmCopyOpen, setConfirmCopyOpen] = useState(false);
  const [copying, setCopying] = useState(false);

  useEffect(() => {
    let cancelled = false;
    (async () => {
      setLoading(true);
      const query = supabase.from(tableName as any).select("*");
      const { data } = isCompany
        ? await query.maybeSingle()
        : await query.eq("association_id", associationId).maybeSingle();
      if (cancelled) return;
      if (data) {
        setLayoutId((data as any).id);
        setLayout({
          check_position: ((data as any).check_position as CheckLayout["check_position"]) || "top",
          offset_x: Number((data as any).offset_x) || 0,
          offset_y: Number((data as any).offset_y) || 0,
          show_payer_block: (data as any).show_payer_block ?? true,
          show_logo: (data as any).show_logo ?? true,
          payer_name: (data as any).payer_name || "",
          payer_address: (data as any).payer_address || "",
          show_signature_line: (data as any).show_signature_line ?? true,
          signature_image_url: (data as any).signature_image_url || "",
          signature_label: (data as any).signature_label || "Authorized Signature",
          memo_prefix: (data as any).memo_prefix || "",
          footer_text: (data as any).footer_text || "",
          show_field_labels: (data as any).show_field_labels ?? false,
          font_family: (data as any).font_family || "helvetica",
          field_positions: ((data as any).field_positions as CheckLayout["field_positions"]) || {},
          logo_url: (data as any).logo_url || "",
          micr_gap_1: Number((data as any).micr_gap_1 ?? 3),
          micr_gap_2: Number((data as any).micr_gap_2 ?? 3),
        });
      } else {
        setLayoutId(null);
        setLayout({ ...DEFAULTS, payer_name: associationName || "" });
      }
      setLoading(false);
    })();
    return () => { cancelled = true; };
  }, [associationId, associationName, tableName, isCompany]);

  // Load other associations' layouts for "Copy from" (association mode only)
  useEffect(() => {
    if (isCompany) { setOtherLayouts([]); return; }
    let cancelled = false;
    (async () => {
      const { data: layouts } = await supabase
        .from("check_layouts")
        .select("id, association_id")
        .neq("association_id", associationId);
      if (cancelled || !layouts || layouts.length === 0) {
        if (!cancelled) setOtherLayouts([]);
        return;
      }
      const ids = Array.from(new Set(layouts.map((l: any) => l.association_id)));
      const { data: assocs } = await supabase
        .from("associations")
        .select("id, name")
        .in("id", ids);
      if (cancelled) return;
      const nameMap = new Map((assocs || []).map((a: any) => [a.id, a.name]));
      const merged = layouts
        .map((l: any) => ({
          id: l.id,
          association_id: l.association_id,
          association_name: nameMap.get(l.association_id) || "Unknown",
        }))
        .sort((a, b) => a.association_name.localeCompare(b.association_name));
      setOtherLayouts(merged);
    })();
    return () => { cancelled = true; };
  }, [associationId, isCompany]);

  const handleCopyFrom = async () => {
    if (!copyFromId) return;
    setCopying(true);
    try {
      const { data, error } = await supabase
        .from("check_layouts")
        .select("*")
        .eq("id", copyFromId)
        .maybeSingle();
      if (error) throw error;
      if (!data) throw new Error("Source layout not found");
      setLayout({
        check_position: (data.check_position as CheckLayout["check_position"]) || "top",
        offset_x: Number(data.offset_x) || 0,
        offset_y: Number(data.offset_y) || 0,
        show_payer_block: data.show_payer_block ?? true,
        show_logo: data.show_logo ?? true,
        // Keep this association's own payer name/address — only copy formatting/positions/images
        payer_name: layout.payer_name || associationName || "",
        payer_address: layout.payer_address || "",
        show_signature_line: data.show_signature_line ?? true,
        signature_image_url: data.signature_image_url || "",
        signature_label: data.signature_label || "Authorized Signature",
        memo_prefix: data.memo_prefix || "",
        footer_text: data.footer_text || "",
        show_field_labels: (data as any).show_field_labels ?? false,
        font_family: (data as any).font_family || "helvetica",
        field_positions: ((data as any).field_positions as CheckLayout["field_positions"]) || {},
        logo_url: (data as any).logo_url || "",
        micr_gap_1: Number((data as any).micr_gap_1 ?? 3),
        micr_gap_2: Number((data as any).micr_gap_2 ?? 3),
      });
      toast({
        title: "Settings copied",
        description: "Review and click Save Layout to apply to this association.",
      });
      setConfirmCopyOpen(false);
    } catch (err: any) {
      toast({ variant: "destructive", title: "Copy failed", description: err.message });
    } finally {
      setCopying(false);
    }
  };

  const update = <K extends keyof CheckLayout>(key: K, value: CheckLayout[K]) => {
    setLayout((prev) => ({ ...prev, [key]: value }));
  };

  const updateField = (key: CheckFieldKey, patch: Partial<CheckFieldPosition>) => {
    setLayout((prev) => {
      const current = (prev.field_positions || {})[key] || {};
      return {
        ...prev,
        field_positions: { ...(prev.field_positions || {}), [key]: { ...current, ...patch } },
      };
    });
  };

  const resetField = (key: CheckFieldKey) => {
    setLayout((prev) => {
      const next = { ...(prev.field_positions || {}) };
      delete next[key];
      return { ...prev, field_positions: next };
    });
  };

  const handleImageUpload = async (
    file: File,
    bucket: "check-signatures" | "check-logos",
    target: "signature_image_url" | "logo_url"
  ) => {
    const setter = target === "signature_image_url" ? setUploading : setUploadingLogo;
    setter(true);
    try {
      const ext = file.name.split(".").pop() || "png";
      const path = `${associationId}/${Date.now()}.${ext}`;
      const { error: upErr } = await supabase.storage.from(bucket).upload(path, file, { upsert: true });
      if (upErr) throw upErr;
      const { data } = supabase.storage.from(bucket).getPublicUrl(path);
      update(target, data.publicUrl);
      toast({ title: target === "logo_url" ? "Logo uploaded" : "Signature uploaded" });
    } catch (err: any) {
      toast({ variant: "destructive", title: "Upload failed", description: err.message });
    } finally {
      setter(false);
    }
  };

  const handleSave = async () => {
    setSaving(true);
    try {
      const basePayload = {
        check_position: layout.check_position || "top",
        offset_x: Number(layout.offset_x) || 0,
        offset_y: Number(layout.offset_y) || 0,
        show_payer_block: !!layout.show_payer_block,
        show_logo: !!layout.show_logo,
        payer_name: layout.payer_name || null,
        payer_address: layout.payer_address || null,
        show_signature_line: !!layout.show_signature_line,
        signature_image_url: layout.signature_image_url || null,
        signature_label: layout.signature_label || null,
        memo_prefix: layout.memo_prefix || null,
        footer_text: layout.footer_text || null,
        show_field_labels: !!layout.show_field_labels,
        font_family: layout.font_family || "helvetica",
        field_positions: (layout.field_positions || {}) as any,
        logo_url: layout.logo_url || null,
        micr_gap_1: Number(layout.micr_gap_1 ?? 3),
        micr_gap_2: Number(layout.micr_gap_2 ?? 3),
      };
      const payload: any = isCompany
        ? basePayload
        : { ...basePayload, association_id: associationId };

      if (layoutId) {
        const { error } = await supabase.from(tableName as any).update(payload).eq("id", layoutId);
        if (error) throw error;
      } else {
        const { data, error } = await supabase.from(tableName as any).insert(payload).select("id").single();
        if (error) throw error;
        setLayoutId((data as any).id);
      }
      toast({ title: "Layout saved", description: isCompany ? "Future company checks will use this layout." : "Future checks for this association will use this layout." });
    } catch (err: any) {
      toast({ variant: "destructive", title: "Save failed", description: err.message });
    } finally {
      setSaving(false);
    }
  };

  const handlePreview = async () => {
    await downloadChecksPdf(
      [{
        check_number: "1001",
        check_date: new Date().toISOString().slice(0, 10),
        payee: "Sample Vendor, Inc.",
        amount: 1234.56,
        memo: "Sample invoice #INV-001",
        bank_account_name: "Operating Account",
        bank_routing_number: "123456789",
        bank_account_number: "9876543210",
        association_name: associationName,
        layout,
      }],
      `check-preview-${associationId}.pdf`,
      { includeMicr: false }
    );
  };

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

  return (
    <div className="space-y-6">
      <div className="flex items-center justify-between gap-3 flex-wrap">
        <div>
          <h3 className="text-lg font-semibold">Check Layout</h3>
          <p className="text-sm text-muted-foreground">
            Customize how printed checks look for this association. Applied automatically when printing checks.
          </p>
        </div>
        <div className="flex gap-2 items-center flex-wrap">
          {otherLayouts.length > 0 && (
            <div className="flex items-center gap-2">
              <Select value={copyFromId} onValueChange={setCopyFromId}>
                <SelectTrigger className="w-[240px]">
                  <SelectValue placeholder="Copy settings from…" />
                </SelectTrigger>
                <SelectContent>
                  {otherLayouts.map((l) => (
                    <SelectItem key={l.id} value={l.id}>{l.association_name}</SelectItem>
                  ))}
                </SelectContent>
              </Select>
              <Button
                variant="outline"
                disabled={!copyFromId}
                onClick={() => setConfirmCopyOpen(true)}
                className="gap-2"
              >
                <Copy className="h-4 w-4" /> Copy
              </Button>
            </div>
          )}
          <Button variant="outline" onClick={handlePreview} className="gap-2">
            <Printer className="h-4 w-4" /> Preview PDF
          </Button>
          <Button onClick={handleSave} disabled={saving} className="gap-2">
            {saving ? <Loader2 className="h-4 w-4 animate-spin" /> : <Save className="h-4 w-4" />}
            {saving ? "Saving…" : "Save Layout"}
          </Button>
        </div>
      </div>

      <AlertDialog open={confirmCopyOpen} onOpenChange={setConfirmCopyOpen}>
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>Copy check layout settings?</AlertDialogTitle>
            <AlertDialogDescription>
              This will replace the current layout, fonts, positions, logo, and signature with the
              selected association's settings. Your payer name and address will be kept. Nothing is
              saved until you click "Save Layout".
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel disabled={copying}>Cancel</AlertDialogCancel>
            <AlertDialogAction onClick={handleCopyFrom} disabled={copying}>
              {copying ? "Copying…" : "Copy settings"}
            </AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>

      <Card>
        <CardHeader><CardTitle className="text-base">Page & Typography</CardTitle></CardHeader>
        <CardContent className="grid grid-cols-1 sm:grid-cols-3 gap-4">
          <div>
            <Label>Check Position</Label>
            <Select
              value={layout.check_position || "top"}
              onValueChange={(v) => update("check_position", v as CheckLayout["check_position"])}
            >
              <SelectTrigger><SelectValue /></SelectTrigger>
              <SelectContent>
                <SelectItem value="top">Top of page</SelectItem>
                <SelectItem value="middle">Middle of page</SelectItem>
                <SelectItem value="bottom">Bottom of page</SelectItem>
              </SelectContent>
            </Select>
            <p className="text-xs text-muted-foreground mt-1">Match your check stock layout.</p>
          </div>
          <div>
            <Label>Font Family</Label>
            <Select
              value={layout.font_family || "helvetica"}
              onValueChange={(v) => update("font_family", v)}
            >
              <SelectTrigger><SelectValue /></SelectTrigger>
              <SelectContent>
                {AVAILABLE_FONTS.map(f => (
                  <SelectItem key={f.value} value={f.value}>{f.label}</SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>
          <div className="flex items-end">
            <div className="flex items-center gap-3">
              <Switch
                id="show_labels"
                checked={!!layout.show_field_labels}
                onCheckedChange={(v) => update("show_field_labels", v)}
              />
              <Label htmlFor="show_labels" className="cursor-pointer">Print field labels (Payee, Memo, Date…)</Label>
            </div>
          </div>
          <div>
            <Label>Global Horizontal offset (in)</Label>
            <Input type="number" step="0.05" value={layout.offset_x ?? 0}
              onChange={(e) => update("offset_x", Number(e.target.value))} />
          </div>
          <div>
            <Label>Global Vertical offset (in)</Label>
            <Input type="number" step="0.05" value={layout.offset_y ?? 0}
              onChange={(e) => update("offset_y", Number(e.target.value))} />
          </div>
          <div>
            <Label>MICR gap: Check # → Routing</Label>
            <Input type="number" min={0} step={1} value={layout.micr_gap_1 ?? 3}
              onChange={(e) => update("micr_gap_1", Math.max(0, parseInt(e.target.value) || 0))} />
            <p className="text-xs text-muted-foreground mt-1">Spaces between segments in the MICR line.</p>
          </div>
          <div>
            <Label>MICR gap: Routing → Account</Label>
            <Input type="number" min={0} step={1} value={layout.micr_gap_2 ?? 3}
              onChange={(e) => update("micr_gap_2", Math.max(0, parseInt(e.target.value) || 0))} />
          </div>
        </CardContent>
      </Card>

      <Card>
        <CardHeader><CardTitle className="text-base">Logo</CardTitle></CardHeader>
        <CardContent className="space-y-4">
          <div className="flex items-center gap-3">
            <Switch id="show_logo" checked={!!layout.show_logo}
              onCheckedChange={(v) => update("show_logo", v)} />
            <Label htmlFor="show_logo" className="cursor-pointer">Print logo on the check</Label>
          </div>
          {layout.logo_url ? (
            <div className="flex items-center gap-3 p-3 border rounded-md bg-muted/30">
              <img src={layout.logo_url} alt="logo" className="h-14 max-w-[160px] object-contain bg-background rounded border p-1" />
              <Button type="button" variant="ghost" size="sm"
                onClick={() => update("logo_url", "")} className="gap-1 text-destructive">
                <Trash2 className="h-4 w-4" /> Remove
              </Button>
            </div>
          ) : (
            <label className="inline-flex items-center gap-2 px-3 py-2 border rounded-md cursor-pointer hover:bg-muted text-sm">
              {uploadingLogo ? <Loader2 className="h-4 w-4 animate-spin" /> : <Upload className="h-4 w-4" />}
              {uploadingLogo ? "Uploading…" : "Upload logo (PNG)"}
              <input type="file" accept="image/png,image/jpeg" className="hidden"
                onChange={(e) => {
                  const f = e.target.files?.[0];
                  if (f) handleImageUpload(f, "check-logos", "logo_url");
                }} />
            </label>
          )}
          <p className="text-xs text-muted-foreground">
            Adjust logo size and position in the per-field editor below (under "Logo").
          </p>
        </CardContent>
      </Card>

      <Card>
        <CardHeader><CardTitle className="text-base">Payer Block</CardTitle></CardHeader>
        <CardContent className="space-y-4">
          <div className="flex items-center gap-3">
            <Switch id="show_payer" checked={!!layout.show_payer_block}
              onCheckedChange={(v) => update("show_payer_block", v)} />
            <Label htmlFor="show_payer" className="cursor-pointer">Show payer name & address</Label>
          </div>
          <div>
            <Label>Payer Name</Label>
            <Input value={layout.payer_name || ""}
              onChange={(e) => update("payer_name", e.target.value)}
              placeholder={associationName || "Association Name"} />
          </div>
          <div>
            <Label>Payer Address</Label>
            <Textarea rows={3} value={layout.payer_address || ""}
              onChange={(e) => update("payer_address", e.target.value)}
              placeholder={"123 Main Street\nCity, ST 12345"} />
          </div>
        </CardContent>
      </Card>

      <Card>
        <CardHeader><CardTitle className="text-base">Signature</CardTitle></CardHeader>
        <CardContent className="space-y-4">
          <div className="flex items-center gap-3">
            <Switch id="show_sig" checked={!!layout.show_signature_line}
              onCheckedChange={(v) => update("show_signature_line", v)} />
            <Label htmlFor="show_sig" className="cursor-pointer">Show signature line</Label>
          </div>
          <div>
            <Label>Signature Label</Label>
            <Input value={layout.signature_label || ""}
              onChange={(e) => update("signature_label", e.target.value)}
              placeholder="Authorized Signature" />
          </div>
          <div>
            <Label>Signature Image (optional)</Label>
            <p className="text-xs text-muted-foreground mb-2">
              Upload a PNG of the signature. Adjust its position and size freely in the per-field editor below (under "Signature Image") — no constraints.
            </p>
            {layout.signature_image_url ? (
              <div className="flex items-center gap-3 p-3 border rounded-md bg-muted/30">
                <img src={layout.signature_image_url} alt="signature" className="h-12 max-w-[200px] object-contain" />
                <Button type="button" variant="ghost" size="sm"
                  onClick={() => update("signature_image_url", "")} className="gap-1 text-destructive">
                  <Trash2 className="h-4 w-4" /> Remove
                </Button>
              </div>
            ) : (
              <label className="inline-flex items-center gap-2 px-3 py-2 border rounded-md cursor-pointer hover:bg-muted text-sm">
                {uploading ? <Loader2 className="h-4 w-4 animate-spin" /> : <Upload className="h-4 w-4" />}
                {uploading ? "Uploading…" : "Upload signature image"}
                <input type="file" accept="image/png,image/jpeg" className="hidden"
                  onChange={(e) => {
                    const f = e.target.files?.[0];
                    if (f) handleImageUpload(f, "check-signatures", "signature_image_url");
                  }} />
              </label>
            )}
          </div>
        </CardContent>
      </Card>

      <Card>
        <CardHeader><CardTitle className="text-base">Memo & Footer</CardTitle></CardHeader>
        <CardContent className="space-y-4">
          <div>
            <Label>Memo Prefix</Label>
            <Input value={layout.memo_prefix || ""}
              onChange={(e) => update("memo_prefix", e.target.value)}
              placeholder="e.g. HOA Dues —" />
          </div>
          <div>
            <Label>Footer Text</Label>
            <Input value={layout.footer_text || ""}
              onChange={(e) => update("footer_text", e.target.value)}
              placeholder="e.g. Void after 90 days" />
          </div>
        </CardContent>
      </Card>

      <Card>
        <CardHeader>
          <CardTitle className="text-base">Per-Field Position, Size & Labels</CardTitle>
          <p className="text-xs text-muted-foreground mt-1">
            Adjust X/Y in inches from the check's top-left corner. Set font size in points.
            For Payee/Memo/Date/etc., the printed label shows when "Print field labels" is on above.
          </p>
        </CardHeader>
        <CardContent className="space-y-2">
          <div className="grid grid-cols-12 gap-2 text-xs font-semibold text-muted-foreground px-2">
            <div className="col-span-3">Field</div>
            <div className="col-span-1 text-center">Show</div>
            <div className="col-span-1">X (in)</div>
            <div className="col-span-1">Y (in)</div>
            <div className="col-span-1">Size</div>
            <div className="col-span-4">Label</div>
            <div className="col-span-1" />
          </div>
          {FIELD_ORDER.map((key) => {
            const def = DEFAULT_FIELD_POSITIONS[key];
            const cur = (layout.field_positions || {})[key] || {};
            const isImage = key === "logo" || key === "signature_line" || key === "signature_image";
            return (
              <div key={key} className="grid grid-cols-12 gap-2 items-center px-2 py-1.5 rounded-md hover:bg-muted/40 border border-transparent hover:border-border">
                <div className="col-span-3 text-sm">{FIELD_LABELS[key]}</div>
                <div className="col-span-1 flex justify-center">
                  <Switch
                    checked={(cur.visible ?? def.visible) !== false}
                    onCheckedChange={(v) => updateField(key, { visible: v })}
                  />
                </div>
                <div className="col-span-1">
                  <Input type="number" step="0.05" className="h-8"
                    value={cur.x ?? def.x ?? 0}
                    onChange={(e) => updateField(key, { x: Number(e.target.value) })} />
                </div>
                <div className="col-span-1">
                  <Input type="number" step="0.05" className="h-8"
                    value={cur.y ?? def.y ?? 0}
                    onChange={(e) => updateField(key, { y: Number(e.target.value) })} />
                </div>
                <div className="col-span-1">
                  {isImage ? (
                    <Input type="number" step="0.05" className="h-8"
                      placeholder="W"
                      value={cur.width ?? def.width ?? 0}
                      onChange={(e) => updateField(key, { width: Number(e.target.value) })} />
                  ) : (
                    <Input type="number" step="1" className="h-8"
                      value={cur.font_size ?? def.font_size ?? 10}
                      onChange={(e) => updateField(key, { font_size: Number(e.target.value) })} />
                  )}
                </div>
                <div className="col-span-4">
                  {isImage ? (
                    <Input type="number" step="0.05" className="h-8"
                      placeholder="Height (in)"
                      value={cur.height ?? def.height ?? 0}
                      onChange={(e) => updateField(key, { height: Number(e.target.value) })} />
                  ) : (
                    <Input className="h-8"
                      placeholder={def.label || "(no label)"}
                      value={cur.label ?? def.label ?? ""}
                      onChange={(e) => updateField(key, { label: e.target.value })} />
                  )}
                </div>
                <div className="col-span-1 text-right">
                  <Button type="button" variant="ghost" size="sm" className="h-8 text-xs"
                    onClick={() => resetField(key)} title="Reset to default">
                    Reset
                  </Button>
                </div>
              </div>
            );
          })}
        </CardContent>
      </Card>
    </div>
  );
}
