"use client";

import { useState } from "react";
import { Controller } from "react-hook-form";
import { AlertCircle, Check, ChevronsUpDown, X } from "lucide-react";
import { Alert, AlertDescription } from "@/components/ui/alert";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "@/components/ui/command";
import { Field, FieldDescription, FieldError, FieldLabel } from "@/components/ui/field";
import { Input } from "@/components/ui/input";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { SearchableSelect } from "@/components/app/searchable-select";
import { OptionLabel } from "@/components/app/filters";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Switch } from "@/components/ui/switch";
import { Textarea } from "@/components/ui/textarea";
import { cn } from "@/lib/utils";

// Radix Select cannot use "" as an item value; this sentinel stands for "none selected".
const NONE = "__none__";

/**
 * React Hook Form + shadcn Field wrappers. Each takes `control` and `name` from useForm(),
 * shows the label, helper text, and the field error (client Zod or server 422).
 */
function FieldFrame({ id, label, description, error, className, children, orientation }) {
  return <Field data-invalid={Boolean(error)} orientation={orientation} className={className}>
    {label && <FieldLabel htmlFor={id}>{label}</FieldLabel>}
    {children}
    {error ? <FieldError>{error.message}</FieldError> : description && <FieldDescription>{description}</FieldDescription>}
  </Field>;
}

export function TextField({ control, name, label, description, type = "text", placeholder, className, inputProps }) {
  return <Controller control={control} name={name} render={({ field, fieldState }) => <FieldFrame id={name} label={label} description={description} error={fieldState.error} className={className}>
    <Input id={name} type={type} placeholder={placeholder} aria-invalid={fieldState.invalid} {...field} value={field.value ?? ""} {...inputProps} />
  </FieldFrame>} />;
}

export function TextareaField({ control, name, label, description, placeholder, rows = 3, className }) {
  return <Controller control={control} name={name} render={({ field, fieldState }) => <FieldFrame id={name} label={label} description={description} error={fieldState.error} className={className}>
    <Textarea id={name} rows={rows} placeholder={placeholder} aria-invalid={fieldState.invalid} {...field} value={field.value ?? ""} />
  </FieldFrame>} />;
}

// options: [{ value, label }]. `placeholder` shows when nothing is chosen; `allowEmpty` adds a "none" choice.
export function SelectField({ control, name, label, description, options, placeholder = "Select…", allowEmpty = false, emptyLabel = "None", className, disabled }) {
  return <Controller control={control} name={name} render={({ field, fieldState }) => <FieldFrame id={name} label={label} description={description} error={fieldState.error} className={className}>
    <Select value={field.value ? String(field.value) : allowEmpty ? NONE : ""} onValueChange={(value) => field.onChange(value === NONE ? "" : value)} disabled={disabled}>
      <SelectTrigger id={name} className="w-full" aria-invalid={fieldState.invalid} onBlur={field.onBlur}><SelectValue placeholder={placeholder}>{field.value ? options.find((option) => String(option.value) === String(field.value))?.label : undefined}</SelectValue></SelectTrigger>
      <SelectContent>
        {allowEmpty && <SelectItem value={NONE}>{emptyLabel}</SelectItem>}
        {options.map((option) => <SelectItem key={option.value} value={String(option.value)}><OptionLabel option={option} /></SelectItem>)}
      </SelectContent>
    </Select>
  </FieldFrame>} />;
}

export function SwitchField({ control, name, label, description, className }) {
  return <Controller control={control} name={name} render={({ field, fieldState }) => <Field orientation="horizontal" data-invalid={Boolean(fieldState.error)} className={cn("items-start", className)}>
    <Switch id={name} checked={Boolean(field.value)} onCheckedChange={field.onChange} />
    <div className="grid gap-1">
      <FieldLabel htmlFor={name}>{label}</FieldLabel>
      {fieldState.error ? <FieldError>{fieldState.error.message}</FieldError> : description && <FieldDescription>{description}</FieldDescription>}
    </div>
  </Field>} />;
}

