'use client';

import * as React from 'react';
import { Dialog } from './Dialog';
import { Button } from './Button';
import { Input } from './Input';
import { Select } from './Select';

export type FormFieldType = 'text' | 'secret' | 'select' | 'number' | 'textarea';

export interface FormFieldDef {
  key: string;
  label: string;
  type: FormFieldType;
  required?: boolean;
  help?: string;
  placeholder?: string;
  default?: string | number;
  options?: { value: string; label: string }[];
  section?: string;
}

export function FormDialog({
  open,
  onClose,
  title,
  description,
  fields,
  initial,
  onSubmit,
  submitLabel = 'Save',
  busy,
  error,
}: {
  open: boolean;
  onClose: () => void;
  title: string;
  description?: string;
  fields: FormFieldDef[];
  initial?: Record<string, string | number>;
  onSubmit: (values: Record<string, string>) => void | Promise<void>;
  submitLabel?: string;
  busy?: boolean;
  error?: string;
}) {
  const [values, setValues] = React.useState<Record<string, string>>({});
  const [fieldErrors, setFieldErrors] = React.useState<Record<string, string>>({});
  const wasOpen = React.useRef(false);
  const fieldsRef = React.useRef(fields);
  const initialRef = React.useRef(initial);
  fieldsRef.current = fields;
  initialRef.current = initial;

  // Seed values only when the dialog opens — not on every parent re-render,
  // otherwise typing a display name gets wiped by new fields/initial object refs.
  // Parent should remount via `key={providerId}` when switching records.
  React.useEffect(() => {
    if (open && !wasOpen.current) {
      const next: Record<string, string> = {};
      for (const f of fieldsRef.current) {
        const v = initialRef.current?.[f.key] ?? f.default ?? '';
        next[f.key] = String(v);
      }
      setValues(next);
      setFieldErrors({});
    }
    wasOpen.current = open;
  }, [open]);

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    const errs: Record<string, string> = {};
    for (const f of fields) {
      if (f.required && !String(values[f.key] ?? '').trim()) {
        errs[f.key] = 'Required';
      }
    }
    setFieldErrors(errs);
    if (Object.keys(errs).length) return;
    await onSubmit(values);
  };

  let lastSection = '';

  return (
    <Dialog open={open} onClose={onClose} title={title} wide>
      <form onSubmit={handleSubmit}>
        {description ? <p className="text-muted text-sm m-0 mb-4 leading-relaxed">{description}</p> : null}
        {fields.map((f) => {
          const sectionHeader =
            f.section && f.section !== lastSection
              ? ((lastSection = f.section), (
                  <div key={`sec-${f.section}`} className="text-sm font-semibold mt-4 mb-2 first:mt-0">
                    {f.section}
                  </div>
                ))
              : null;

          return (
            <React.Fragment key={f.key}>
              {sectionHeader}
              <label className="block mb-3.5 font-medium text-sm">
                {f.label}
                {f.type === 'select' ? (
                  <Select
                    className="mt-1.5"
                    value={values[f.key] ?? ''}
                    onChange={(e) => setValues((v) => ({ ...v, [f.key]: e.target.value }))}
                  >
                    {(f.options || []).map((o) => (
                      <option key={o.value} value={o.value}>
                        {o.label}
                      </option>
                    ))}
                  </Select>
                ) : f.type === 'textarea' ? (
                  <textarea
                    className="mt-1.5 w-full rounded-[var(--r)] border border-line bg-surface text-text px-[11px] py-2 focus:border-accent focus:outline-none focus:shadow-[0_0_0_3px_var(--accent-soft)]"
                    rows={3}
                    value={values[f.key] ?? ''}
                    placeholder={f.placeholder}
                    onChange={(e) => setValues((v) => ({ ...v, [f.key]: e.target.value }))}
                  />
                ) : (
                  <Input
                    className="mt-1.5"
                    type={f.type === 'secret' ? 'password' : f.type === 'number' ? 'number' : 'text'}
                    value={values[f.key] ?? ''}
                    placeholder={f.placeholder}
                    autoComplete="off"
                    onChange={(e) => setValues((v) => ({ ...v, [f.key]: e.target.value }))}
                  />
                )}
                {f.help ? <small className="block text-muted font-normal mt-1">{f.help}</small> : null}
                {fieldErrors[f.key] ? (
                  <small className="block text-danger mt-1">{fieldErrors[f.key]}</small>
                ) : null}
              </label>
            </React.Fragment>
          );
        })}
        {error ? <p className="text-danger text-sm min-h-5 mb-2">{error}</p> : null}
        <div className="flex justify-end gap-2 mt-4">
          <Button type="button" variant="ghost" onClick={onClose} disabled={busy}>
            Cancel
          </Button>
          <Button type="submit" variant="primary" disabled={busy}>
            {submitLabel}
          </Button>
        </div>
      </form>
    </Dialog>
  );
}
