/* global React, window, Kw, Parsed */
/* ============================================================
   RACE + ORIGIN CREATOR — abas "Raças" e "Origens"
   Lista filtrável à esquerda · detalhes à direita.
   Seleção persiste em localStorage.
   Preparado para grandes volumes (50+ raças, 100+ origens):
     – busca em tempo real
     – filtro por fonte (chips)
     – lista ordenada alfabeticamente
     – scroll nos dois lados
   ============================================================ */

const { useState, useEffect, useMemo } = React;

const LS_RACE   = "arton_char_race";
const LS_ORIGIN = "arton_char_origin";
const LS_CLASS  = "arton_char_class";

/* ============================================================
   REGRAS ESPECIAIS POR ORIGEM
   ============================================================ */

/** "Duplo Feérico (Pondsmânia)" exige escolher uma habilidade
   de classe de 1º nível de uma classe diferente da sua. */
function isDuploFeerico(origin) {
  return !!origin && /^Duplo Feérico/i.test(origin.name);
}

/** Lê as classes salvas do personagem (multiclasse). */
function getSavedClassNames() {
  try {
    const data = JSON.parse(localStorage.getItem(LS_CLASS));
    if (data && Array.isArray(data.classes)) {
      return data.classes.map((c) => c.className).filter(Boolean);
    }
  } catch {}
  return [];
}

/** Normaliza nome removendo parênteses finais — "Magias (1º círculo)" → "magias". */
function normalizeFeatureName(s) {
  return (s || "").replace(/\s*\([^)]*\)\s*$/, "").trim().toLowerCase();
}

/** Para uma classe, devolve as habilidades de 1º nível (sem slots de poder),
   resolvendo nome → descrição completa via features[]. */
function getLevel1Abilities(classObj) {
  const prog = classObj?.feature_progression?.["1"];
  if (!Array.isArray(prog)) return [];
  const features = classObj.features || [];
  return prog
    .filter(p => !p.is_power_slot)
    .map(p => {
      const norm = normalizeFeatureName(p.name);
      const full = features.find(f =>
        f.level === 1 && normalizeFeatureName(f.name) === norm
      );
      return {
        name: full?.name || p.name,
        description: full?.description || "",
      };
    });
}

/** Marca "Magias" e variantes para alertas especiais do Duplo Feérico. */
function isMagiasAbility(featureName) {
  return /^magias\b/i.test(featureName || "");
}

/* Ofícios disponíveis para o sub-picker */
const OFICIO_TYPES = [
  "alfaiate","alquimista","armeiro","artesão","barbeiro","carpinteiro",
  "cozinheiro","coureiro","escriba","escultor","ferreiro","joalheiro",
  "marceneiro","minerador","músico","ourives","pedreiro","pescador",
  "pintor","sapateiro","servial","tecelão",
];

/* Perícias para o sub-picker de "qualquer perícia" */
const T20_SKILL_LIST = [
  "Acrobacia","Adestramento","Arte","Atletismo","Atuação",
  "Cavalgar","Conhecimento","Cura","Diplomacia","Enganação",
  "Fortitude","Furtividade","Guerra","Iniciativa","Intimidação",
  "Intuição","Investigação","Jogatina","Ladinagem","Luta",
  "Misticismo","Nobreza","Ofício","Percepção","Pilotagem",
  "Pontaria","Reflexos","Religião","Sobrevivência","Vontade",
];

function lsGet(key)      { try { return JSON.parse(localStorage.getItem(key)); } catch { return null; } }
function lsSet(key, val) {
  try { localStorage.setItem(key, JSON.stringify(val)); } catch {}
  try { window.dispatchEvent(new CustomEvent("arton:char-changed")); } catch {}
}

function RCCorners() {
  return <>
    <span className="frame-corner tl"/>
    <span className="frame-corner tr"/>
    <span className="frame-corner bl"/>
    <span className="frame-corner br"/>
  </>;
}

/* chips de fonte — só aparece quando há múltiplas fontes */
function SourceChips({ sources, active, onToggle }) {
  if (!sources || sources.length <= 1) return null;
  return (
    <div className="rc-source-chips">
      {sources.map(s => (
        <button
          key={s}
          className={"rc-source-chip" + (active === s ? " active" : "")}
          onClick={() => onToggle(s)}
        >
          {s}
        </button>
      ))}
    </div>
  );
}

const ATTR_NAMES = { for: "Força", des: "Destreza", con: "Constituição", int: "Inteligência", sab: "Sabedoria", car: "Carisma" };

