// Screen 3 — Editor assistente: form a sezioni con validazione legata ai path,
// campi "da completare"/obbligatori in rosso, cronologia versioni e modifica con AI.
//
// Dati reali:
//   - Salvataggio:   PUT /assistants/{thread} (x-source: human|llm) → 200|400{problems}|422{pending}
//   - Modifica AI:   POST /assistants/build {description, domain, thread, target} → documento completo
//   - Cronologia:    GET/POST /assistants/{thread}/revisions… (gestita da VersionHistory)
const { Card, CardBody, Tabs, TextField, Select, RadioGroup, Switch, Button, Banner, Badge, Icon, IconButton } = window.AriaDesignSystem_af77ab;

const LANGS = [
  { value: "it", label: "Italiano" }, { value: "en", label: "English" },
  { value: "fr", label: "Français" }, { value: "de", label: "Deutsch" }, { value: "es", label: "Español" },
];

function SectionHead({ title, hint, action }) {
  return (
    <div style={{ marginBottom: 18, display: "flex", alignItems: "flex-start", gap: 12 }}>
      <div style={{ flex: 1 }}>
        <h2 style={{ font: "var(--text-h2)", color: "var(--text-strong)" }}>{title}</h2>
        {hint && <p style={{ fontSize: 13, color: "var(--text-muted)", marginTop: 4 }}>{hint}</p>}
      </div>
      {action}
    </div>
  );
}

function NavLabel({ text, issues }) {
  return (
    <span style={{ display: "inline-flex", alignItems: "center", gap: 6 }}>
      {text}
      {issues > 0 && <span title={`${issues} da completare`} style={{ width: 7, height: 7, borderRadius: "50%", background: "var(--danger-500)" }} />}
    </span>
  );
}

function StringList({ label, items, onChange, placeholder }) {
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
      <span style={{ font: "var(--text-label)", color: "var(--text-strong)" }}>{label}</span>
      {(items || []).map((it, i) => (
        <div key={i} style={{ display: "flex", gap: 8 }}>
          <div style={{ flex: 1 }}>
            <TextField value={it} onChange={(e) => onChange(items.map((x, j) => (j === i ? e.target.value : x)))} placeholder={placeholder} />
          </div>
          <IconButton label="Rimuovi" outline onClick={() => onChange(items.filter((_, j) => j !== i))}><Icon name="x" size={16} /></IconButton>
        </div>
      ))}
      <Button variant="ghost" size="sm" iconLeft={<Icon name="plus" size={15} />} style={{ alignSelf: "flex-start" }} onClick={() => onChange((items || []).concat(""))}>Aggiungi regola</Button>
    </div>
  );
}

