"use client";

import { useState, useTransition } from "react";
import {
  newId,
  FIELD_TYPE_LABELS,
  FILE_ACCEPT_LABELS,
  type FormField,
  type FieldType,
  type FileAcceptCategory,
  type DocumentRequest,
} from "@/lib/forms/types";
import Icon from "@/components/Icon";
import { useDialog } from "@/components/feedback/DialogProvider";
import { saveFormTemplate, uploadSampleDocument } from "./actions";

type Props = {
  serviceSlug: string;
  initialTitle: string;
  initialDescription: string;
  initialFields: FormField[];
  initialDocuments: DocumentRequest[];
  initialPublished: boolean;
};

const FIELD_TYPES: FieldType[] = [
  "text",
  "email",
  "phone",
  "number",
  "date",
  "textarea",
  "select",
  "radio",
  "checkbox",
  "file",
];

const FILE_CATEGORIES: FileAcceptCategory[] = [
  "image",
  "pdf",
  "word",
  "excel",
  "any",
];

export default function FormBuilderEditor({
  serviceSlug,
  initialTitle,
  initialDescription,
  initialFields,
  initialDocuments,
  initialPublished,
}: Props) {
  const [title, setTitle] = useState(initialTitle);
  const [description, setDescription] = useState(initialDescription);
  const [fields, setFields] = useState<FormField[]>(initialFields);
  const [documents, setDocuments] =
    useState<DocumentRequest[]>(initialDocuments);
  const [published, setPublished] = useState(initialPublished);
  const [isDirty, setIsDirty] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [savedAt, setSavedAt] = useState<Date | null>(null);
  const [isPending, startTransition] = useTransition();
  const { confirm } = useDialog();

  function markDirty() {
    setIsDirty(true);
    setSavedAt(null);
  }

  /* ─── Field operations ───────────────────────────────────────────── */

  function addField(type: FieldType = "text") {
    const newField: FormField = {
      id: newId("f"),
      type,
      label: "Nouveau champ",
      required: false,
    };
    if (type === "select" || type === "radio") {
      newField.options = [
        { value: "option1", label: "Option 1" },
        { value: "option2", label: "Option 2" },
      ];
    }
    if (type === "file") {
      newField.acceptCategories = ["pdf", "image", "word"];
      newField.maxSizeMb = 25;
      newField.multiple = false;
    }
    setFields((prev) => [...prev, newField]);
    markDirty();
  }

  function updateField(id: string, patch: Partial<FormField>) {
    setFields((prev) =>
      prev.map((f) => (f.id === id ? { ...f, ...patch } : f))
    );
    markDirty();
  }

  async function removeField(id: string) {
    const ok = await confirm({
      title: "Supprimer ce champ ?",
      body: "Le champ sera retiré du formulaire. Pensez à enregistrer pour publier la modification.",
      confirmLabel: "Supprimer",
      danger: true,
    });
    if (!ok) return;
    setFields((prev) => prev.filter((f) => f.id !== id));
    markDirty();
  }

  function moveField(id: string, direction: -1 | 1) {
    setFields((prev) => {
      const idx = prev.findIndex((f) => f.id === id);
      if (idx === -1) return prev;
      const newIdx = idx + direction;
      if (newIdx < 0 || newIdx >= prev.length) return prev;
      const next = [...prev];
      [next[idx], next[newIdx]] = [next[newIdx], next[idx]];
      return next;
    });
    markDirty();
  }

  /* ─── Document operations ────────────────────────────────────────── */

  function addDocument() {
    setDocuments((prev) => [
      ...prev,
      {
        id: newId("d"),
        label: "Nouveau document",
        required: false,
        acceptCategories: ["pdf", "image"],
        maxSizeMb: 25,
        multiple: false,
      },
    ]);
    markDirty();
  }

  function updateDocument(id: string, patch: Partial<DocumentRequest>) {
    setDocuments((prev) =>
      prev.map((d) => (d.id === id ? { ...d, ...patch } : d))
    );
    markDirty();
  }

  async function removeDocument(id: string) {
    const ok = await confirm({
      title: "Supprimer ce document demandé ?",
      body: "Le document ne sera plus demandé au client lors de la soumission. Pensez à enregistrer.",
      confirmLabel: "Supprimer",
      danger: true,
    });
    if (!ok) return;
    setDocuments((prev) => prev.filter((d) => d.id !== id));
    markDirty();
  }

  function moveDocument(id: string, direction: -1 | 1) {
    setDocuments((prev) => {
      const idx = prev.findIndex((d) => d.id === id);
      if (idx === -1) return prev;
      const newIdx = idx + direction;
      if (newIdx < 0 || newIdx >= prev.length) return prev;
      const next = [...prev];
      [next[idx], next[newIdx]] = [next[newIdx], next[idx]];
      return next;
    });
    markDirty();
  }

  /* ─── Save ───────────────────────────────────────────────────────── */

  function handleSave() {
    setError(null);
    startTransition(async () => {
      try {
        await saveFormTemplate({
          serviceSlug,
          title,
          description: description || null,
          fields,
          documentRequests: documents,
          published,
        });
        setIsDirty(false);
        setSavedAt(new Date());
      } catch (err) {
        setError(err instanceof Error ? err.message : "Erreur de sauvegarde");
      }
    });
  }

  return (
    <div className="space-y-10">
      {/* Save bar — sticky en haut quand dirty */}
      <div
        className={`sticky top-0 z-30 -mx-6 lg:-mx-12 px-6 lg:px-12 py-4 border-b transition-colors ${
          isDirty
            ? "bg-secondary-container border-secondary"
            : "bg-white border-outline-variant"
        }`}
      >
        <div className="flex items-center justify-between gap-4 flex-wrap">
          <div className="flex items-center gap-3 text-sm">
            {isDirty ? (
              <>
                <Icon
                  name="edit_note"
                  className="text-on-secondary-container"
                />
                <span className="text-on-secondary-container font-serif">
                  Modifications non sauvegardées
                </span>
              </>
            ) : savedAt ? (
              <>
                <Icon name="check_circle" className="text-secondary" />
                <span className="text-on-surface-variant">
                  Sauvegardé à{" "}
                  {savedAt.toLocaleTimeString("fr-FR", {
                    hour: "2-digit",
                    minute: "2-digit",
                  })}
                </span>
              </>
            ) : (
              <span className="text-on-surface-variant">Aucune modification</span>
            )}
          </div>
          <div className="flex items-center gap-3">
            <label className="flex items-center gap-2 text-xs uppercase tracking-widest font-serif text-on-surface-variant cursor-pointer">
              <input
                type="checkbox"
                checked={published}
                onChange={(e) => {
                  setPublished(e.target.checked);
                  markDirty();
                }}
                className="w-4 h-4 accent-primary"
              />
              Publié
            </label>
            <button
              type="button"
              onClick={handleSave}
              disabled={!isDirty || isPending}
              className="btn btn-primary !py-3 !px-6 text-xs disabled:opacity-50 disabled:cursor-not-allowed"
            >
              {isPending ? "Sauvegarde…" : "Enregistrer"}
            </button>
          </div>
        </div>
        {error && (
          <p className="text-error text-sm mt-2">{error}</p>
        )}
      </div>

      {/* Métadonnées */}
      <Section title="Métadonnées" subtitle="Affichées en haut du formulaire public.">
        <div className="space-y-5">
          <Field label="Titre du formulaire">
            <TextInput
              value={title}
              onChange={(v) => {
                setTitle(v);
                markDirty();
              }}
            />
          </Field>
          <Field label="Description / consignes" optional>
            <TextArea
              value={description}
              onChange={(v) => {
                setDescription(v);
                markDirty();
              }}
              rows={3}
            />
          </Field>
        </div>
      </Section>

      {/* Champs */}
      <Section
        title="Questions"
        subtitle={`${fields.length} champ${fields.length > 1 ? "s" : ""} dans le formulaire.`}
        action={
          <select
            onChange={(e) => {
              if (e.target.value) {
                addField(e.target.value as FieldType);
                e.target.value = "";
              }
            }}
            defaultValue=""
            className="text-xs uppercase tracking-widest font-serif border border-outline-variant px-3 py-2 bg-white"
          >
            <option value="" disabled>
              + Ajouter un champ
            </option>
            {FIELD_TYPES.map((t) => (
              <option key={t} value={t}>
                {FIELD_TYPE_LABELS[t]}
              </option>
            ))}
          </select>
        }
      >
        {fields.length === 0 ? (
          <Empty label="Aucun champ. Ajoutez-en un avec le bouton ci-dessus." />
        ) : (
          <ul className="space-y-3">
            {fields.map((f, idx) => (
              <FieldCard
                key={f.id}
                field={f}
                isFirst={idx === 0}
                isLast={idx === fields.length - 1}
                onUpdate={(patch) => updateField(f.id, patch)}
                onRemove={() => removeField(f.id)}
                onMoveUp={() => moveField(f.id, -1)}
                onMoveDown={() => moveField(f.id, 1)}
              />
            ))}
          </ul>
        )}
      </Section>

      {/* Documents */}
      <Section
        title="Documents demandés"
        subtitle="Listés en bas du formulaire. Le client les uploadera directement au moment de la soumission."
        action={
          <button
            type="button"
            onClick={addDocument}
            className="text-xs uppercase tracking-widest font-serif border border-outline-variant px-3 py-2 hover:border-primary transition-colors"
          >
            + Ajouter un document
          </button>
        }
      >
        {documents.length === 0 ? (
          <Empty label="Aucun document demandé." />
        ) : (
          <ul className="space-y-3">
            {documents.map((d, idx) => (
              <DocumentCard
                key={d.id}
                doc={d}
                serviceSlug={serviceSlug}
                isFirst={idx === 0}
                isLast={idx === documents.length - 1}
                onUpdate={(patch) => updateDocument(d.id, patch)}
                onRemove={() => removeDocument(d.id)}
                onMoveUp={() => moveDocument(d.id, -1)}
                onMoveDown={() => moveDocument(d.id, 1)}
              />
            ))}
          </ul>
        )}
      </Section>
    </div>
  );
}