/* "Força +2 · Constituição +1" — handles real API format */
function fmtAttrMods(mods) {
  if (!mods) return "—";
  const parts = [];
  for (const [k, v] of Object.entries(mods)) {
    if (k === "variable") {
      if (v && v.count > 0) parts.push(`Escolha ${v.count} atributo${v.count !== 1 ? "s" : ""} +${v.amount}`);
    } else if (v) {
      parts.push(`${ATTR_NAMES[k] || k} ${v > 0 ? "+" : ""}${v}`);
    }
  }
  return parts.length ? parts.join(" · ") : "—";
}

/* ============================================================
   RACE LIST  (página esquerda)
   ============================================================ */
function RaceList({ races, total, selected, saved, onSelect, query, setQuery, sources, activeSource, onSourceToggle }) {
  const folioLabel = races.length < total ? `${races.length} de ${total}` : String(total);
  return (
    <div className="page-content rc-list-page">
      <header className="page-header">
        <span className="page-eyebrow">Raças · Personagem</span>
        <span className="page-folio">{folioLabel} raças</span>
      </header>
      <h1 className="page-title">Escolher Raça</h1>
      <p className="page-subtitle">
        A raça concede modificadores de atributo, habilidades raciais e slots de poder.
      </p>
      <div className="rc-search-wrap">
        <input
          className="rc-search"
          placeholder="Buscar raça…"
          value={query}
          onChange={e => setQuery(e.target.value)}
        />
      </div>
      <SourceChips sources={sources} active={activeSource} onToggle={onSourceToggle}/>
      <div className="rc-entity-list">
        {races.map(r => {
          const isSaved    = saved?.id === r.id;
          const isSelected = selected?.id === r.id;
          return (
            <button
              key={r.id}
              className={"rc-entity-row" + (isSelected ? " rc-selected" : "") + (isSaved ? " rc-saved" : "")}
              onClick={() => onSelect(r)}
            >
              <div className="rc-entity-main">
                <span className="rc-entity-name">
                  {r.name}{r.variant ? <span className="rc-variant"> · {r.variant}</span> : null}
                </span>
                <span className="rc-entity-source">{r.source}</span>
              </div>
              <div className="rc-entity-sub">
                <span className="rc-attr-preview">{fmtAttrMods(r.attr_modifiers)}</span>
                {isSaved && <span className="rc-saved-badge">✦ Salvo</span>}
              </div>
            </button>
          );
        })}
        {races.length === 0 && (
          <div className="rc-empty">Nenhuma raça encontrada.</div>
        )}
      </div>
    </div>
  );
}

/* ============================================================
   RACE DETAIL  (página direita)
   ============================================================ */
const ATTR_ABBREVS = ["FOR", "DES", "CON", "INT", "SAB", "CAR"];
const ATTR_LABELS = { FOR: "Força", DES: "Destreza", CON: "Constituição", INT: "Inteligência", SAB: "Sabedoria", CAR: "Carisma" };

function VariableAttrPicker({ rule, picks, onChange }) {
  if (!rule || !rule.count) return null;
  const chosen = picks.filter(Boolean);
  const sign = rule.amount >= 0 ? "+" : "";
  function toggle(attr) {
    const isActive = chosen.includes(attr);
    let next;
    if (isActive) {
      next = chosen.filter((a) => a !== attr);
    } else {
      if (chosen.length >= rule.count) return; /* já cheio */
      next = [...chosen, attr];
    }
    /* mantém o tamanho do array igual a rule.count, preenchendo com null */
    while (next.length < rule.count) next.push(null);
    onChange(next);
  }
  return (
    <div className="rc-var-picker">
      <div className="rc-benefit-picker-label">
        Escolha {rule.count} atributo{rule.count !== 1 ? "s" : ""} <Kw kind="attribute">{sign}{rule.amount}</Kw> ({chosen.length}/{rule.count})
      </div>
      <div className="rc-benefit-chips">
        {ATTR_ABBREVS.map((a) => {
          const isActive = chosen.includes(a);
          const isFull = chosen.length >= rule.count && !isActive;
          return (
            <button
              key={a}
              className={"rc-benefit-chip" + (isActive ? " active" : "")}
              disabled={isFull}
              onClick={() => toggle(a)}
              title={ATTR_LABELS[a]}
            >
              {ATTR_LABELS[a]} {sign}{rule.amount}
            </button>
          );
        })}
      </div>
    </div>
  );
}

