"use client";

import { useState, useEffect, useRef } from "react";
import { Plus, Pencil, Sparkles, X } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog";
import { Label } from "@/components/ui/label";
import { Combobox } from "@/components/ui/combobox";
import { CATEGORY_OPTIONS, getSubcategoryOptions } from "@/lib/pantry/categories";
import type { PantryItem, LocationOption, PlantOption } from "./pantry-client";

const SOURCES = [
  { value: "GARDEN", label: "Our garden" },
  { value: "HOMEMADE", label: "Homemade" },
  { value: "STORE", label: "Store" },
  { value: "FARMERS_MARKET", label: "Farmers market" },
  { value: "GIFTED", label: "Gifted" },
  { value: "OTHER", label: "Other" },
];

const COMMON_UNITS = ["lbs", "oz", "g", "kg", "bags", "jars", "quart jars", "pint jars", "gallon bags", "quart bags", "containers", "cans", "bottles", "bunches", "loaves", "portions", "each"];
const PRICE_UNITS = ["package", "lb", "oz", "kg", "each", "dozen", "bunch"];


type Suggestion = {
  name: string;
  description: string | null;
  unit: string | null;
  source: string | null;
  pantryCategory: string | null;
  pantrySubcategory: string | null;
  priceUnit: string | null;
  pricePaid: number | null;
  locationId: string | null;
  locationName: string | null;
  plantId: string | null;
};

type CatalogData = {
  suggestions: Suggestion[];
  categories: string[];
  subcategories: { category: string; subcategory: string }[];
  labels: string[];
};

type Form = {
  name: string;
  description: string;
  quantity: string;
  unit: string;
  locationId: string;
  storedAt: string;
  bestBefore: string;
  source: string;
  plantId: string;
  pantryCategory: string;
  pantrySubcategory: string;
  pricePaid: string;
  priceUnit: string;
  notes: string;
};

type Props = {
  item?: PantryItem;
  locations: LocationOption[];
  plants: PlantOption[];
  onSuccess: () => void;
};