/* ─── Sub-components ─────────────────────────────────────────────────── */

function Section({
  title,
  subtitle,
  action,
  children,
}: {
  title: string;
  subtitle?: string;
  action?: React.ReactNode;
  children: React.ReactNode;
}) {
  return (
    <section className="space-y-6">
      <header className="flex items-end justify-between gap-4 flex-wrap">
        <div>
          <h2 className="font-serif text-2xl text-primary">{title}</h2>
          {subtitle && (
            <p className="text-sm text-on-surface-variant mt-1">{subtitle}</p>
          )}
        </div>
        {action}
      </header>
      {children}
    </section>
  );
}

function Field({
  label,
  optional,
  children,
}: {
  label: string;
  optional?: boolean;
  children: React.ReactNode;
}) {
  return (
    <div>
      <label className="eyebrow !text-on-surface-variant block mb-2">
        {label}
        {optional && (
          <span className="ml-2 text-on-surface-variant/60 normal-case">
            (optionnel)
          </span>
        )}
      </label>
      {children}
    </div>
  );
}

function TextInput({
  value,
  onChange,
  placeholder,
}: {
  value: string;
  onChange: (v: string) => void;
  placeholder?: string;
}) {
  return (
    <input
      type="text"
      value={value}
      onChange={(e) => onChange(e.target.value)}
      placeholder={placeholder}
      className="w-full bg-white border border-outline-variant px-3 py-2 body-md focus:border-primary outline-none transition-colors"
    />
  );
}