function RaceDetail({ race, saved, onSave, variablePicks, onPicksChange }) {
  if (!race) {
    return (
      <div className="page-content">
        <header className="page-header">
          <span className="page-eyebrow">Detalhes</span>
          <span className="page-folio">—</span>
        </header>
        <div className="empty-state">
          <div className="ornament">✦ ✦ ✦</div>
          <div>Selecione uma raça à esquerda.</div>
        </div>
      </div>
    );
  }
  const isSaved = saved?.id === race.id;
  const variableRule = race?.attr_modifiers?.variable;
  const hasVariable = !!(variableRule && variableRule.count > 0);
  const picksComplete = !hasVariable || (Array.isArray(variablePicks) && variablePicks.length === variableRule.count && variablePicks.every(Boolean));
  return (
    <div className="page-content rc-detail-page">
      <header className="page-header">
        <span className="page-eyebrow">Raça · {race.source}</span>
        <span className="page-folio">{race.racial_power_slots} slot{race.racial_power_slots !== 1 ? "s" : ""} racial{race.racial_power_slots !== 1 ? "is" : ""}</span>
      </header>
      <h1 className="page-title">{race.name}</h1>
      {race.variant && <p className="page-subtitle">{race.variant}</p>}
      <div className="rc-detail-body">
        <dl className="statblock">
          {Object.entries(race.attr_modifiers || {}).map(([k, v]) => {
            if (k === "variable") return null; /* renderizado pelo picker abaixo */
            if (!v) return null;
            return (
              <div key={k}>
                <dt>{ATTR_NAMES[k] || k}</dt>
                <dd><Kw kind="attribute">{v > 0 ? "+" : ""}{v}</Kw></dd>
              </div>
            );
          })}
          <div>
            <dt>Poderes raciais</dt>
            <dd>{race.racial_power_slots} slot{race.racial_power_slots !== 1 ? "s" : ""}</dd>
          </div>
        </dl>
        {hasVariable && (
          <VariableAttrPicker
            rule={variableRule}
            picks={variablePicks}
            onChange={onPicksChange}
          />
        )}
        <div className="divider">❦</div>
        <div className="rc-abilities">
          {(race.abilities || []).map((ab, i) => (
            <div key={i} className="rc-ability">
              <div className="rc-ability-name"><Kw kind="race">{ab.name}</Kw></div>
              <div className="rc-ability-desc"><Parsed>{ab.description}</Parsed></div>
            </div>
          ))}
        </div>
      </div>
      <div className="rc-save-wrap">
        <button
          className={"rc-save-btn" + (isSaved ? " is-saved" : "") + (!picksComplete ? " is-disabled" : "")}
          onClick={() => {
            if (isSaved || !picksComplete) return;
            onSave(race, hasVariable ? variablePicks : undefined);
          }}
          disabled={!isSaved && !picksComplete}
          title={!picksComplete ? `Faltam ${variableRule.count - variablePicks.filter(Boolean).length} escolha(s) de atributo` : ""}
        >
          {isSaved
            ? "✦ Raça selecionada"
            : (picksComplete ? "Selecionar esta raça" : `Escolha ${variableRule.count - variablePicks.filter(Boolean).length} atributo(s)`)}
        </button>
      </div>
    </div>
  );
}

/* ============================================================
   RACE CREATOR  (root da aba "racas")
   ============================================================ */
