'use client';
import { formatErrorBanner } from '@/lib/api/toast-error';

import { useState } from 'react';
import { Plus, X } from 'lucide-react';

import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { FieldLabel } from '@/components/ui/field-label';
import { Switch } from '@/components/ui/switch';
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogFooter,
} from '@/components/ui/dialog';
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@/components/ui/select';
import { apiFetch } from '@/lib/api/client';

// ─── Types ────────────────────────────────────────────────────────────────────

export interface CustomFieldDefinition {
  id: string;
  entityType: string;
  fieldName: string;
  fieldLabel: string;
  fieldType: string;
  selectOptions: string[] | null;
  isRequired: boolean;
  sortOrder: number;
}

interface CustomFieldFormProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  field?: CustomFieldDefinition | null;
  onSuccess: () => void;
}

const ENTITY_TYPE_LABELS: Record<string, string> = {
  client: 'Clients',
  interest: 'Interests',
  berth: 'Berths',
};

const FIELD_TYPE_LABELS: Record<string, string> = {
  text: 'Text',
  number: 'Number',
  date: 'Date',
  boolean: 'Yes / No',
  select: 'Dropdown (Select)',
};

// ─── Component ────────────────────────────────────────────────────────────────

export function CustomFieldForm(props: CustomFieldFormProps) {
  // Key-based remount: the body is keyed on open + field.id so its
  // useState initializers re-seed each time the dialog opens.
  return (
    <CustomFieldFormBody
      key={props.open ? `open:${props.field?.id ?? 'new'}` : 'closed'}
      {...props}
    />
  );
}

