"use client";

import * as React from "react";
import Link from "next/link";
import { useParams } from "next/navigation";
import { toast } from "sonner";
import {
  ArrowLeft,
  ChevronUp,
  ChevronDown,
  FileText,
  GripVertical,
  Loader2,
  Plus,
  Save,
  Trash2,
  X,
  Asterisk,
  Lock,
} from "lucide-react";
import { Header } from "@/components/layout/header";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Badge } from "@/components/ui/badge";
import { Switch } from "@/components/ui/switch";
import { Textarea } from "@/components/ui/textarea";
import { Separator } from "@/components/ui/separator";
import {
  Card,
  CardContent,
  CardHeader,
  CardTitle,
  CardDescription,
} from "@/components/ui/card";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";

const FIELD_TYPES = [
  { value: "text", label: "Text" },
  { value: "textarea", label: "Text Area" },
  { value: "email", label: "Email" },
  { value: "phone", label: "Phone" },
  { value: "date", label: "Date" },
  { value: "select", label: "Select" },
  { value: "multiselect", label: "Multi-Select" },
  { value: "checkbox", label: "Checkbox" },
  { value: "radio", label: "Radio" },
  { value: "number", label: "Number" },
  { value: "url", label: "URL" },
] as const;

const SECTIONS = [
  { value: "personal", label: "Personal" },
  { value: "contact", label: "Contact" },
  { value: "address", label: "Address" },
  { value: "survey", label: "Survey" },
  { value: "followup", label: "Follow-up" },
  { value: "custom", label: "Custom" },
] as const;

const HAS_OPTIONS = new Set(["select", "multiselect", "radio"]);

type TemplateField = {
  id: string;
  label: string;
  key: string;
  type: string;
  section: string;
  isRequired: boolean;
  isCore: boolean;
  sortOrder: number;
  options: string[] | null;
  placeholder: string | null;
  helpText: string | null;
  visibleOnCard: boolean;
  visibleOnSurvey: boolean;
};

type Template = {
  id: string;
  name: string;
  description: string | null;
  isDefault: boolean;
  isActive: boolean;
  fields: TemplateField[];
};