function RaceCreator() {
  const [allRaces, setAllRaces] = useState([]);
  const [loading,  setLoading]  = useState(true);
  const [query,    setQuery]    = useState("");
  const [activeSource, setActiveSource] = useState(null);
  const [selected, setSelected] = useState(null);
  const [saved,    setSaved]    = useState(() => lsGet(LS_RACE));
  /* picks da regra "Escolha X atributos +Y" — array de abreviações (FOR/DES/...) */
  const [variablePicks, setVariablePicks] = useState(() => {
    const s = lsGet(LS_RACE);
    return Array.isArray(s?.variable_picks) ? s.variable_picks : [];
  });

  useEffect(() => {
    window.fetchRaces().then(data => {
      const sorted = [...data].sort((a, b) =>
        a.name.localeCompare(b.name, "pt-BR") || (a.variant || "").localeCompare(b.variant || "", "pt-BR")
      );
      setAllRaces(sorted);
      setLoading(false);
      const s = lsGet(LS_RACE);
      if (s) setSelected(sorted.find(r => r.id === s.id) || null);
    });
  }, []);

  /* Ao trocar a raça SELECIONADA (navegação na lista), inicializa os picks:
     se for a raça já salva, recarrega; senão limpa (a quantidade depende da raça). */
  useEffect(() => {
    if (!selected) { setVariablePicks([]); return; }
    if (saved?.id === selected.id && Array.isArray(saved.variable_picks)) {
      setVariablePicks(saved.variable_picks);
    } else {
      const n = selected?.attr_modifiers?.variable?.count || 0;
      setVariablePicks(Array(n).fill(null));
    }
  }, [selected?.id]);

  const sources = useMemo(() => [...new Set(allRaces.map(r => r.source))].sort(), [allRaces]);

  const filtered = useMemo(() => {
    let out = allRaces;
    if (activeSource) out = out.filter(r => r.source === activeSource);
    const q = query.toLowerCase().trim();
    if (q) out = out.filter(r =>
      r.name.toLowerCase().includes(q) ||
      (r.variant || "").toLowerCase().includes(q)
    );
    return out;
  }, [allRaces, query, activeSource]);

  const handleSave = (race, picks) => {
    const val = { id: race.id, name: race.name, variant: race.variant, source: race.source };
    if (Array.isArray(picks) && picks.length > 0) val.variable_picks = picks;
    lsSet(LS_RACE, val);
    setSaved(val);
    /* defesa em duas camadas: lsSet já dispara, mas micro-task garante que
       qualquer leitura síncrona de localStorage ocorra depois do write. */
    queueMicrotask(() => {
      try { window.dispatchEvent(new CustomEvent("arton:char-changed")); } catch {}
    });
  };

  /* Re-dispatch char-changed a cada mudança de saved (defesa contra batching). */
  useEffect(() => {
    try { window.dispatchEvent(new CustomEvent("arton:char-changed")); } catch {}
  }, [saved]);

  /* Quando a raça selecionada JÁ É a raça salva e o usuário altera picks,
     persiste imediatamente — o painel reage via storage event. */
  const handlePicksChange = (nextPicks) => {
    setVariablePicks(nextPicks);
    if (selected && saved?.id === selected.id) {
      const val = { id: saved.id, name: saved.name, variant: saved.variant, source: saved.source };
      if (nextPicks.length > 0) val.variable_picks = nextPicks;
      lsSet(LS_RACE, val);
      setSaved(val);
    }
  };

  return (
    <div className="cc-root">
      <div className="spread-frame">
        <div className="page left">
          <RCCorners/>
          {loading
            ? <div className="page-content"><div className="empty-state"><div className="ornament">·</div><div>Carregando raças…</div></div></div>
            : <RaceList
                races={filtered}
                total={allRaces.length}
                selected={selected}
                saved={saved}
                onSelect={setSelected}
                query={query}
                setQuery={setQuery}
                sources={sources}
                activeSource={activeSource}
                onSourceToggle={s => setActiveSource(prev => prev === s ? null : s)}
              />
          }
        </div>
        <div className="page right">
          <RCCorners/>
          <RaceDetail
            race={selected}
            saved={saved}
            onSave={handleSave}
            variablePicks={variablePicks}
            onPicksChange={handlePicksChange}
          />
        </div>
      </div>
    </div>
  );
}

/* ============================================================
   ORIGIN LIST  (página esquerda)
   ============================================================ */
function OriginList({ origins, total, selected, saved, onSelect, query, setQuery, sources, activeSource, onSourceToggle }) {
  const folioLabel = origins.length < total ? `${origins.length} de ${total}` : String(total);
  return (
    <div className="page-content rc-list-page">
      <header className="page-header">
        <span className="page-eyebrow">Origens · Personagem</span>
        <span className="page-folio">{folioLabel} origens</span>
      </header>
      <h1 className="page-title">Escolher Origem</h1>
      <p className="page-subtitle">
        A origem define o passado do personagem e concede perícias, equipamentos e bônus de atributo.
      </p>
      <div className="rc-search-wrap">
        <input
          className="rc-search"
          placeholder="Buscar origem…"
          value={query}
          onChange={e => setQuery(e.target.value)}
        />
      </div>
      <SourceChips sources={sources} active={activeSource} onToggle={onSourceToggle}/>
      <div className="rc-entity-list">
        {origins.map(o => {
          const isSaved    = saved?.id === o.id;
          const isSelected = selected?.id === o.id;
          const attrLine   = (o.benefits || [])
            .filter(b => b.type === "attribute")
            .map(b => `${b.name} ${b.bonus}`)
            .join(" · ");
          const skillLine  = (o.benefits || [])
            .filter(b => b.type === "skill")
            .map(b => b.name)
            .join(" · ");
          return (
            <button
              key={o.id}
              className={"rc-entity-row" + (isSelected ? " rc-selected" : "") + (isSaved ? " rc-saved" : "")}
              onClick={() => onSelect(o)}
            >
              <div className="rc-entity-main">
                <span className="rc-entity-name">{o.name}</span>
                <span className="rc-entity-source">{o.source}</span>
              </div>
              <div className="rc-entity-sub">
                <span className="rc-attr-preview">{attrLine || skillLine}</span>
                {isSaved && <span className="rc-saved-badge">✦ Salvo</span>}
              </div>
            </button>
          );
        })}
        {origins.length === 0 && (
          <div className="rc-empty">Nenhuma origem encontrada.</div>
        )}
      </div>
    </div>
  );
}