function AssistantEditor({ initial, fromAI, onBack, onSaved }) {
  const { setIn, getIn, isPending, validate, diffConfigs, sectionForPath, labelForPath } = window.AriaEditorUtil;
  const { enums } = window.AriaData;
  const [cfg, setCfg] = React.useState(initial);
  const [section, setSection] = React.useState("base");
  const [skillFocus, setSkillFocus] = React.useState({ index: 0, nonce: 0 });
  const [historyOpen, setHistoryOpen] = React.useState(false);
  const [aiScope, setAiScope] = React.useState(null);
  const [saving, setSaving] = React.useState(false);
  const [saveError, setSaveError] = React.useState(null); // errore inatteso (rete/5xx)
  // Issue restituite dal server all'ultimo salvataggio: 400 {problems:[{path,message}]} (kind "server")
  // e 422 {pending:[path]} (kind "pending"). Si azzerano appena l'utente modifica il campo coinvolto.
  const [serverIssues, setServerIssues] = React.useState([]);
  const set = (path, value) => {
    setCfg((c) => setIn(c, path, value));
    // alla modifica di un path, rimuovi l'eventuale issue server collegata
    setServerIssues((list) => list.filter((i) => i.path !== path));
  };

  const thread = cfg.thread || null;
  const currentVersion = cfg.version != null ? cfg.version : null;

  // Validazione client (feedback immediato) + issue server dell'ultimo salvataggio.
  const clientIssues = validate(cfg);
  const issues = React.useMemo(() => {
    const seen = new Set(clientIssues.map((i) => i.path));
    return clientIssues.concat(serverIssues.filter((i) => !seen.has(i.path)));
  }, [clientIssues, serverIssues]);

  const canSave = issues.length === 0;
  const counts = { base: 0, personality: 0, behavior: 0, skills: 0 };
  issues.forEach((i) => { counts[i.section] = (counts[i.section] || 0) + 1; });
  const errText = (path) => {
    const it = issues.find((x) => x.path === path);
    if (!it) return undefined;
    if (it.kind === "server" && it.message) return it.message;
    return it.kind === "required" ? "Campo obbligatorio" : "Da completare";
  };

  function goTo(issue) {
    setSection(issue.section);
    if (issue.section === "skills" && issue.skillIndex != null) {
      setSkillFocus((f) => ({ index: issue.skillIndex, nonce: f.nonce + 1 }));
    }
  }

  // Mappa i path restituiti dal server in issue navigabili (sezione + label + skillIndex).
  function mapServerPaths(arr, kind) {
    return (arr || []).map((p) => {
      const path = typeof p === "string" ? p : p.path;
      const message = typeof p === "string" ? undefined : p.message;
      return Object.assign({ path, label: labelForPath(path), kind, message }, sectionForPath(path));
    });
  }

  function openAi(section, skillIndex) {
    // mappa le sezioni dell'editor ai target reali di /build
    const map = {
      base: { target: "description", subtitle: "Base · Descrizione" },
      personality: { target: "personality", subtitle: "Personalità" },
      behavior: { target: "rules", subtitle: "Comportamento · Regole" },
    };
    const scope = section === "skills"
      ? { section, skillIndex, target: `skill:${cfg.skills[skillIndex].id || skillIndex}`, subtitle: `Skill ${skillIndex + 1} · ${cfg.skills[skillIndex].id || "nuova"}`, placeholder: "Es. rendi la descrizione più specifica" }
      : { section, target: map[section].target, subtitle: map[section].subtitle, placeholder: "Es. rendi il tono più cordiale" };
    setAiScope(scope);
  }

  function applyAi(proposal) {
    // il backend restituisce il documento completo modificato: lo adottiamo così com'è
    setCfg(proposal.nextConfig);
    setServerIssues([]); // il documento è cambiato: le issue server precedenti non valgono più
    setAiScope(null);
  }

  // Salvataggio reale. La provenienza è "llm" per le bozze AI non ancora salvate dall'utente,
  // altrimenti "human". Gestisce 200 (successo), 400 (problems→campo) e 422 (pending→campo).
  async function save() {
    if (!thread) {
      setSaveError(new Error("Manca il thread dell'assistente: impossibile salvare. Apri l'assistente dalla lista o rigenera la bozza."));
      return;
    }
    setSaving(true);
    setSaveError(null);
    try {
      const res = await window.AriaData.saveAssistant(thread, cfg, { source: fromAI ? "llm" : "human" });
      if (res.ok) {
        setServerIssues([]);
        onSaved(cfg);
        return;
      }
      if (res.kind === "pending") {
        setServerIssues(mapServerPaths(res.pending, "pending"));
        window.AriaToast && window.AriaToast({ tone: "warning", title: "Campi da completare", body: `${res.pending.length} campi richiesti prima di salvare.` });
      } else if (res.kind === "problems") {
        setServerIssues(mapServerPaths(res.problems, "server"));
        window.AriaToast && window.AriaToast({ tone: "danger", title: "Configurazione non valida", body: `${res.problems.length} problemi da risolvere.` });
      }
    } catch (err) {
      setSaveError(err);
    } finally {
      setSaving(false);
    }
  }

  const sections = [
    { id: "base", label: <NavLabel text="Base" issues={counts.base} />, icon: <Icon name="file-text" size={16} /> },
    { id: "personality", label: <NavLabel text="Personalità" issues={counts.personality} />, icon: <Icon name="smile" size={16} /> },
    { id: "behavior", label: <NavLabel text="Comportamento" issues={counts.behavior} />, icon: <Icon name="sliders-horizontal" size={16} /> },
    { id: "skills", label: <NavLabel text="Skill" issues={counts.skills} />, icon: <Icon name="puzzle" size={16} />, count: cfg.skills.length },
  ];

  const aiBtn = (
    <Button variant="ghost" size="sm" iconLeft={<Icon name="sparkles" size={15} />} onClick={() => openAi(section)}>Modifica con AI</Button>
  );

  return (
    <React.Fragment>
      <header style={{ height: "var(--topbar-h)", flex: "none", display: "flex", alignItems: "center", gap: 12, padding: "0 28px", background: "var(--surface-card)", borderBottom: "1px solid var(--border-subtle)", position: "sticky", top: 0, zIndex: 6 }}>
        <IconButton label="Indietro" onClick={onBack}><Icon name="arrow-left" size={18} /></IconButton>
        <div style={{ display: "flex", flexDirection: "column", lineHeight: 1.25, minWidth: 0 }}>
          <span style={{ font: "var(--text-h2)", color: "var(--text-strong)" }}>{isPending(cfg.name) ? "Nuovo assistente" : cfg.name}</span>
          <span style={{ fontSize: 12, color: "var(--text-muted)" }}>{cfg.domain}{currentVersion != null ? ` · v${currentVersion}` : ""}</span>
        </div>
        <div style={{ marginLeft: "auto", display: "flex", alignItems: "center", gap: 10 }}>
          {fromAI && <Badge tone="info" dot>Bozza AI</Badge>}
          {!canSave && <Badge tone="danger">{issues.length} da completare</Badge>}
          <Button variant="ghost" iconLeft={<Icon name="history" size={16} />} disabled={!thread} onClick={() => setHistoryOpen(true)}>Cronologia</Button>
          <Button disabled={!canSave || saving} iconLeft={<Icon name={saving ? "loader" : "save"} size={16} />} onClick={save}>Salva</Button>
        </div>
      </header>

      <div style={{ overflowY: "auto", flex: 1 }}>
        <div style={{ maxWidth: 1080, margin: "0 auto", padding: 28 }}>
          {fromAI && (
            <div style={{ marginBottom: 12 }}>
              <Banner tone="info" title="Bozza generata da Aria">
                Rivedi i valori proposti. I campi che Aria non può inventare sono evidenziati come <b>da completare</b>.
              </Banner>
            </div>
          )}
          {saveError && (
            <div style={{ marginBottom: 12 }}>
              <Banner tone="danger" title="Salvataggio non riuscito" icon="alert-circle">
                {saveError.message || "Errore inatteso. Riprova."}
              </Banner>
            </div>
          )}
          {!canSave && (
            <div style={{ marginBottom: 18 }}>
              <Banner tone="danger" title={`${issues.length} campi da completare`} icon="alert-circle">
                <span>Il salvataggio è disabilitato. Vai al campo: </span>
                <span style={{ display: "inline-flex", flexWrap: "wrap", gap: 6, marginTop: 6 }}>
                  {issues.map((it) => (
                    <button key={it.path} onClick={() => goTo(it)} style={{ border: 0, background: "transparent", padding: 0, cursor: "pointer" }}>
                      <Badge tone="danger">{it.label} <span aria-hidden="true" style={{ marginLeft: 2 }}>↗</span></Badge>
                    </button>
                  ))}
                </span>
              </Banner>
            </div>
          )}

          <div style={{ display: "grid", gridTemplateColumns: "208px 1fr", gap: 28, alignItems: "start" }}>
            <div style={{ position: "sticky", top: 16 }}>
              <Tabs vertical value={section} onChange={setSection} tabs={sections} />
            </div>

            <div style={{ minWidth: 0 }}>
              {section === "base" && (
                <Card><CardBody>
                  <SectionHead title="Base" hint="Identità dell'assistente all'interno del dominio." action={aiBtn} />
                  <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "18px 20px", alignItems: "start" }}>
                    <TextField label="ID" required value={isPending(cfg.id) ? "" : cfg.id} error={errText("id")} placeholder="es. supporto-clienti" hint="Identificatore tecnico, minuscolo." onChange={(e) => set("id", e.target.value)} />
                    <TextField label="Nome" required value={isPending(cfg.name) ? "" : cfg.name} error={errText("name")} placeholder="es. Supporto clienti" onChange={(e) => set("name", e.target.value)} />
                    <Select label="Lingua" value={cfg.language || "it"} onChange={(e) => set("language", e.target.value)} options={LANGS} />
                    <TextField label="Saluto iniziale" optional value={cfg.greeting || ""} onChange={(e) => set("greeting", e.target.value)} />
                    <div style={{ gridColumn: "1 / -1" }}>
                      <TextField label="Descrizione" required multiline rows={3} value={isPending(cfg.description) ? "" : cfg.description} error={errText("description")} onChange={(e) => set("description", e.target.value)} />
                    </div>
                  </div>
                </CardBody></Card>
              )}

              {section === "personality" && (
                <Card><CardBody>
                  <SectionHead title="Personalità" hint="Come si presenta e dialoga l'assistente." action={aiBtn} />
                  <div style={{ display: "flex", flexDirection: "column", gap: 18 }}>
                    <TextField label="Persona" required value={isPending(cfg.personality.persona) ? "" : cfg.personality.persona} error={errText("personality.persona")} onChange={(e) => set("personality.persona", e.target.value)} />
                    <TextField label="Tono" required value={isPending(cfg.personality.tone) ? "" : cfg.personality.tone} error={errText("personality.tone")} onChange={(e) => set("personality.tone", e.target.value)} />
                    <div style={{ maxWidth: 260 }}>
                      <TextField label="Ritmo" type="number" min={1} value={cfg.personality.pacing ?? 2} hint="1 = essenziale, valori più alti = più discorsivo." onChange={(e) => set("personality.pacing", Number(e.target.value))} />
                    </div>
                  </div>
                </CardBody></Card>
              )}

              {section === "behavior" && (
                <Card><CardBody>
                  <SectionHead title="Comportamento" hint="Regole di instradamento e gestione della conversazione." action={aiBtn} />
                  <div style={{ display: "flex", flexDirection: "column", gap: 20 }}>
                    <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "18px 20px" }}>
                      <RadioGroup label="Al cambio skill" value={cfg.behavior.onSwitch} onChange={(v) => set("behavior.onSwitch", v)} options={enums.onSwitch} hint="Conferma o passaggio fluido tra skill." />
                      <RadioGroup label="Multi-intent" value={cfg.behavior.multiIntent} onChange={(v) => set("behavior.multiIntent", v)} options={enums.multiIntent} />
                      <RadioGroup label="Fuori tema" value={cfg.behavior.offTopic} onChange={(v) => set("behavior.offTopic", v)} options={enums.offTopic} />
                      <Select label="Skill di fallback" required value={cfg.behavior.fallbackSkillId} error={errText("behavior.fallbackSkillId")} onChange={(e) => set("behavior.fallbackSkillId", e.target.value)} options={cfg.skills.map((s) => ({ value: s.id, label: s.id || "(senza id)" }))} />
                      <div style={{ maxWidth: 220 }}>
                        <TextField label="Riprese proattive max" type="number" min={0} value={cfg.behavior.resumeSuspended.max} onChange={(e) => set("behavior.resumeSuspended.max", Number(e.target.value))} />
                      </div>
                      <div style={{ alignSelf: "end", paddingBottom: 8 }}>
                        <Switch checked={cfg.behavior.inputFilter.enabled} onChange={(e) => set("behavior.inputFilter.enabled", e.target.checked)} label="Filtro input attivo" />
                      </div>
                    </div>
                    <div style={{ borderTop: "1px solid var(--border-subtle)", paddingTop: 18, display: "grid", gridTemplateColumns: "1fr 1fr", gap: 24 }}>
                      <StringList label="Regole" items={cfg.behavior.rules} onChange={(v) => set("behavior.rules", v)} placeholder="Es. Rispondi sempre in italiano." />
                      <StringList label="Regole di sicurezza" items={cfg.behavior.securityRules} onChange={(v) => set("behavior.securityRules", v)} placeholder="Es. Non rivelare dati di altri clienti." />
                    </div>
                  </div>
                </CardBody></Card>
              )}

              {section === "skills" && (
                <div>
                  <SectionHead title="Skill" hint="Unità di funzionalità: attributi da raccogliere e azione finale." />
                  <SkillSection config={cfg} onChange={set} errText={errText} focus={skillFocus} onAiEdit={(i) => openAi("skills", i)} />
                </div>
              )}
            </div>
          </div>
        </div>
      </div>

      {window.VersionHistory && (
        <window.VersionHistory
          open={historyOpen}
          thread={thread}
          currentVersion={currentVersion}
          onRestored={async (res) => {
            // Dopo il ripristino il backend ha creato una nuova revisione: ricarica la config corrente.
            try {
              const fresh = await window.AriaData.getAssistant(res.thread || thread);
              setCfg(fresh);
              setServerIssues([]);
            } catch (_e) {
              // se il reload fallisce, lascia la config attuale; l'utente può ricaricare manualmente
            }
          }}
          onClose={() => setHistoryOpen(false)} />
      )}
      {window.AiEditDialog && (
        <window.AiEditDialog
          open={!!aiScope} scope={aiScope}
          examples={["Rendi il tono più cordiale", "Sii più conciso", "Adatta a un pubblico tecnico"]}
          onGenerate={async (instruction) => {
            // POST /assistants/build con target → documento completo; il diff è client-side.
            const res = await window.AriaData.buildAssistant({
              description: instruction, domain: cfg.domain, thread: thread || undefined, target: aiScope.target,
            });
            if (!res.ok) {
              const e = new Error("Aria non ha prodotto una modifica valida. Riformula l'istruzione.");
              e.problems = res.problems;
              throw e;
            }
            return {
              summary: "Proposta generata da Aria.",
              changes: diffConfigs(cfg, res.config),
              nextConfig: res.config,
            };
          }}
          onApply={applyAi} onClose={() => setAiScope(null)} />
      )}
    </React.Fragment>
  );
}

Object.assign(window, { AssistantEditor });
