import React, { useEffect, useState } from "react";
import { api } from "./api.js";
import { Spinner } from "./ui.jsx";

// Description declarative des champs, groupes par section.
const SECTIONS = [
  {
    title: "Modèles (identifiants MLX / HuggingFace)",
    hint: "Changer un identifiant recharge un autre modèle (peut déclencher un téléchargement au prochain usage).",
    fields: [
      { key: "gemma_model", label: "Gemma (analyse)", type: "text" },
      { key: "qwen3_model", label: "Qwen3-TTS (rendu)", type: "text" },
      { key: "kokoro_model", label: "Kokoro (preview)", type: "text" },
    ],
  },
  {
    title: "Génération Gemma",
    hint: "Paramètres d'échantillonnage de l'analyse (locuteurs, personnages, prononciations).",
    fields: [
      { key: "gemma_temperature", label: "Température", type: "number", step: 0.05, min: 0, max: 2 },
      { key: "gemma_max_tokens", label: "Max tokens", type: "number", step: 1, min: 64, max: 8192 },
    ],
  },
  {
    title: "Prompts système (analyse)",
    hint: "Instructions envoyées à Gemma avant chaque tâche. Le modèle doit répondre en JSON.",
    fields: [
      { key: "prompt_speakers", label: "Attribution des locuteurs", type: "textarea" },
      { key: "prompt_characters", label: "Extraction des personnages", type: "textarea" },
      { key: "prompt_pronunciation", label: "Mots à risque (prononciation)", type: "textarea" },
    ],
  },
  {
    title: "Casting (déduplication)",
    hint: "Le rapprochement des variantes de noms (Holden / James Holden / James) est heuristique et sûr. La passe Gemma ajoute les variantes non évidentes (diminutifs, titres) mais, avec un petit modèle local, produit des fusions erronées.",
    fields: [
      { key: "dedup_use_gemma", label: "Affiner la déduplication avec Gemma (moins sûr)", type: "checkbox" },
    ],
  },
  {
    title: "TTS (voix par défaut)",
    hint: "Backend et voix utilisés par défaut pour le rendu et les replis.",
    fields: [
      { key: "default_backend", label: "Backend par défaut", type: "select",
        options: [["kokoro", "Kokoro (rapide)"], ["qwen3", "Qwen3 (qualité + clonage)"]] },
      { key: "language", label: "Langue (Qwen3)", type: "text" },
      { key: "kokoro_lang_code", label: "Code langue Kokoro", type: "text" },
      { key: "kokoro_default_voice", label: "Voix Kokoro par défaut", type: "text" },
      { key: "qwen3_default_voice", label: "Voix Qwen3 par défaut", type: "text" },
    ],
  },
  {
    title: "Audio (encodage final)",
    hint: "Appliqué à la concaténation et à l'export MP3.",
    fields: [
      { key: "target_sample_rate", label: "Sample rate (Hz)", type: "number", step: 1000, min: 8000, max: 48000 },
      { key: "mp3_bitrate", label: "Bitrate MP3", type: "text" },
      { key: "target_dbfs", label: "Normalisation (dBFS)", type: "number", step: 0.5, min: -40, max: 0 },
    ],
  },
];

function Field({ field, value, onChange }) {
  const common = "input w-full";
  if (field.type === "checkbox")
    return <input type="checkbox" className="h-4 w-4"
      checked={!!value} onChange={(e) => onChange(e.target.checked)} />;
  if (field.type === "textarea")
    return <textarea className={`${common} min-h-[5rem] resize-y text-sm`} rows={4}
      value={value ?? ""} onChange={(e) => onChange(e.target.value)} />;
  if (field.type === "select")
    return <select className={common} value={value ?? ""} onChange={(e) => onChange(e.target.value)}>
      {field.options.map(([v, lbl]) => <option key={v} value={v}>{lbl}</option>)}
    </select>;
  if (field.type === "number")
    return <input className={common} type="number"
      step={field.step} min={field.min} max={field.max}
      value={value ?? ""} onChange={(e) => onChange(e.target.value === "" ? "" : Number(e.target.value))} />;
  return <input className={common} type="text"
    value={value ?? ""} onChange={(e) => onChange(e.target.value)} />;
}

export default function Settings({ onBack }) {
  const [settings, setSettings] = useState(null);
  const [saved, setSaved] = useState(false);
  const [error, setError] = useState(null);

  useEffect(() => {
    api.getSettings().then(setSettings).catch((e) => setError(String(e)));
  }, []);

  if (error) return <p className="text-sm text-red-400">{error}</p>;
  if (!settings) return <p className="text-ink-muted"><Spinner /> chargement des réglages…</p>;

  const set = (key, val) => { setSettings({ ...settings, [key]: val }); setSaved(false); };

  const save = async () => {
    setError(null);
    try { await api.putSettings(settings); setSaved(true); }
    catch (e) { setError("Échec de l'enregistrement : " + e); }
  };

  return (
    <div className="space-y-6">
      <div className="flex items-center gap-3">
        <button onClick={onBack} className="text-sm text-ink-muted hover:text-ink-text">← Bibliothèque</button>
        <h1 className="font-serif text-2xl">Réglages techniques</h1>
        <button className="btn-primary ml-auto" onClick={save}>
          {saved ? "✓ enregistré" : "Enregistrer"}
        </button>
      </div>

      <p className="text-sm text-ink-muted">
        Réglages globaux appliqués à toute l'app. Les changements de modèle prennent effet au
        prochain lancement d'analyse ou de rendu.
      </p>

      {SECTIONS.map((sec) => (
        <section key={sec.title} className="card p-4 space-y-3">
          <div>
            <h2 className="font-medium">{sec.title}</h2>
            {sec.hint && <p className="text-xs text-ink-muted">{sec.hint}</p>}
          </div>
          <div className="grid gap-3">
            {sec.fields.map((f) => (
              <label key={f.key} className="grid gap-1">
                <span className="text-sm text-ink-muted">{f.label}</span>
                <Field field={f} value={settings[f.key]} onChange={(v) => set(f.key, v)} />
              </label>
            ))}
          </div>
        </section>
      ))}

      <div className="flex justify-end">
        <button className="btn-primary" onClick={save}>
          {saved ? "✓ enregistré" : "Enregistrer"}
        </button>
      </div>
    </div>
  );
}