function CustomFieldFormBody({ open, onOpenChange, field, onSuccess }: CustomFieldFormProps) {
  const isEdit = !!field;

  // Form state
  const [entityType, setEntityType] = useState(field?.entityType ?? 'client');
  const [fieldName, setFieldName] = useState(field?.fieldName ?? '');
  const [fieldLabel, setFieldLabel] = useState(field?.fieldLabel ?? '');
  const [fieldType, setFieldType] = useState(field?.fieldType ?? 'text');
  const [selectOptions, setSelectOptions] = useState<string[]>(field?.selectOptions ?? []);
  const [newOption, setNewOption] = useState('');
  const [isRequired, setIsRequired] = useState(field?.isRequired ?? false);
  const [sortOrder, setSortOrder] = useState(field?.sortOrder ?? 0);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);

  // Reset is handled by the parent key-based remount above.

  // ── Select options management ──────────────────────────────────────────────

  function addOption() {
    const trimmed = newOption.trim();
    if (!trimmed || selectOptions.includes(trimmed)) return;
    setSelectOptions((prev) => [...prev, trimmed]);
    setNewOption('');
  }

  function removeOption(opt: string) {
    setSelectOptions((prev) => prev.filter((o) => o !== opt));
  }

  function handleOptionKeyDown(e: React.KeyboardEvent) {
    if (e.key === 'Enter') {
      e.preventDefault();
      addOption();
    }
  }

  // ── Submit ─────────────────────────────────────────────────────────────────

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    setError(null);

    if (fieldType === 'select' && selectOptions.length === 0) {
      setError('Select fields must have at least one option.');
      return;
    }

    setLoading(true);
    try {
      if (isEdit) {
        await apiFetch(`/api/v1/admin/custom-fields/${field.id}`, {
          method: 'PATCH',
          body: {
            fieldLabel,
            selectOptions: fieldType === 'select' ? selectOptions : undefined,
            isRequired,
            sortOrder,
          },
        });
      } else {
        await apiFetch('/api/v1/admin/custom-fields', {
          method: 'POST',
          body: {
            entityType,
            fieldName,
            fieldLabel,
            fieldType,
            selectOptions: fieldType === 'select' ? selectOptions : undefined,
            isRequired,
            sortOrder,
          },
        });
      }
      onSuccess();
      onOpenChange(false);
    } catch (err: unknown) {
      const message = formatErrorBanner(err);
      setError(message);
    } finally {
      setLoading(false);
    }
  }

  // ── Render ─────────────────────────────────────────────────────────────────

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="max-w-lg">
        <DialogHeader>
          <DialogTitle>{isEdit ? 'Edit Custom Field' : 'New Custom Field'}</DialogTitle>
        </DialogHeader>

        <form onSubmit={handleSubmit} className="space-y-5 py-2">
          {/* Entity Type - create only */}
          <div className="space-y-1.5">
            <Label htmlFor="cf-entity-type">Entity Type</Label>
            {isEdit ? (
              <p className="text-sm text-muted-foreground">
                {ENTITY_TYPE_LABELS[entityType] ?? entityType}
              </p>
            ) : (
              <Select value={entityType} onValueChange={setEntityType}>
                <SelectTrigger id="cf-entity-type">
                  <SelectValue />
                </SelectTrigger>
                <SelectContent>
                  {Object.entries(ENTITY_TYPE_LABELS).map(([val, label]) => (
                    <SelectItem key={val} value={val}>
                      {label}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            )}
          </div>

          {/* Field Name - create only */}
          <div className="space-y-1.5">
            <Label htmlFor="cf-field-name">
              Field Name
              <span className="ml-1 text-xs text-muted-foreground">(snake_case)</span>
            </Label>
            {isEdit ? (
              <p className="font-mono text-sm text-muted-foreground">{fieldName}</p>
            ) : (
              <Input
                id="cf-field-name"
                value={fieldName}
                onChange={(e) => setFieldName(e.target.value)}
                placeholder="e.g. vessel_type"
                pattern="^[a-z_][a-z0-9_]*$"
                maxLength={50}
                required
              />
            )}
          </div>

          {/* Field Label */}
          <div className="space-y-1.5">
            <Label htmlFor="cf-field-label">Display Label</Label>
            <Input
              id="cf-field-label"
              value={fieldLabel}
              onChange={(e) => setFieldLabel(e.target.value)}
              placeholder="e.g. Vessel Type"
              maxLength={100}
              required
            />
          </div>

          {/* Field Type - create only */}
          <div className="space-y-1.5">
            <Label htmlFor="cf-field-type">Field Type</Label>
            {isEdit ? (
              <div>
                <p className="text-sm text-muted-foreground">
                  {FIELD_TYPE_LABELS[fieldType] ?? fieldType}
                </p>
                <p className="mt-0.5 text-xs text-muted-foreground">
                  Type cannot be changed after creation.
                </p>
              </div>
            ) : (
              <Select value={fieldType} onValueChange={setFieldType}>
                <SelectTrigger id="cf-field-type">
                  <SelectValue />
                </SelectTrigger>
                <SelectContent>
                  {Object.entries(FIELD_TYPE_LABELS).map(([val, label]) => (
                    <SelectItem key={val} value={val}>
                      {label}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            )}
          </div>

          {/* Select Options - visible when fieldType = 'select' */}
          {fieldType === 'select' && (
            <div className="space-y-2">
              <Label>Options</Label>
              <div className="flex gap-2">
                <Input
                  value={newOption}
                  onChange={(e) => setNewOption(e.target.value)}
                  onKeyDown={handleOptionKeyDown}
                  placeholder="Add option..."
                  maxLength={100}
                />
                <Button type="button" variant="outline" size="sm" onClick={addOption}>
                  <Plus className="h-4 w-4" aria-hidden />
                </Button>
              </div>
              {selectOptions.length > 0 && (
                <div className="flex flex-wrap gap-1.5 pt-1">
                  {selectOptions.map((opt) => (
                    <span
                      key={opt}
                      className="flex items-center gap-1 rounded-md border bg-muted px-2 py-0.5 text-sm"
                    >
                      {opt}
                      <button
                        type="button"
                        onClick={() => removeOption(opt)}
                        className="ml-0.5 text-muted-foreground hover:text-destructive"
                        aria-label={`Remove option ${opt}`}
                      >
                        <X className="h-3 w-3" />
                      </button>
                    </span>
                  ))}
                </div>
              )}
            </div>
          )}

          {/* Is Required */}
          <div className="flex items-center justify-between">
            <Label htmlFor="cf-is-required">Required field</Label>
            <Switch id="cf-is-required" checked={isRequired} onCheckedChange={setIsRequired} />
          </div>

          {/* Sort Order */}
          <div className="space-y-1.5">
            <FieldLabel
              htmlFor="cf-sort-order"
              tooltip="Lower numbers render first when the field set is shown on entity detail pages. Use to pin frequently-edited fields to the top."
            >
              Sort Order
            </FieldLabel>
            <Input
              id="cf-sort-order"
              type="number"
              value={sortOrder}
              onChange={(e) => setSortOrder(parseInt(e.target.value, 10) || 0)}
              min={0}
            />
          </div>

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

          <DialogFooter>
            <Button
              type="button"
              variant="outline"
              onClick={() => onOpenChange(false)}
              disabled={loading}
            >
              Cancel
            </Button>
            <Button type="submit" disabled={loading}>
              {loading ? 'Saving…' : isEdit ? 'Save changes' : 'Create Field'}
            </Button>
          </DialogFooter>
        </form>
      </DialogContent>
    </Dialog>
  );
}