function TextArea({
  value,
  onChange,
  rows = 3,
}: {
  value: string;
  onChange: (v: string) => void;
  rows?: number;
}) {
  return (
    <textarea
      value={value}
      onChange={(e) => onChange(e.target.value)}
      rows={rows}
      className="w-full bg-white border border-outline-variant px-3 py-2 body-md focus:border-primary outline-none transition-colors resize-y"
    />
  );
}

function Empty({ label }: { label: string }) {
  return (
    <div className="bg-white border border-outline-variant border-dashed p-12 text-center">
      <p className="text-sm text-on-surface-variant italic">{label}</p>
    </div>
  );
}

function ReorderButtons({
  isFirst,
  isLast,
  onMoveUp,
  onMoveDown,
}: {
  isFirst: boolean;
  isLast: boolean;
  onMoveUp: () => void;
  onMoveDown: () => void;
}) {
  return (
    <div className="flex flex-col -gap-px">
      <button
        type="button"
        onClick={onMoveUp}
        disabled={isFirst}
        aria-label="Monter"
        className="text-on-surface-variant hover:text-primary disabled:opacity-30 disabled:cursor-not-allowed"
      >
        <Icon name="keyboard_arrow_up" />
      </button>
      <button
        type="button"
        onClick={onMoveDown}
        disabled={isLast}
        aria-label="Descendre"
        className="text-on-surface-variant hover:text-primary disabled:opacity-30 disabled:cursor-not-allowed"
      >
        <Icon name="keyboard_arrow_down" />
      </button>
    </div>
  );
}