export default function TemplateEditorPage() {
  const params = useParams();
  const id = params.id as string;

  const [template, setTemplate] = React.useState<Template | null>(null);
  const [loading, setLoading] = React.useState(true);
  const [error, setError] = React.useState<string | null>(null);
  const [selectedFieldId, setSelectedFieldId] = React.useState<string | null>(
    null
  );
  const [savingTemplate, setSavingTemplate] = React.useState(false);
  const [savingField, setSavingField] = React.useState(false);
  const [addingField, setAddingField] = React.useState(false);
  const [showAddForm, setShowAddForm] = React.useState(false);

  const [newField, setNewField] = React.useState({
    label: "",
    key: "",
    type: "text",
    section: "custom",
  });

  const fetchTemplate = React.useCallback(async () => {
    try {
      const res = await fetch(`/api/form-templates/${id}`);
      if (!res.ok) throw new Error("Failed to fetch");
      const data = await res.json();
      setTemplate(data.template ?? data);
      setError(null);
    } catch {
      setError("Failed to load template.");
    } finally {
      setLoading(false);
    }
  }, [id]);

  React.useEffect(() => {
    fetchTemplate();
  }, [fetchTemplate]);

  const selectedField = template?.fields.find(
    (f) => f.id === selectedFieldId
  );

  const fieldsBySection = React.useMemo(() => {
    if (!template) return {};
    const grouped: Record<string, TemplateField[]> = {};
    for (const field of template.fields) {
      const section = field.section || "custom";
      if (!grouped[section]) grouped[section] = [];
      grouped[section].push(field);
    }
    for (const section of Object.keys(grouped)) {
      grouped[section].sort((a, b) => a.sortOrder - b.sortOrder);
    }
    return grouped;
  }, [template]);

  const handleSaveTemplate = async () => {
    if (!template) return;
    setSavingTemplate(true);
    try {
      const res = await fetch(`/api/form-templates/${id}`, {
        method: "PUT",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          name: template.name,
          description: template.description,
          isActive: template.isActive,
        }),
      });
      if (!res.ok) throw new Error("Failed to update");
      toast.success("Template updated");
    } catch {
      toast.error("Failed to update template");
    } finally {
      setSavingTemplate(false);
    }
  };

  const handleSaveField = async () => {
    if (!selectedField) return;
    setSavingField(true);
    try {
      const res = await fetch(
        `/api/form-templates/${id}/fields/${selectedField.id}`,
        {
          method: "PUT",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            label: selectedField.label,
            type: selectedField.type,
            section: selectedField.section,
            isRequired: selectedField.isRequired,
            options: selectedField.options,
            placeholder: selectedField.placeholder,
            helpText: selectedField.helpText,
            visibleOnCard: selectedField.visibleOnCard,
            visibleOnSurvey: selectedField.visibleOnSurvey,
          }),
        }
      );
      if (!res.ok) throw new Error("Failed to update");
      toast.success("Field updated");
    } catch {
      toast.error("Failed to update field");
    } finally {
      setSavingField(false);
    }
  };

  const handleAddField = async () => {
    if (!newField.label.trim() || !newField.key.trim()) return;
    setAddingField(true);
    try {
      const res = await fetch(`/api/form-templates/${id}/fields`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          label: newField.label.trim(),
          key: newField.key.trim(),
          type: newField.type,
          section: newField.section,
        }),
      });
      if (!res.ok) throw new Error("Failed to add field");
      toast.success("Field added");
      setNewField({ label: "", key: "", type: "text", section: "custom" });
      setShowAddForm(false);
      fetchTemplate();
    } catch {
      toast.error("Failed to add field");
    } finally {
      setAddingField(false);
    }
  };

  const handleDeleteField = async (field: TemplateField) => {
    if (field.isCore) return;
    try {
      const res = await fetch(
        `/api/form-templates/${id}/fields/${field.id}`,
        { method: "DELETE" }
      );
      if (!res.ok) throw new Error("Failed to delete");
      setTemplate((prev) =>
        prev
          ? { ...prev, fields: prev.fields.filter((f) => f.id !== field.id) }
          : prev
      );
      if (selectedFieldId === field.id) setSelectedFieldId(null);
      toast.success("Field deleted");
    } catch {
      toast.error("Failed to delete field");
    }
  };

  const handleReorder = async (
    field: TemplateField,
    direction: "up" | "down"
  ) => {
    if (!template) return;
    const sectionFields = template.fields
      .filter((f) => f.section === field.section)
      .sort((a, b) => a.sortOrder - b.sortOrder);

    const idx = sectionFields.findIndex((f) => f.id === field.id);
    if (
      (direction === "up" && idx === 0) ||
      (direction === "down" && idx === sectionFields.length - 1)
    )
      return;

    const swapWith =
      direction === "up" ? sectionFields[idx - 1] : sectionFields[idx + 1];

    const newFields = template.fields.map((f) => {
      if (f.id === field.id) return { ...f, sortOrder: swapWith.sortOrder };
      if (f.id === swapWith.id) return { ...f, sortOrder: field.sortOrder };
      return f;
    });

    setTemplate({ ...template, fields: newFields });

    try {
      await fetch(`/api/form-templates/${id}/fields/${field.id}`, {
        method: "PUT",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ sortOrder: swapWith.sortOrder }),
      });
      await fetch(`/api/form-templates/${id}/fields/${swapWith.id}`, {
        method: "PUT",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ sortOrder: field.sortOrder }),
      });
    } catch {
      toast.error("Failed to reorder fields");
      fetchTemplate();
    }
  };

  const updateSelectedField = (updates: Partial<TemplateField>) => {
    if (!selectedFieldId || !template) return;
    setTemplate({
      ...template,
      fields: template.fields.map((f) =>
        f.id === selectedFieldId ? { ...f, ...updates } : f
      ),
    });
  };

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

  if (error || !template) {
    return (
      <div className="space-y-4">
        <Button
          variant="ghost"
          size="sm"
          render={<Link href="/settings/forms" />}
        >
          <ArrowLeft className="size-4" />
          Back to templates
        </Button>
        <div className="glass-card rounded-2xl p-8 text-center text-sm text-muted-foreground">
          {error ?? "Template not found."}
        </div>
      </div>
    );
  }

  return (
    <div className="space-y-6">
      <div className="flex items-center gap-3">
        <Button
          variant="ghost"
          size="icon-sm"
          render={<Link href="/settings/forms" />}
        >
          <ArrowLeft className="size-4" />
        </Button>
        <Header title={template.name} icon={FileText} />
      </div>

      {/* Template Settings */}
      <Card className="glass-card">
        <CardHeader>
          <CardTitle className="text-base">Template Settings</CardTitle>
          <CardDescription>
            Update the template name, description, and status.
          </CardDescription>
        </CardHeader>
        <CardContent className="space-y-4">
          <div className="grid gap-4 sm:grid-cols-2">
            <div className="space-y-2">
              <Label>Name</Label>
              <Input
                value={template.name}
                onChange={(e) =>
                  setTemplate({ ...template, name: e.target.value })
                }
              />
            </div>
            <div className="space-y-2">
              <Label>Description</Label>
              <Input
                value={template.description ?? ""}
                onChange={(e) =>
                  setTemplate({
                    ...template,
                    description: e.target.value || null,
                  })
                }
                placeholder="Optional description..."
              />
            </div>
          </div>
          <div className="flex items-center justify-between">
            <div>
              <Label>Active</Label>
              <p className="text-xs text-muted-foreground">
                Inactive templates won&apos;t appear when creating new cards.
              </p>
            </div>
            <Switch
              checked={template.isActive}
              onCheckedChange={(checked) =>
                setTemplate({ ...template, isActive: !!checked })
              }
            />
          </div>
          <div className="flex justify-end">
            <Button onClick={handleSaveTemplate} disabled={savingTemplate}>
              {savingTemplate ? (
                <Loader2 className="mr-2 size-4 animate-spin" />
              ) : (
                <Save className="mr-2 size-4" />
              )}
              Save Settings
            </Button>
          </div>
        </CardContent>
      </Card>

      <Separator />

      {/* Field Editor Layout */}
      <div className="grid gap-6 lg:grid-cols-[1fr_1fr]">
        {/* Left Panel - Field List */}
        <div className="space-y-4">
          <div className="flex items-center justify-between">
            <h2 className="text-sm font-semibold text-foreground">Fields</h2>
            <Button
              variant="outline"
              size="xs"
              onClick={() => setShowAddForm((v) => !v)}
            >
              {showAddForm ? (
                <>
                  <X className="size-3" />
                  Cancel
                </>
              ) : (
                <>
                  <Plus className="size-3" />
                  Add Field
                </>
              )}
            </Button>
          </div>

          {showAddForm && (
            <Card className="glass-card">
              <CardContent className="space-y-3 pt-4">
                <div className="grid gap-3 sm:grid-cols-2">
                  <div className="space-y-1.5">
                    <Label className="text-xs">Label</Label>
                    <Input
                      placeholder="e.g. Phone Number"
                      value={newField.label}
                      onChange={(e) => {
                        const label = e.target.value;
                        setNewField({
                          ...newField,
                          label,
                          key: label
                            .toLowerCase()
                            .replace(/[^a-z0-9]+/g, "_")
                            .replace(/^_|_$/g, ""),
                        });
                      }}
                    />
                  </div>
                  <div className="space-y-1.5">
                    <Label className="text-xs">Key</Label>
                    <Input
                      placeholder="phone_number"
                      value={newField.key}
                      onChange={(e) =>
                        setNewField({ ...newField, key: e.target.value })
                      }
                    />
                  </div>
                </div>
                <div className="grid gap-3 sm:grid-cols-2">
                  <div className="space-y-1.5">
                    <Label className="text-xs">Type</Label>
                    <Select
                      value={newField.type}
                      onValueChange={(v) =>
                        setNewField({ ...newField, type: v as string })
                      }
                    >
                      <SelectTrigger className="w-full">
                        <SelectValue />
                      </SelectTrigger>
                      <SelectContent>
                        {FIELD_TYPES.map((ft) => (
                          <SelectItem key={ft.value} value={ft.value}>
                            {ft.label}
                          </SelectItem>
                        ))}
                      </SelectContent>
                    </Select>
                  </div>
                  <div className="space-y-1.5">
                    <Label className="text-xs">Section</Label>
                    <Select
                      value={newField.section}
                      onValueChange={(v) =>
                        setNewField({ ...newField, section: v as string })
                      }
                    >
                      <SelectTrigger className="w-full">
                        <SelectValue />
                      </SelectTrigger>
                      <SelectContent>
                        {SECTIONS.map((s) => (
                          <SelectItem key={s.value} value={s.value}>
                            {s.label}
                          </SelectItem>
                        ))}
                      </SelectContent>
                    </Select>
                  </div>
                </div>
                <div className="flex justify-end">
                  <Button
                    size="sm"
                    onClick={handleAddField}
                    disabled={
                      addingField ||
                      !newField.label.trim() ||
                      !newField.key.trim()
                    }
                  >
                    {addingField && (
                      <Loader2 className="mr-1 size-3 animate-spin" />
                    )}
                    Add Field
                  </Button>
                </div>
              </CardContent>
            </Card>
          )}

          {Object.keys(fieldsBySection).length === 0 ? (
            <div className="glass-card rounded-2xl p-8 text-center text-sm text-muted-foreground">
              No fields yet. Add your first field to get started.
            </div>
          ) : (
            <div className="space-y-4">
              {SECTIONS.map((section) => {
                const fields = fieldsBySection[section.value];
                if (!fields || fields.length === 0) return null;
                return (
                  <div key={section.value}>
                    <p className="mb-2 text-xs font-semibold uppercase tracking-wider text-muted-foreground">
                      {section.label}
                    </p>
                    <div className="space-y-1">
                      {fields.map((field, idx) => (
                        <button
                          key={field.id}
                          type="button"
                          onClick={() => setSelectedFieldId(field.id)}
                          className={`flex w-full items-center gap-2 rounded-lg px-3 py-2 text-left text-sm transition-colors ${
                            selectedFieldId === field.id
                              ? "bg-primary/10 text-primary ring-1 ring-primary/20"
                              : "hover:bg-muted/50"
                          }`}
                        >
                          <GripVertical className="size-3.5 shrink-0 text-muted-foreground/50" />
                          <span className="min-w-0 flex-1 truncate font-medium">
                            {field.label}
                          </span>
                          <div className="flex shrink-0 items-center gap-1">
                            {field.isRequired && (
                              <Asterisk className="size-3 text-destructive" />
                            )}
                            {field.isCore && (
                              <Lock className="size-3 text-muted-foreground" />
                            )}
                            <Badge variant="secondary" className="text-[10px]">
                              {field.type}
                            </Badge>
                          </div>
                          <div className="flex shrink-0 items-center">
                            <Button
                              variant="ghost"
                              size="icon-xs"
                              onClick={(e) => {
                                e.stopPropagation();
                                handleReorder(field, "up");
                              }}
                              disabled={idx === 0}
                              className="size-5"
                            >
                              <ChevronUp className="size-3" />
                            </Button>
                            <Button
                              variant="ghost"
                              size="icon-xs"
                              onClick={(e) => {
                                e.stopPropagation();
                                handleReorder(field, "down");
                              }}
                              disabled={idx === fields.length - 1}
                              className="size-5"
                            >
                              <ChevronDown className="size-3" />
                            </Button>
                          </div>
                        </button>
                      ))}
                    </div>
                  </div>
                );
              })}
            </div>
          )}
        </div>

        {/* Right Panel - Field Editor */}
        <div>
          {selectedField ? (
            <FieldEditor
              field={selectedField}
              isCore={selectedField.isCore}
              onChange={updateSelectedField}
              onSave={handleSaveField}
              onDelete={() => handleDeleteField(selectedField)}
              saving={savingField}
            />
          ) : (
            <div className="glass-card flex flex-col items-center gap-2 rounded-2xl p-12 text-center">
              <FileText className="size-8 text-muted-foreground/30" />
              <p className="text-sm text-muted-foreground">
                Select a field to edit its properties
              </p>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

function FieldEditor({
  field,
  isCore,
  onChange,
  onSave,
  onDelete,
  saving,
}: {
  field: TemplateField;
  isCore: boolean;
  onChange: (updates: Partial<TemplateField>) => void;
  onSave: () => void;
  onDelete: () => void;
  saving: boolean;
}) {
  const [optionInput, setOptionInput] = React.useState("");

  const addOption = () => {
    const val = optionInput.trim();
    if (!val) return;
    const current = field.options ?? [];
    if (!current.includes(val)) {
      onChange({ options: [...current, val] });
    }
    setOptionInput("");
  };

  const removeOption = (opt: string) => {
    onChange({ options: (field.options ?? []).filter((o) => o !== opt) });
  };

  return (
    <Card className="glass-card sticky top-4">
      <CardHeader>
        <div className="flex items-center justify-between">
          <CardTitle className="text-base">Edit Field</CardTitle>
          {!isCore && (
            <Button variant="destructive" size="xs" onClick={onDelete}>
              <Trash2 className="size-3" />
              Delete
            </Button>
          )}
        </div>
        <CardDescription>
          {isCore
            ? "Core fields cannot be deleted or have their key changed."
            : "Configure this field's properties."}
        </CardDescription>
      </CardHeader>
      <CardContent className="space-y-4">
        <div className="space-y-2">
          <Label>Label</Label>
          <Input
            value={field.label}
            onChange={(e) => onChange({ label: e.target.value })}
          />
        </div>

        <div className="space-y-2">
          <Label>Key</Label>
          <Input value={field.key} disabled={isCore} className={isCore ? "opacity-60" : ""} onChange={(e) => !isCore && onChange({ key: e.target.value })} />
          {isCore && (
            <p className="text-xs text-muted-foreground">
              Core field keys cannot be changed.
            </p>
          )}
        </div>

        <div className="grid gap-4 sm:grid-cols-2">
          <div className="space-y-2">
            <Label>Type</Label>
            <Select
              value={field.type}
              onValueChange={(v) => onChange({ type: v as string })}
            >
              <SelectTrigger className="w-full">
                <SelectValue />
              </SelectTrigger>
              <SelectContent>
                {FIELD_TYPES.map((ft) => (
                  <SelectItem key={ft.value} value={ft.value}>
                    {ft.label}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>
          <div className="space-y-2">
            <Label>Section</Label>
            <Select
              value={field.section}
              onValueChange={(v) => onChange({ section: v as string })}
            >
              <SelectTrigger className="w-full">
                <SelectValue />
              </SelectTrigger>
              <SelectContent>
                {SECTIONS.map((s) => (
                  <SelectItem key={s.value} value={s.value}>
                    {s.label}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>
        </div>

        <div className="space-y-2">
          <Label>Placeholder</Label>
          <Input
            value={field.placeholder ?? ""}
            onChange={(e) =>
              onChange({ placeholder: e.target.value || null })
            }
            placeholder="Optional placeholder text..."
          />
        </div>

        <div className="space-y-2">
          <Label>Help Text</Label>
          <Textarea
            value={field.helpText ?? ""}
            onChange={(e) =>
              onChange({ helpText: e.target.value || null })
            }
            placeholder="Optional help text shown below the field..."
            rows={2}
          />
        </div>

        {HAS_OPTIONS.has(field.type) && (
          <div className="space-y-2">
            <Label>Options</Label>
            {field.options && field.options.length > 0 && (
              <div className="flex flex-wrap gap-1.5">
                {field.options.map((opt) => (
                  <span
                    key={opt}
                    className="inline-flex items-center gap-1 rounded-full bg-secondary px-2.5 py-0.5 text-xs font-medium text-secondary-foreground"
                  >
                    {opt}
                    <button
                      type="button"
                      onClick={() => removeOption(opt)}
                      className="rounded-full p-0.5 hover:bg-foreground/10"
                    >
                      <X className="size-2.5" />
                    </button>
                  </span>
                ))}
              </div>
            )}
            <div className="flex gap-2">
              <Input
                placeholder="Add an option..."
                value={optionInput}
                onChange={(e) => setOptionInput(e.target.value)}
                onKeyDown={(e) => {
                  if (e.key === "Enter") {
                    e.preventDefault();
                    addOption();
                  }
                }}
              />
              <Button
                variant="outline"
                size="sm"
                onClick={addOption}
                disabled={!optionInput.trim()}
              >
                Add
              </Button>
            </div>
          </div>
        )}

        <Separator />

        <div className="space-y-3">
          <div className="flex items-center justify-between">
            <div>
              <Label>Required</Label>
              <p className="text-xs text-muted-foreground">
                Field must be filled when submitting
              </p>
            </div>
            <Switch
              size="sm"
              checked={field.isRequired}
              onCheckedChange={(checked) =>
                onChange({ isRequired: !!checked })
              }
            />
          </div>
          <div className="flex items-center justify-between">
            <div>
              <Label>Visible on Card</Label>
              <p className="text-xs text-muted-foreground">
                Show this field on the connect card
              </p>
            </div>
            <Switch
              size="sm"
              checked={field.visibleOnCard}
              onCheckedChange={(checked) =>
                onChange({ visibleOnCard: !!checked })
              }
            />
          </div>
          <div className="flex items-center justify-between">
            <div>
              <Label>Visible on Survey</Label>
              <p className="text-xs text-muted-foreground">
                Show this field on the digital survey
              </p>
            </div>
            <Switch
              size="sm"
              checked={field.visibleOnSurvey}
              onCheckedChange={(checked) =>
                onChange({ visibleOnSurvey: !!checked })
              }
            />
          </div>
        </div>

        <div className="flex justify-end pt-2">
          <Button onClick={onSave} disabled={saving}>
            {saving ? (
              <Loader2 className="mr-2 size-4 animate-spin" />
            ) : (
              <Save className="mr-2 size-4" />
            )}
            Save Field
          </Button>
        </div>
      </CardContent>
    </Card>
  );
}