// Form-level server error (set by applyServerErrors on form.formState.errors.root.server).
export function FormErrorAlert({ form }) {
  const message = form.formState.errors.root?.server?.message;
  if (!message) return null;
  return <Alert variant="destructive"><AlertCircle /><AlertDescription>{message}</AlertDescription></Alert>;
}

// Searchable single select for long option lists (buyers, factories, POs). options: [{ value, label, description? }]
// Pass `create` (useQuickAdd from app/lib/useQuickAdd.js) so a missing option can be added, or the list says who can add it.
export function ComboboxField({ control, name, label, description, options, placeholder = "Select…", searchPlaceholder = "Search…", emptyText = "No match.", allowEmpty = false, emptyLabel = "None", create, onCreate, createNoun, loading, className, disabled }) {
  return <Controller control={control} name={name} render={({ field, fieldState }) => <FieldFrame id={name} label={label} description={description} error={fieldState.error} className={className}>
    <SearchableSelect id={name} value={field.value} onChange={field.onChange} onBlur={field.onBlur} options={options} placeholder={placeholder} searchPlaceholder={searchPlaceholder}
      emptyText={emptyText} allowEmpty={allowEmpty} emptyLabel={emptyLabel} create={create} onCreate={onCreate} createNoun={createNoun} loading={loading} disabled={disabled} invalid={fieldState.invalid} />
  </FieldFrame>} />;
}

export function CheckboxField({ control, name, label, description, className }) {
  return <Controller control={control} name={name} render={({ field, fieldState }) => <Field orientation="horizontal" data-invalid={Boolean(fieldState.error)} className={cn("items-start", className)}>
    <Checkbox id={name} checked={Boolean(field.value)} onCheckedChange={(checked) => field.onChange(checked === true)} />
    <div className="grid gap-1">
      <FieldLabel htmlFor={name} className="font-normal">{label}</FieldLabel>
      {fieldState.error ? <FieldError>{fieldState.error.message}</FieldError> : description && <FieldDescription>{description}</FieldDescription>}
    </div>
  </Field>} />;
}

// Free-text chips (colorways, sizes, tags). Value is an array of strings; Enter or comma adds, Backspace on empty removes the last.
export function TagsField({ control, name, label, description, placeholder = "Type and press Enter", className }) {
  const [draft, setDraft] = useState("");

  return <Controller control={control} name={name} render={({ field, fieldState }) => {
    const values = Array.isArray(field.value) ? field.value : [];
    const add = () => {
      const parts = draft.split(",").map((item) => item.trim()).filter(Boolean);
      if (parts.length) field.onChange([...new Set([...values, ...parts])]);
      setDraft("");
    };
    return <FieldFrame id={name} label={label} description={description || "Press Enter or comma after each value."} error={fieldState.error} className={className}>
      <div className={cn("flex min-h-9 w-full flex-wrap items-center gap-1.5 rounded-md border border-input bg-transparent px-2 py-1.5 shadow-xs transition-[color,box-shadow] focus-within:border-ring focus-within:ring-[3px] focus-within:ring-ring/50 dark:bg-input/30", fieldState.invalid && "border-destructive")}>
        {values.map((value) => <Badge key={value} variant="secondary" className="gap-1 pr-1">{value}
          <button type="button" className="rounded-sm p-0.5 hover:bg-foreground/10" aria-label={`Remove ${value}`} onClick={() => field.onChange(values.filter((item) => item !== value))}><X className="size-3" /></button>
        </Badge>)}
        <input id={name} className="min-w-24 flex-1 bg-transparent text-sm outline-none placeholder:text-muted-foreground" value={draft} placeholder={values.length ? "" : placeholder}
          onChange={(event) => setDraft(event.target.value)} onBlur={() => { add(); field.onBlur(); }}
          onKeyDown={(event) => {
            if (event.key === "Enter" || event.key === ",") { event.preventDefault(); add(); }
            if (event.key === "Backspace" && !draft && values.length) field.onChange(values.slice(0, -1));
          }} />
      </div>
    </FieldFrame>;
  }} />;
}