/* ============================================================
   ORIGIN DETAIL  (página direita)
   ============================================================ */
/* ============================================================
   DUPLO FEÉRICO PICKER  — escolha de habilidade de classe extra
   ============================================================ */
function DuploFeericoPicker({ duploPick, setDuploPick, savedClassNames }) {
  const allClasses = window.CLASSES || [];
  const charClassesSet = new Set(savedClassNames || []);

  /* Sem dados? avisa em vez de quebrar silenciosamente. */
  if (allClasses.length === 0) {
    return (
      <div className="rc-duplo-card">
        <div className="rc-section-label">Habilidade Duplicada</div>
        <p style={{ fontSize: 12.5, color: "var(--kw-condition)", margin: "6px 0 0", fontStyle: "italic" }}>
          Lista de classes ainda não carregada. Tente recarregar a página.
        </p>
      </div>
    );
  }

  /* Classes elegíveis: todas exceto as do personagem. */
  const eligible = allClasses
    .filter(c => !charClassesSet.has(c.name))
    .slice()
    .sort((a, b) => a.name.localeCompare(b.name, "pt-BR"));

  /* Conflito: a classe escolhida no Duplo agora é uma das classes do personagem. */
  const hasConflict = !!duploPick?.class_name
    && charClassesSet.has(duploPick.class_name);

  const selectedClass = eligible.find(c => c.name === duploPick?.class_name) || null;
  const abilities     = selectedClass ? getLevel1Abilities(selectedClass) : [];

  const pickedAbility = duploPick?.feature_name
    ? abilities.find(a => a.name === duploPick.feature_name) || null
    : null;

  const handleClassPick = (className) => {
    /* Trocar de classe limpa a habilidade. */
    setDuploPick({ class_name: className, feature_name: null });
  };

  const handleAbilityPick = (abilityName) => {
    setDuploPick(prev => ({
      class_name: prev?.class_name || selectedClass?.name || null,
      feature_name: prev?.feature_name === abilityName ? null : abilityName,
    }));
  };

  return (
    <div className="rc-duplo-card">
      <div className="rc-section-label" style={{ display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap" }}>
        <span>Habilidade Duplicada</span>
        {duploPick?.feature_name && (
          <span style={{
            fontFamily: "var(--font-body)",
            fontStyle: "italic",
            fontSize: 11,
            color: "var(--gilt-1)",
            textTransform: "none",
            letterSpacing: 0,
            fontWeight: 400,
          }}>
            {duploPick.class_name} · {duploPick.feature_name}
          </span>
        )}
      </div>

      <p className="rc-duplo-hint">
        {savedClassNames && savedClassNames.length > 0
          ? <>Suas classes atuais: {savedClassNames.map((n, i) => (
              <span key={n}>{i > 0 && " · "}<Kw kind="class">{n}</Kw></span>
            ))}. Escolha uma habilidade de 1º nível de uma classe diferente.</>
          : <>Você ainda não escolheu uma classe. Quando escolher, voltará aqui para excluí-la da lista.</>
        }
      </p>

      {hasConflict && (
        <div className="rc-duplo-conflict">
          <strong>⚠ Conflito:</strong> <Kw kind="class">{duploPick.class_name}</Kw>
          {" "}agora é uma das suas classes. Selecione outra classe abaixo.
        </div>
      )}

      {/* passo 1 — classe */}
      <div className="rc-duplo-step-label">1. Classe</div>
      <div className="rc-duplo-class-chips">
        {eligible.map(c => (
          <button
            key={c.name}
            className={"rc-duplo-chip" + (duploPick?.class_name === c.name ? " active" : "")}
            onClick={() => handleClassPick(c.name)}
          >
            {c.name}
          </button>
        ))}
      </div>

      {/* passo 2 — habilidade */}
      {selectedClass && (
        <>
          <div className="rc-duplo-step-label" style={{ marginTop: 12 }}>
            2. Habilidade de {selectedClass.name}
          </div>
          {abilities.length === 0 ? (
            <p style={{ fontSize: 12, fontStyle: "italic", color: "var(--ink-2)", margin: "4px 0 0" }}>
              Nenhuma habilidade de 1º nível registrada para esta classe.
            </p>
          ) : (
            <div className="rc-duplo-abilities">
              {abilities.map(a => {
                const isSelected = duploPick?.feature_name === a.name;
                const isMagias   = isMagiasAbility(a.name);
                return (
                  <div
                    key={a.name}
                    className={"rc-duplo-ability" + (isSelected ? " is-selected" : "")}
                    onClick={() => handleAbilityPick(a.name)}
                  >
                    <div className="rc-duplo-ability-head">
                      <span className={"rc-duplo-radio" + (isSelected ? " is-selected" : "")}>
                        <span className="rc-duplo-radio-dot"/>
                      </span>
                      <span className="rc-duplo-ability-name">{a.name}</span>
                      {isMagias && (
                        <span className="rc-duplo-magias-flag" title="Regra especial: só aprende uma magia, ganha +1 PM, não soma atributo-chave.">
                          ⚠ regra especial
                        </span>
                      )}
                    </div>
                  </div>
                );
              })}
            </div>
          )}
        </>
      )}

      {/* descrição da habilidade escolhida */}
      {pickedAbility?.description && (
        <div className="rc-duplo-desc">
          <Parsed>{pickedAbility.description}</Parsed>
          {isMagiasAbility(pickedAbility.name) && (
            <p className="rc-duplo-magias-warning">
              <strong>Atenção:</strong> ao escolher <em>Magias</em> via Duplo Feérico,
              você aprende <strong>uma única magia</strong> e recebe <strong>+1 PM</strong>,
              mas <em>não</em> soma o atributo-chave da habilidade no seu total de PM.
            </p>
          )}
        </div>
      )}
    </div>
  );
}

function OriginDetail({ origin, saved, onSave, benefitPicks, setBenefitPicks, duploPick, setDuploPick, savedClassNames }) {
  if (!origin) {
    return (
      <div className="page-content">
        <header className="page-header">
          <span className="page-eyebrow">Detalhes</span>
          <span className="page-folio">—</span>
        </header>
        <div className="empty-state">
          <div className="ornament">✦ ✦ ✦</div>
          <div>Selecione uma origem à esquerda.</div>
        </div>
      </div>
    );
  }

  const picks       = benefitPicks || [];
  const isSaved     = saved?.id === origin.id;
  const attrBonuses = (origin.benefits || []).filter(b => b.type === "attribute");
  const choosable   = (origin.benefits || []).filter(b => b.type !== "attribute");

  /* pending = primeiro skill_choice selecionado que ainda não foi resolvido */
  const pendingChoice = picks.find(p => p.type === "skill_choice");

  /* resolved picks for statblock */
  const pickedSkills = picks.filter(p => p.type === "skill");
  const pickedPowers = picks.filter(p => p.type === "power");
  /* unresolved skill_choice — shown in statblock as "(a escolher)" */
  const unresolvedChoices = picks.filter(p => p.type === "skill_choice");

  /* toggle a choosable benefit in/out of picks */
  const togglePick = (b) => {
    setBenefitPicks(prev => {
      const idx = prev.findIndex(p =>
        p.type === b.type && p.name === b.name && p.category === b.category
      );
      if (idx >= 0) return prev.filter((_, i) => i !== idx);
      if (prev.length >= 2) return prev;
      return [...prev, b];
    });
  };

  /* resolve a skill_choice pick to a concrete skill name */
  const resolveChoice = (choice, resolvedName) => {
    setBenefitPicks(prev => {
      const idx = prev.findIndex(p =>
        p.type === "skill_choice" && p.name === choice.name && p.category === choice.category
      );
      if (idx < 0) return prev;
      const next = [...prev];
      next[idx] = { type: "skill", name: resolvedName, wasChoice: true };
      return next;
    });
  };

  /* sub-options for the pending sub-picker */
  const subOptions = pendingChoice
    ? pendingChoice.category === "Ofício"
      ? OFICIO_TYPES.map(t => `Ofício (${t})`)
      : T20_SKILL_LIST
    : [];

  return (
    <div className="page-content rc-detail-page">
      <header className="page-header">
        <span className="page-eyebrow">Origem · {origin.source}</span>
        <span className="page-folio">—</span>
      </header>
      <h1 className="page-title">{origin.name}</h1>
      <div className="rc-detail-body">
        <dl className="statblock">
          {attrBonuses.map((b, i) => (
            <div key={i}>
              <dt>{b.name || "Atributo"}</dt>
              <dd><Kw kind="attribute">{b.bonus}</Kw></dd>
            </div>
          ))}
          {(pickedSkills.length > 0 || unresolvedChoices.length > 0) && (
            <div style={{ gridColumn: "1 / -1" }}>
              <dt>Perícias escolhidas</dt>
              <dd>
                {[
                  ...pickedSkills.map(s => s.name),
                  ...unresolvedChoices.map(c =>
                    c.category === "Ofício" ? "Ofício (a escolher)" : "Perícia (a escolher)"
                  ),
                ].join(" · ")}
              </dd>
            </div>
          )}
          {pickedPowers.length > 0 && (
            <div style={{ gridColumn: "1 / -1" }}>
              <dt>Poderes escolhidos</dt>
              <dd>{pickedPowers.map(p => p.name).join(" · ")}</dd>
            </div>
          )}
        </dl>

        {choosable.length > 0 && (
          <div>
            <div className="rc-benefit-picker-label">
              Escolha 2 benefícios ({picks.length}/2)
            </div>
            <div className="rc-benefit-chips">
              {choosable.map((b, i) => {
                const isActive = picks.some(p =>
                  p.type === b.type && p.name === b.name && p.category === b.category
                );
                const isFull = picks.length >= 2 && !isActive;
                const label  = b.type === "skill_choice"
                  ? (b.category === "Ofício" ? "Ofício ▾" : "Perícia ▾")
                  : b.name;
                return (
                  <button
                    key={i}
                    className={"rc-benefit-chip"
                      + (isActive ? " active" : "")
                      + (b.unique ? " unique" : "")
                      + (b.type === "skill_choice" ? " choice" : "")}
                    disabled={isFull}
                    onClick={() => togglePick(b)}
                  >
                    {label}
                  </button>
                );
              })}
            </div>

            {/* Sub-picker — aparece quando um skill_choice está selecionado */}
            {pendingChoice && (
              <div className="rc-sub-picker">
                <div className="rc-sub-picker-label">
                  {pendingChoice.category === "Ofício"
                    ? "Qual ofício?"
                    : "Qual perícia?"}
                </div>
                <div className="rc-sub-picker-chips">
                  {subOptions.map((opt, i) => (
                    <button
                      key={i}
                      className="rc-sub-chip"
                      onClick={() => resolveChoice(pendingChoice, opt)}
                    >
                      {opt}
                    </button>
                  ))}
                </div>
              </div>
            )}
          </div>
        )}

        {origin.items && (
          <div className="rc-origin-items">
            <div className="rc-section-label">Equipamentos iniciais</div>
            <p className="rc-items-text">{origin.items}</p>
          </div>
        )}

        {/* Regra especial: Duplo Feérico exige uma habilidade extra */}
        {isDuploFeerico(origin) && (
          <DuploFeericoPicker
            duploPick={duploPick}
            setDuploPick={setDuploPick}
            savedClassNames={savedClassNames}
          />
        )}

        <div className="divider">❦</div>
        <div className="rc-desc">
          {(origin.description || "").split("\n\n").map((p, i) => (
            <p key={i} style={{ fontSize: 14, lineHeight: 1.65, margin: "0 0 0.7em", color: "var(--ink-0)", textWrap: "pretty" }}>
              <Parsed>{p}</Parsed>
            </p>
          ))}
        </div>
      </div>
      <div className="rc-save-wrap">
        {(() => {
          const needsPicks  = choosable.length > 0 && picks.length < 2;
          const needsDuplo  = isDuploFeerico(origin) && !duploPick?.feature_name;
          const messages = [];
          if (needsPicks) {
            const faltam = 2 - picks.length;
            messages.push(`Escolha ${faltam} benefício${faltam !== 1 ? "s" : ""}`);
          }
          if (needsDuplo) {
            messages.push("Escolha a habilidade duplicada");
          }
          const canSave = !needsPicks && !needsDuplo;
          return (
            <>
              {messages.length > 0 && (
                <div style={{ fontSize: 11, color: "var(--ink-2)", marginBottom: 6, textAlign: "center", letterSpacing: "0.05em" }}>
                  {messages.join(" · ")} antes de salvar
                </div>
              )}
              <button
                className={"rc-save-btn" + (isSaved ? " is-saved" : "")}
                disabled={!canSave && !isSaved}
                style={!canSave && !isSaved ? { opacity: 0.5, cursor: "not-allowed" } : null}
                onClick={() => canSave && !isSaved && onSave(origin)}
              >
                {isSaved ? "✦ Origem selecionada" : "Selecionar esta origem"}
              </button>
            </>
          );
        })()}
      </div>
    </div>
  );
}

/* ============================================================
   ORIGIN CREATOR  (root da aba "origens")
   ============================================================ */
function OriginCreator() {
  const [allOrigins, setAllOrigins] = useState([]);
  const [loading,    setLoading]    = useState(true);
  const [query,      setQuery]      = useState("");
  const [activeSource, setActiveSource] = useState(null);
  const [selected,   setSelected]   = useState(null);
  const [saved,      setSaved]      = useState(() => lsGet(LS_ORIGIN));
  const [benefitPicks, setBenefitPicks] = useState(() => lsGet(LS_ORIGIN)?.picks || []);
  /* escolha extra do Duplo Feérico: { class_name, feature_name } | null */
  const [duploPick, setDuploPick] = useState(() => lsGet(LS_ORIGIN)?.duplo_pick || null);
  const [savedClassNames, setSavedClassNames] = useState(() => getSavedClassNames());

  /* sincroniza classes do personagem se o jogador as trocou em outra aba */
  useEffect(() => {
    const sync = () => setSavedClassNames(getSavedClassNames());
    window.addEventListener("focus", sync);
    return () => window.removeEventListener("focus", sync);
  }, []);

  useEffect(() => {
    window.fetchOrigins().then(data => {
      const sorted = [...data].sort((a, b) => a.name.localeCompare(b.name, "pt-BR"));
      setAllOrigins(sorted);
      setLoading(false);
      const s = lsGet(LS_ORIGIN);
      if (s) setSelected(sorted.find(o => o.id === s.id) || null);
    });
  }, []);

  // When selected origin changes, restore or reset picks + duploPick
  useEffect(() => {
    if (!selected) { setBenefitPicks([]); setDuploPick(null); return; }
    const s = lsGet(LS_ORIGIN);
    if (s && s.id === selected.id) {
      setBenefitPicks(s.picks || []);
      setDuploPick(s.duplo_pick || null);
    } else {
      setBenefitPicks([]);
      setDuploPick(null);
    }
  }, [selected?.id]);


  const sources = useMemo(() => [...new Set(allOrigins.map(o => o.source))].sort(), [allOrigins]);

  const filtered = useMemo(() => {
    let out = allOrigins;
    if (activeSource) out = out.filter(o => o.source === activeSource);
    const q = query.toLowerCase().trim();
    if (q) out = out.filter(o => o.name.toLowerCase().includes(q));
    return out;
  }, [allOrigins, query, activeSource]);

  const handleSave = origin => {
    const val = {
      id: origin.id,
      name: origin.name,
      source: origin.source,
      picks: benefitPicks,
      /* só inclui duplo_pick em origens que exigem (mantém o LS limpo) */
      duplo_pick: isDuploFeerico(origin) ? duploPick : null,
    };
    lsSet(LS_ORIGIN, val);
    setSaved(val);
  };

  return (
    <div className="cc-root">
      <div className="spread-frame">
        <div className="page left">
          <RCCorners/>
          {loading
            ? <div className="page-content"><div className="empty-state"><div className="ornament">·</div><div>Carregando origens…</div></div></div>
            : <OriginList
                origins={filtered}
                total={allOrigins.length}
                selected={selected}
                saved={saved}
                onSelect={setSelected}
                query={query}
                setQuery={setQuery}
                sources={sources}
                activeSource={activeSource}
                onSourceToggle={s => setActiveSource(prev => prev === s ? null : s)}
              />
          }
        </div>
        <div className="page right">
          <RCCorners/>
          <OriginDetail
            origin={selected}
            saved={saved}
            onSave={handleSave}
            benefitPicks={benefitPicks}
            setBenefitPicks={setBenefitPicks}
            duploPick={duploPick}
            setDuploPick={setDuploPick}
            savedClassNames={savedClassNames}
          />
        </div>
      </div>
    </div>
  );
}

window.RaceCreator   = RaceCreator;
window.OriginCreator = OriginCreator;