function FieldCard({
  field,
  isFirst,
  isLast,
  onUpdate,
  onRemove,
  onMoveUp,
  onMoveDown,
}: {
  field: FormField;
  isFirst: boolean;
  isLast: boolean;
  onUpdate: (patch: Partial<FormField>) => void;
  onRemove: () => void;
  onMoveUp: () => void;
  onMoveDown: () => void;
}) {
  const [expanded, setExpanded] = useState(false);
  const hasOptions = field.type === "select" || field.type === "radio";

  return (
    <li className="bg-white border border-outline-variant">
      <div className="flex items-center gap-4 p-4">
        <ReorderButtons
          isFirst={isFirst}
          isLast={isLast}
          onMoveUp={onMoveUp}
          onMoveDown={onMoveDown}
        />
        <div className="flex-1 min-w-0">
          <p className="font-serif text-base text-primary truncate">
            {field.label || (
              <em className="text-on-surface-variant">Sans titre</em>
            )}
            {field.required && (
              <span className="ml-2 text-secondary text-xs">*</span>
            )}
          </p>
          <p className="text-xs text-on-surface-variant font-mono">
            {field.id} · {FIELD_TYPE_LABELS[field.type]}
          </p>
        </div>
        <button
          type="button"
          onClick={() => setExpanded((v) => !v)}
          className="text-xs uppercase tracking-widest font-serif text-on-surface-variant hover:text-primary transition-colors"
        >
          {expanded ? "Replier" : "Modifier"}
        </button>
        <button
          type="button"
          onClick={onRemove}
          aria-label="Supprimer ce champ"
          className="text-on-surface-variant hover:text-error transition-colors"
        >
          <Icon name="delete" />
        </button>
      </div>

      {expanded && (
        <div className="border-t border-outline-variant/40 p-4 space-y-4 bg-surface-container-low">
          <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
            <Field label="Label affiché">
              <TextInput
                value={field.label}
                onChange={(v) => onUpdate({ label: v })}
              />
            </Field>
            <Field label="Type">
              <select
                value={field.type}
                onChange={(e) =>
                  onUpdate({ type: e.target.value as FieldType })
                }
                className="w-full bg-white border border-outline-variant px-3 py-2 body-md"
              >
                {FIELD_TYPES.map((t) => (
                  <option key={t} value={t}>
                    {FIELD_TYPE_LABELS[t]}
                  </option>
                ))}
              </select>
            </Field>
          </div>

          <Field label="Description / aide" optional>
            <TextInput
              value={field.description ?? ""}
              onChange={(v) => onUpdate({ description: v || undefined })}
            />
          </Field>

          {(field.type === "text" ||
            field.type === "email" ||
            field.type === "phone" ||
            field.type === "textarea" ||
            field.type === "number" ||
            field.type === "date") && (
            <Field label="Placeholder" optional>
              <TextInput
                value={field.placeholder ?? ""}
                onChange={(v) => onUpdate({ placeholder: v || undefined })}
              />
            </Field>
          )}

          {hasOptions && (
            <Field label="Options (valeur / label)">
              <OptionsEditor
                options={field.options ?? []}
                onChange={(options) => onUpdate({ options })}
              />
            </Field>
          )}

          {field.type === "file" && (
            <FileFieldOptions field={field} onUpdate={onUpdate} />
          )}

          <div className="flex items-center gap-6">
            <label className="flex items-center gap-2 text-sm cursor-pointer">
              <input
                type="checkbox"
                checked={field.required ?? false}
                onChange={(e) => onUpdate({ required: e.target.checked })}
                className="w-4 h-4 accent-primary"
              />
              {field.type === "file" ? "Au moins un fichier requis" : "Champ requis"}
            </label>
          </div>

          <div className="border-t border-outline-variant/40 pt-3 text-xs text-on-surface-variant font-mono">
            ID technique : <code>{field.id}</code>
          </div>
        </div>
      )}
    </li>
  );
}