export function PantryItemDialog({ item, locations, plants, onSuccess }: Props) {
  const [open, setOpen] = useState(false);
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [catalog, setCatalog] = useState<CatalogData | null>(null);
  const [nameSuggestions, setNameSuggestions] = useState<Suggestion[]>([]);
  const [showDropdown, setShowDropdown] = useState(false);
  const [autofillBanner, setAutofillBanner] = useState<Suggestion | null>(null);
  const [tags, setTags] = useState<string[]>(item?.tags ?? []);
  const [tagInput, setTagInput] = useState("");
  const [tagSuggestions, setTagSuggestions] = useState<string[]>([]);
  const [showTagDropdown, setShowTagDropdown] = useState(false);
  const nameRef = useRef<HTMLInputElement>(null);
  const tagInputRef = useRef<HTMLInputElement>(null);
  const debounceRef = useRef<ReturnType<typeof setTimeout>>();

  const blankForm = (): Form => ({
    name: item?.name ?? "",
    description: item?.description ?? "",
    quantity: item?.quantity?.toString() ?? "1",
    unit: item?.unit ?? "",
    locationId: item?.locationId ?? "",
    storedAt: item?.storedAt ? new Date(item.storedAt).toISOString().slice(0, 10) : "",
    bestBefore: item?.bestBefore ? new Date(item.bestBefore).toISOString().slice(0, 10) : "",
    source: item?.source ?? "",
    plantId: item?.plantId ?? "",
    pantryCategory: (item as any)?.pantryCategory ?? "",
    pantrySubcategory: (item as any)?.pantrySubcategory ?? "",
    pricePaid: (item as any)?.pricePaid?.toString() ?? "",
    priceUnit: (item as any)?.priceUnit ?? "package",
    notes: item?.notes ?? "",
  });

  const [form, setForm] = useState<Form>(blankForm);

  function set(key: keyof Form, val: string) {
    setForm(f => ({ ...f, [key]: val }));
  }

  function addTag(name: string) {
    const t = name.trim();
    if (!t || tags.includes(t)) return;
    setTags(prev => [...prev, t]);
    setTagInput("");
    setShowTagDropdown(false);
  }

  function removeTag(name: string) {
    setTags(prev => prev.filter(t => t !== name));
  }

  function handleTagKeyDown(e: React.KeyboardEvent<HTMLInputElement>) {
    if ((e.key === "Enter" || e.key === ",") && tagInput.trim()) {
      e.preventDefault();
      addTag(tagInput);
    } else if (e.key === "Backspace" && !tagInput && tags.length) {
      removeTag(tags[tags.length - 1]);
    }
  }

  // Reset tag state when dialog opens/closes
  useEffect(() => {
    if (open) {
      setTags(item?.tags ?? []);
      setTagInput("");
    }
  }, [open]);

  // Load catalog on open (for name autocomplete suggestions)
  useEffect(() => {
    if (!open) return;
    fetch("/api/v1/pantry/catalog")
      .then(r => r.json())
      .then(setCatalog)
      .catch(() => {});
  }, [open]);

  // Tag autocomplete from catalog labels
  useEffect(() => {
    const q = tagInput.trim().toLowerCase();
    if (!q || !catalog?.labels) { setTagSuggestions([]); setShowTagDropdown(false); return; }
    const matches = catalog.labels.filter(l => l.toLowerCase().includes(q) && !tags.includes(l));
    setTagSuggestions(matches.slice(0, 6));
    setShowTagDropdown(matches.length > 0 || q.length > 0);
  }, [tagInput, catalog, tags]);

  // Debounced name search for autocomplete
  function handleNameChange(val: string) {
    set("name", val);
    setAutofillBanner(null);
    clearTimeout(debounceRef.current);
    if (val.length < 2) { setNameSuggestions([]); setShowDropdown(false); return; }
    debounceRef.current = setTimeout(async () => {
      const res = await fetch(`/api/v1/pantry/catalog?q=${encodeURIComponent(val)}`);
      if (!res.ok) return;
      const data: CatalogData = await res.json();
      setNameSuggestions(data.suggestions.slice(0, 6));
      setShowDropdown(data.suggestions.length > 0);
    }, 200);
  }

  function applyAutofill(s: Suggestion) {
    setForm(f => ({
      ...f,
      name: s.name,
      description: s.description ?? f.description,
      unit: s.unit ?? f.unit,
      source: s.source ?? f.source,
      pantryCategory: s.pantryCategory ?? f.pantryCategory,
      pantrySubcategory: s.pantrySubcategory ?? f.pantrySubcategory,
      priceUnit: s.priceUnit ?? f.priceUnit,
      pricePaid: s.pricePaid != null ? s.pricePaid.toString() : f.pricePaid,
      locationId: s.locationId ?? f.locationId,
      plantId: s.plantId ?? f.plantId,
    }));
    setShowDropdown(false);
    setAutofillBanner(null);
  }

  function selectSuggestion(s: Suggestion) {
    setShowDropdown(false);
    setAutofillBanner(s);
    set("name", s.name);
  }

  // Merge static category list with any custom categories previously saved to the DB.
  const catalogCategories: string[] = catalog?.categories ?? [];
  const knownCategoryValues = new Set(CATEGORY_OPTIONS.map(o => o.value.toLowerCase()));
  const extraCategoryOptions = catalogCategories
    .filter(c => !knownCategoryValues.has(c.toLowerCase()))
    .map(c => ({ value: c, label: c }));
  const allCategoryOptions = [...CATEGORY_OPTIONS, ...extraCategoryOptions];

  // Static subcategories for this category + any custom ones from the catalog.
  const staticSubcategoryOptions = getSubcategoryOptions(form.pantryCategory);
  const catalogSubcategories: { category: string; subcategory: string }[] = catalog?.subcategories ?? [];
  const knownSubValues = new Set(staticSubcategoryOptions.map(o => o.value.toLowerCase()));
  const extraSubOptions = catalogSubcategories
    .filter(cs => cs.category.toLowerCase() === form.pantryCategory.toLowerCase() && !knownSubValues.has(cs.subcategory.toLowerCase()))
    .map(cs => ({ value: cs.subcategory, label: cs.subcategory }));
  const subcategoryOptions = [...staticSubcategoryOptions, ...extraSubOptions];

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    setSaving(true);
    setError(null);
    try {
      const body = {
        name: form.name.trim(),
        description: form.description.trim() || null,
        quantity: parseFloat(form.quantity) || 1,
        unit: form.unit.trim() || null,
        locationId: form.locationId || null,
        storedAt: form.storedAt || null,
        bestBefore: form.bestBefore || null,
        source: form.source || null,
        plantId: form.plantId || null,
        pantryCategory: form.pantryCategory.trim() || null,
        pantrySubcategory: form.pantrySubcategory.trim() || null,
        pricePaid: form.pricePaid ? parseFloat(form.pricePaid) : null,
        priceUnit: form.priceUnit || null,
        notes: form.notes.trim() || null,
        kind: "CONSUMABLE",
        tags,
      };
      const res = await fetch(item ? `/api/v1/pantry/${item.id}` : "/api/v1/pantry", {
        method: item ? "PATCH" : "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(body),
      });
      if (!res.ok) throw new Error((await res.json()).error ?? "Failed");
      setOpen(false);
      setForm(blankForm());
      setAutofillBanner(null);
      setTags([]);
      setTagInput("");
      onSuccess();
    } catch (err) {
      setError(String(err).replace("Error: ", ""));
    } finally {
      setSaving(false);
    }
  }

  const inputCls = "w-full rounded-md border bg-background px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring";

  return (
    <>
      {item ? (
        <Button variant="ghost" size="icon" className="h-8 w-8" onClick={() => setOpen(true)}>
          <Pencil className="h-3.5 w-3.5" />
        </Button>
      ) : (
        <Button onClick={() => setOpen(true)} className="gap-2">
          <Plus className="h-4 w-4" /> Add item
        </Button>
      )}

      <Dialog open={open} onOpenChange={o => { setOpen(o); if (!o) { setAutofillBanner(null); setShowDropdown(false); } }}>
        <DialogContent className="max-w-lg max-h-[90vh] overflow-y-auto">
          <DialogHeader>
            <DialogTitle>{item ? "Edit item" : "Add pantry item"}</DialogTitle>
          </DialogHeader>

          <form onSubmit={handleSubmit} noValidate className="space-y-4 py-2">

            {/* Name with autocomplete */}
            <div className="space-y-1 relative">
              <Label>Name *</Label>
              <input
                ref={nameRef}
                className={inputCls}
                value={form.name}
                onChange={e => handleNameChange(e.target.value)}
                onBlur={() => setTimeout(() => setShowDropdown(false), 150)}
                required
                placeholder="e.g. Blueberries, Ground beef, Chicken broth"
              />
              {showDropdown && nameSuggestions.length > 0 && (
                <div className="absolute z-50 left-0 right-0 top-full mt-1 bg-popover border rounded-md shadow-md overflow-hidden">
                  <p className="px-3 py-1.5 text-[10px] text-muted-foreground uppercase tracking-wider">Previously added</p>
                  {nameSuggestions.map(s => (
                    <button
                      key={s.name}
                      type="button"
                      onMouseDown={() => selectSuggestion(s)}
                      className="w-full text-left px-3 py-2 text-sm hover:bg-accent flex items-center justify-between gap-2"
                    >
                      <span>{s.name}</span>
                      <span className="text-xs text-muted-foreground shrink-0">
                        {[s.pantryCategory, s.pantrySubcategory].filter(Boolean).join(" › ")}
                      </span>
                    </button>
                  ))}
                </div>
              )}
            </div>

            {/* Autofill banner */}
            {autofillBanner && (
              <div className="flex items-center gap-2 rounded-md bg-amber-50 border border-amber-200 px-3 py-2 text-sm">
                <Sparkles className="h-4 w-4 text-amber-500 shrink-0" />
                <span className="flex-1 text-amber-800">
                  Fill in previous settings for <strong>{autofillBanner.name}</strong>?
                </span>
                <button type="button" onClick={() => applyAutofill(autofillBanner)} className="text-amber-700 font-medium hover:underline shrink-0">Apply</button>
                <button type="button" onClick={() => setAutofillBanner(null)} className="text-amber-400 hover:text-amber-600">
                  <X className="h-4 w-4" />
                </button>
              </div>
            )}

            {/* Category */}
            <div className="grid grid-cols-2 gap-3">
              <div className="space-y-1">
                <Label>Category</Label>
                <Combobox
                  options={allCategoryOptions}
                  value={form.pantryCategory}
                  onChange={v => { set("pantryCategory", v); set("pantrySubcategory", ""); }}
                  placeholder="Select or add category…"
                  allowCustom
                />
              </div>
              <div className="space-y-1">
                <Label>Subcategory</Label>
                <Combobox
                  options={subcategoryOptions}
                  value={form.pantrySubcategory}
                  onChange={v => set("pantrySubcategory", v)}
                  placeholder="Select or add…"
                  disabled={!form.pantryCategory}
                  emptyText="Type to add a subcategory"
                  allowCustom
                />
              </div>
            </div>

            {/* Description */}
            <div className="space-y-1">
              <Label>Package / container description</Label>
              <input className={inputCls} value={form.description} onChange={e => set("description", e.target.value)} placeholder="e.g. 1-gallon freezer bag, quart jar, vacuum-sealed" />
            </div>

            {/* Quantity + unit */}
            <div className="grid grid-cols-2 gap-3">
              <div className="space-y-1">
                <Label>Quantity *</Label>
                <input className={inputCls} type="number" min="0" step="1" value={form.quantity} onChange={e => set("quantity", e.target.value)} required />
              </div>
              <div className="space-y-1">
                <Label>Unit</Label>
                <input className={inputCls} list="unit-list" value={form.unit} onChange={e => set("unit", e.target.value)} placeholder="bags, lbs, jars…" />
                <datalist id="unit-list">
                  {COMMON_UNITS.map(u => <option key={u} value={u} />)}
                </datalist>
              </div>
            </div>

            {/* Price */}
            <div className="grid grid-cols-2 gap-3">
              <div className="space-y-1">
                <Label>Price paid</Label>
                <div className="relative">
                  <span className="absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground text-sm">$</span>
                  <input className={inputCls + " pl-6"} type="number" min="0" step="0.01" value={form.pricePaid} onChange={e => set("pricePaid", e.target.value)} placeholder="0.00" />
                </div>
              </div>
              <div className="space-y-1">
                <Label>Per</Label>
                <select className={inputCls} value={form.priceUnit} onChange={e => set("priceUnit", e.target.value)}>
                  {PRICE_UNITS.map(u => <option key={u} value={u}>{u}</option>)}
                </select>
              </div>
            </div>

            {/* Location */}
            <div className="space-y-1">
              <Label>Location</Label>
              <select className={inputCls} value={form.locationId} onChange={e => set("locationId", e.target.value)}>
                <option value="">— none —</option>
                {locations.map(l => <option key={l.id} value={l.id}>{l.name}</option>)}
              </select>
            </div>

            {/* Dates */}
            <div className="grid grid-cols-2 gap-3">
              <div className="space-y-1">
                <Label>Date stored / frozen</Label>
                <input className={inputCls} type="date" value={form.storedAt} onChange={e => set("storedAt", e.target.value)} />
              </div>
              <div className="space-y-1">
                <Label>Best by / expires</Label>
                <input className={inputCls} type="date" value={form.bestBefore} onChange={e => set("bestBefore", e.target.value)} />
              </div>
            </div>

            {/* Source */}
            <div className="space-y-1">
              <Label>Source</Label>
              <select className={inputCls} value={form.source} onChange={e => set("source", e.target.value)}>
                <option value="">— unknown —</option>
                {SOURCES.map(s => <option key={s.value} value={s.value}>{s.label}</option>)}
              </select>
            </div>

            {form.source === "GARDEN" && (
              <div className="space-y-1">
                <Label>Plant</Label>
                <select className={inputCls} value={form.plantId} onChange={e => set("plantId", e.target.value)}>
                  <option value="">— select a plant —</option>
                  {plants.map(p => (
                    <option key={p.id} value={p.id}>{p.commonName}{p.variety ? ` (${p.variety})` : ""}</option>
                  ))}
                </select>
              </div>
            )}

            <div className="space-y-1">
              <Label>Notes</Label>
              <textarea className={inputCls} rows={2} value={form.notes} onChange={e => set("notes", e.target.value)} placeholder="Any notes…" />
            </div>

            {/* Tags — multi-label, e.g. "Pre-cooked" + "Poultry" */}
            <div className="space-y-1.5">
              <Label>Tags</Label>
              <div className={`${inputCls} flex flex-wrap gap-1.5 min-h-[40px] cursor-text`} onClick={() => tagInputRef.current?.focus()}>
                {tags.map(tag => (
                  <span key={tag} className="inline-flex items-center gap-1 rounded-full bg-primary/10 text-primary text-xs px-2 py-0.5">
                    {tag}
                    <button type="button" onClick={e => { e.stopPropagation(); removeTag(tag); }} className="hover:text-destructive">
                      <X className="h-3 w-3" />
                    </button>
                  </span>
                ))}
                <div className="relative flex-1 min-w-[120px]">
                  <input
                    ref={tagInputRef}
                    className="w-full bg-transparent text-sm outline-none placeholder:text-muted-foreground"
                    placeholder={tags.length ? "" : "e.g. Pre-cooked, Poultry…"}
                    value={tagInput}
                    onChange={e => setTagInput(e.target.value)}
                    onKeyDown={handleTagKeyDown}
                    onBlur={() => setTimeout(() => setShowTagDropdown(false), 150)}
                  />
                  {showTagDropdown && (
                    <div className="absolute z-50 left-0 top-full mt-1 bg-popover border rounded-md shadow-md overflow-hidden min-w-[160px]">
                      {tagSuggestions.map(s => (
                        <button key={s} type="button" onMouseDown={() => addTag(s)}
                          className="w-full text-left px-3 py-2 text-sm hover:bg-accent">
                          {s}
                        </button>
                      ))}
                      {tagInput.trim() && !tagSuggestions.some(s => s.toLowerCase() === tagInput.trim().toLowerCase()) && (
                        <button type="button" onMouseDown={() => addTag(tagInput)}
                          className="w-full text-left px-3 py-2 text-sm hover:bg-accent flex items-center gap-2 text-primary border-t">
                          <Plus className="h-3.5 w-3.5" /> Add &ldquo;{tagInput.trim()}&rdquo;
                        </button>
                      )}
                    </div>
                  )}
                </div>
              </div>
              <p className="text-xs text-muted-foreground">Press Enter or comma to add. Tag things multiple ways, like &ldquo;Pre-cooked&rdquo; and &ldquo;Poultry&rdquo;.</p>
            </div>

            {error && <p className="text-sm text-destructive">{error}</p>}

            <DialogFooter>
              <Button type="button" variant="outline" onClick={() => setOpen(false)}>Cancel</Button>
              <Button type="submit" disabled={saving}>{saving ? "Saving…" : item ? "Save" : "Add item"}</Button>
            </DialogFooter>
          </form>
        </DialogContent>
      </Dialog>
    </>
  );
}