function OptionsEditor({
  options,
  onChange,
}: {
  options: { value: string; label: string }[];
  onChange: (options: { value: string; label: string }[]) => void;
}) {
  function update(idx: number, patch: Partial<{ value: string; label: string }>) {
    onChange(options.map((o, i) => (i === idx ? { ...o, ...patch } : o)));
  }
  function remove(idx: number) {
    onChange(options.filter((_, i) => i !== idx));
  }
  function add() {
    onChange([
      ...options,
      { value: `option${options.length + 1}`, label: `Option ${options.length + 1}` },
    ]);
  }

  return (
    <div className="space-y-2">
      {options.map((o, idx) => (
        <div key={idx} className="flex gap-2 items-center">
          <input
            type="text"
            value={o.value}
            onChange={(e) => update(idx, { value: e.target.value })}
            placeholder="value"
            className="flex-1 bg-white border border-outline-variant px-2 py-1.5 text-sm font-mono"
          />
          <input
            type="text"
            value={o.label}
            onChange={(e) => update(idx, { label: e.target.value })}
            placeholder="Label"
            className="flex-1 bg-white border border-outline-variant px-2 py-1.5 text-sm"
          />
          <button
            type="button"
            onClick={() => remove(idx)}
            aria-label="Supprimer"
            className="text-on-surface-variant hover:text-error"
          >
            <Icon name="close" className="!text-base" />
          </button>
        </div>
      ))}
      <button
        type="button"
        onClick={add}
        className="text-xs uppercase tracking-widest font-serif text-on-surface-variant hover:text-primary transition-colors"
      >
        + Ajouter une option
      </button>
    </div>
  );
}

function FileFieldOptions({
  field,
  onUpdate,
}: {
  field: FormField;
  onUpdate: (patch: Partial<FormField>) => void;
}) {
  const cats = field.acceptCategories ?? [];

  function toggleCategory(cat: FileAcceptCategory, checked: boolean) {
    let next = [...cats];
    if (cat === "any" && checked) {
      next = ["any"];
    } else if (checked) {
      next = next.filter((c) => c !== "any");
      next.push(cat);
    } else {
      next = next.filter((c) => c !== cat);
    }
    onUpdate({ acceptCategories: next });
  }

  return (
    <>
      <Field label="Types de fichiers acceptés">
        <div className="flex flex-wrap gap-3">
          {FILE_CATEGORIES.map((c) => (
            <label
              key={c}
              className="flex items-center gap-2 text-sm cursor-pointer border border-outline-variant px-3 py-1.5 hover:border-primary transition-colors"
            >
              <input
                type="checkbox"
                checked={cats.includes(c)}
                onChange={(e) => toggleCategory(c, e.target.checked)}
                className="w-4 h-4 accent-primary"
              />
              {FILE_ACCEPT_LABELS[c]}
            </label>
          ))}
        </div>
        <p className="text-xs text-on-surface-variant mt-1">
          Cocher "Tout fichier" lève toute restriction.
        </p>
      </Field>
      <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
        <Field label="Taille max par fichier (Mo)">
          <TextInput
            value={String(field.maxSizeMb ?? 25)}
            onChange={(v) => {
              const n = Number(v);
              if (Number.isFinite(n) && n > 0) onUpdate({ maxSizeMb: n });
            }}
          />
        </Field>
        <Field label="Plusieurs fichiers ?">
          <label className="flex items-center gap-2 text-sm cursor-pointer">
            <input
              type="checkbox"
              checked={field.multiple ?? false}
              onChange={(e) => onUpdate({ multiple: e.target.checked })}
              className="w-4 h-4 accent-primary"
            />
            Autoriser l'upload de plusieurs fichiers
          </label>
        </Field>
      </div>
    </>
  );
}

function DocumentCard({
  doc,
  serviceSlug,
  isFirst,
  isLast,
  onUpdate,
  onRemove,
  onMoveUp,
  onMoveDown,
}: {
  doc: DocumentRequest;
  serviceSlug: string;
  isFirst: boolean;
  isLast: boolean;
  onUpdate: (patch: Partial<DocumentRequest>) => void;
  onRemove: () => void;
  onMoveUp: () => void;
  onMoveDown: () => void;
}) {
  const [expanded, setExpanded] = useState(false);
  return (
    <li className="bg-white border border-outline-variant">
      <div className="flex items-center gap-4 p-4">
        <ReorderButtons
          isFirst={isFirst}
          isLast={isLast}
          onMoveUp={onMoveUp}
          onMoveDown={onMoveDown}
        />
        <Icon
          name="upload_file"
          className="!text-xl text-on-surface-variant"
        />
        <div className="flex-1 min-w-0">
          <p className="font-serif text-base text-primary truncate">
            {doc.label}
            {doc.required && (
              <span className="ml-2 text-secondary text-xs">*</span>
            )}
          </p>
          {doc.description && (
            <p className="text-xs text-on-surface-variant truncate">
              {doc.description}
            </p>
          )}
        </div>
        <button
          type="button"
          onClick={() => setExpanded((v) => !v)}
          className="text-xs uppercase tracking-widest font-serif text-on-surface-variant hover:text-primary transition-colors"
        >
          {expanded ? "Replier" : "Modifier"}
        </button>
        <button
          type="button"
          onClick={onRemove}
          aria-label="Supprimer"
          className="text-on-surface-variant hover:text-error transition-colors"
        >
          <Icon name="delete" />
        </button>
      </div>

      {expanded && (
        <div className="border-t border-outline-variant/40 p-4 space-y-4 bg-surface-container-low">
          <Field label="Label">
            <TextInput
              value={doc.label}
              onChange={(v) => onUpdate({ label: v })}
            />
          </Field>
          <Field label="Description / consignes" optional>
            <TextArea
              value={doc.description ?? ""}
              onChange={(v) => onUpdate({ description: v || undefined })}
              rows={2}
            />
          </Field>

          <DocumentFileOptions doc={doc} onUpdate={onUpdate} />

          <SampleFileSection
            doc={doc}
            serviceSlug={serviceSlug}
            onUpdate={onUpdate}
          />

          <label className="flex items-center gap-2 text-sm cursor-pointer">
            <input
              type="checkbox"
              checked={doc.required ?? false}
              onChange={(e) => onUpdate({ required: e.target.checked })}
              className="w-4 h-4 accent-primary"
            />
            Document requis
          </label>
        </div>
      )}
    </li>
  );
}

function SampleFileSection({
  doc,
  serviceSlug,
  onUpdate,
}: {
  doc: DocumentRequest;
  serviceSlug: string;
  onUpdate: (patch: Partial<DocumentRequest>) => void;
}) {
  const [uploading, setUploading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const { confirm } = useDialog();

  async function onFileChosen(file: File) {
    setError(null);
    setUploading(true);
    const fd = new FormData();
    fd.append("serviceSlug", serviceSlug);
    fd.append("docId", doc.id);
    fd.append("file", file);
    const result = await uploadSampleDocument(fd);
    setUploading(false);
    if (!result.ok) {
      setError(result.error);
      return;
    }
    onUpdate({ sampleFile: result.sample });
  }

  async function removeSample() {
    const ok = await confirm({
      title: "Retirer le document d'exemple ?",
      body: "Le client ne pourra plus télécharger ce modèle. Le fichier sera supprimé du serveur.",
      confirmLabel: "Retirer",
      danger: true,
    });
    if (!ok) return;
    onUpdate({ sampleFile: undefined });
  }

  return (
    <Field label="Document d'exemple" optional>
      {doc.sampleFile ? (
        <div className="flex items-center justify-between gap-4 bg-white border border-outline-variant px-4 py-3">
          <div className="min-w-0 flex items-center gap-3">
            <Icon name="description" className="!text-xl text-secondary" />
            <div className="min-w-0">
              <p className="font-serif text-sm text-primary truncate">
                {doc.sampleFile.name}
              </p>
              <p className="text-xs text-on-surface-variant">
                {doc.sampleFile.sizeBytes
                  ? `${(doc.sampleFile.sizeBytes / 1024 / 1024).toFixed(2)} Mo`
                  : ""}
              </p>
            </div>
          </div>
          <button
            type="button"
            onClick={removeSample}
            className="text-xs uppercase tracking-widest font-serif text-on-surface-variant hover:text-error transition-colors"
          >
            Retirer
          </button>
        </div>
      ) : (
        <label className="flex items-center gap-3 bg-white border border-outline-variant border-dashed px-4 py-3 cursor-pointer hover:border-primary transition-colors">
          <Icon name="upload" className="!text-base text-on-surface-variant" />
          <span className="text-sm text-on-surface-variant">
            {uploading ? "Upload en cours…" : "Joindre un fichier modèle (PDF, Word, etc.)"}
          </span>
          <input
            type="file"
            className="hidden"
            disabled={uploading}
            onChange={(e) => {
              const f = e.target.files?.[0];
              if (f) void onFileChosen(f);
              e.target.value = "";
            }}
          />
        </label>
      )}
      <p className="text-xs text-on-surface-variant mt-1">
        Optionnel. Le client pourra le télécharger comme modèle à compléter.
      </p>
      {error && <p className="text-error text-sm mt-1">{error}</p>}
    </Field>
  );
}

function DocumentFileOptions({
  doc,
  onUpdate,
}: {
  doc: DocumentRequest;
  onUpdate: (patch: Partial<DocumentRequest>) => void;
}) {
  const cats = doc.acceptCategories ?? [];

  function toggleCategory(cat: FileAcceptCategory, checked: boolean) {
    let next = [...cats];
    if (cat === "any" && checked) {
      next = ["any"];
    } else if (checked) {
      next = next.filter((c) => c !== "any");
      next.push(cat);
    } else {
      next = next.filter((c) => c !== cat);
    }
    onUpdate({ acceptCategories: next });
  }

  return (
    <>
      <Field label="Types de fichiers acceptés">
        <div className="flex flex-wrap gap-3">
          {FILE_CATEGORIES.map((c) => (
            <label
              key={c}
              className="flex items-center gap-2 text-sm cursor-pointer border border-outline-variant px-3 py-1.5 hover:border-primary transition-colors"
            >
              <input
                type="checkbox"
                checked={cats.includes(c)}
                onChange={(e) => toggleCategory(c, e.target.checked)}
                className="w-4 h-4 accent-primary"
              />
              {FILE_ACCEPT_LABELS[c]}
            </label>
          ))}
        </div>
      </Field>
      <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
        <Field label="Taille max par fichier (Mo)">
          <TextInput
            value={String(doc.maxSizeMb ?? 25)}
            onChange={(v) => {
              const n = Number(v);
              if (Number.isFinite(n) && n > 0) onUpdate({ maxSizeMb: n });
            }}
          />
        </Field>
        <Field label="Plusieurs fichiers ?">
          <label className="flex items-center gap-2 text-sm cursor-pointer">
            <input
              type="checkbox"
              checked={doc.multiple ?? false}
              onChange={(e) => onUpdate({ multiple: e.target.checked })}
              className="w-4 h-4 accent-primary"
            />
            Autoriser l'upload de plusieurs fichiers
          </label>
        </Field>
      </div>
    </>
  );
}
