<script lang="ts">
  import { onMount } from "svelte";
  import {
    getConfig,
    saveConfig,
    getStatus,
    getGuide,
    detectLogs,
    stepDelta,
    setOverlayLocked,
    toggleOverlay,
    toggleLayout,
    setLayoutSize,
    saveOverlayGeometry,
    getTimer,
    timerStart,
    timerPause,
    timerReset,
    createProfile,
    deleteProfile,
    selectProfile,
    onStatus,
    onStep,
    onConfig,
    onGuideReload,
    onTimer,
    fmtTime,
    type Config,
    type Status,
    type GuideData,
    type RunTimer,
  } from "$lib/api";

  let config = $state<Config | null>(null);
  let status = $state<Status | null>(null);
  let guide = $state<GuideData | null>(null);
  let timer = $state<RunTimer | null>(null);
  let detected = $state<string[]>([]);
  let overlayUnlocked = $state(false);

  // --- character profiles ---
  let newProfileName = $state("");
  let newProfileLeagueStart = $state(true);

  async function refreshDetect() {
    detected = await detectLogs();
  }

  async function addProfile() {
    const name = newProfileName.trim();
    if (!name) return;
    await createProfile(name, newProfileLeagueStart);
    newProfileName = "";
    // config (profiles + active_character) is pushed back via config://update
  }

  async function save() {
    if (config) await saveConfig($state.snapshot(config));
  }

  async function toggleLock() {
    overlayUnlocked = !overlayUnlocked;
    await setOverlayLocked(!overlayUnlocked); // locked = click-through
    if (!overlayUnlocked) await saveOverlayGeometry();
    if (overlayUnlocked) config = await getConfig();
  }

  onMount(() => {
    const unlisten: Array<() => void> = [];
    (async () => {
      config = await getConfig();
      status = await getStatus();
      guide = await getGuide();
      timer = await getTimer();
      await refreshDetect();
      unlisten.push(await onStatus((s) => (status = s)));
      unlisten.push(
        await onStep((i) => {
          if (config) config = { ...config, current_step: i };
        }),
      );
      unlisten.push(await onConfig((c) => (config = c)));
      unlisten.push(await onGuideReload(async () => (guide = await getGuide())));
      unlisten.push(await onTimer((t) => (timer = t)));
    })();
    return () => unlisten.forEach((u) => u());
  });
</script>

<main>
  <h1>Exile UI <small>· Act-Tracker (PoE2)</small></h1>

  {#if status}
    <section class="status">
      <div><b>{status.character || "—"}</b> ({status.class || "?"}) · Lv {status.level || "?"}</div>
      <div>
        Zone : <span class="hl">{status.area_name || status.area_id || "—"}</span>
        {#if status.area_level}· niveau zone {status.area_level}{/if}
      </div>
      <div class="muted">
        Jeu focus : {status.game_focused ? "✔️" : "✖️"} · areaID : {status.area_id || "—"}
      </div>
    </section>
  {/if}

  {#if config && guide}
    <section>
      <h2>Guide</h2>
      <div class="row">
        <button onclick={() => stepDelta(-1)}>◀ Précédent</button>
        <span class="prog">Étape {config.current_step + 1} / {guide.steps.length}</span>
        <button onclick={() => stepDelta(1)}>Suivant ▶</button>
      </div>
      <div class="row">
        <button onclick={() => toggleOverlay()}>Afficher/Masquer overlay</button>
        <button onclick={toggleLock}>
          {overlayUnlocked ? "🔒 Verrouiller (click-through)" : "🔓 Déverrouiller (déplacer)"}
        </button>
      </div>
      {#if overlayUnlocked}
        <p class="muted">Overlay déverrouillé : déplace/redimensionne la fenêtre, puis reverrouille pour sauvegarder.</p>
      {/if}
    </section>

    <section>
      <h2>Profils <small>· un profil = un personnage</small></h2>
      <p class="muted">
        Crée un profil par personnage (le nom doit correspondre au nom du perso
        en jeu). La progression du guide est mémorisée <b>par profil</b>, et le
        profil devient actif tout seul quand le log détecte ce personnage.
      </p>

      <div class="status">
        Profil actif :
        <span class="hl">{config.active_character || "— aucun —"}</span>
        {#if status?.character && status.character !== config.active_character}
          · perso en jeu : <span class="hl">{status.character}</span>
          {#if !config.profiles.some((p) => p.name === status?.character)}
            <span class="muted">(pas de profil)</span>
          {/if}
        {/if}
      </div>

      {#if config.profiles.length}
        <div class="char-list">
          {#each config.profiles as p}
            <div class="char" class:active={config.active_character === p.name}>
              <button class="char-pick" onclick={() => selectProfile(p.name)}>
                <b>{p.name}</b>
                <span class="muted">
                  étape {p.current_step + 1} · {p.league_start ? "league-start" : "standard"}
                </span>
              </button>
              <button class="del" title="Supprimer ce profil" onclick={() => deleteProfile(p.name)}>✕</button>
            </div>
          {/each}
        </div>
      {:else}
        <p class="muted">Aucun profil pour l'instant.</p>
      {/if}

      <div class="row">
        <input
          type="text"
          bind:value={newProfileName}
          placeholder="nom du personnage"
          style="flex:1"
          onkeydown={(e) => e.key === "Enter" && addProfile()}
        />
        <label class="ck" style="white-space:nowrap">
          <input type="checkbox" bind:checked={newProfileLeagueStart} />
          league-start
        </label>
        <button onclick={addProfile} disabled={!newProfileName.trim()}>+ Créer</button>
      </div>
    </section>

    <section>
      <h2>Layouts de zones <small>· identificateur de layout (PoE2)</small></h2>
      <p class="muted">
        Ouvre une fenêtre interactive affichant les layouts possibles de la zone
        courante. Clique celui qui correspond à ce que tu vois pour l'affiner, et
        pivote/miroir l'image pour l'aligner sur l'orientation en jeu (chaque
        instance de zone est tournée aléatoirement).
      </p>
      <label class="ck">
        <input type="checkbox" bind:checked={config.feature_layouts} onchange={save} />
        Activer le viewer de layouts
      </label>
      {#if config.feature_layouts}
        <div class="row">
          <button onclick={() => toggleLayout()}>Afficher / masquer la fenêtre layouts</button>
        </div>
        <div class="grid">
          <label>Hotkey « layouts »
            <input type="text" bind:value={config.hotkey_layout} onchange={save} />
          </label>
          <label>Largeur fenêtre (px)
            <input
              type="number"
              min="240"
              max="2000"
              bind:value={config.layout_w}
              onchange={() => { save(); if (config) setLayoutSize(config.layout_w, config.layout_h); }}
            />
          </label>
          <label>Hauteur fenêtre (px)
            <input
              type="number"
              min="200"
              max="2000"
              bind:value={config.layout_h}
              onchange={() => { save(); if (config) setLayoutSize(config.layout_w, config.layout_h); }}
            />
          </label>
        </div>
        <p class="muted">
          La fenêtre est interactive (elle prend le focus). Si KWin ne la garde pas
          au-dessus du jeu, ajoute une règle de fenêtre pour « Exile UI Layouts ».
        </p>
      {/if}
    </section>

    <section>
      <h2>Timer de campagne</h2>
      <label class="ck">
        <input type="checkbox" bind:checked={config.timer_enabled} onchange={save} />
        Activer le timer
      </label>
      <label class="ck">
        <input type="checkbox" bind:checked={config.timer_pause_in_town} onchange={save} />
        Mettre en pause automatiquement en ville / hideout
      </label>
      <label class="ck">
        <input type="checkbox" bind:checked={config.timer_afk_enabled} onchange={save} />
        Anti-AFK : mettre en pause si la souris ne bouge plus
      </label>
      {#if config.timer_afk_enabled}
        <label>Délai avant pause AFK (secondes)
          <input type="number" min="10" bind:value={config.timer_afk_seconds} onchange={save} />
        </label>
      {/if}
      <label class="ck">
        <input type="checkbox" bind:checked={config.timer_pause_unfocused} onchange={save} />
        Mettre en pause quand PoE2 n'a pas le focus (alt-tab)
      </label>
      {#if config.timer_enabled}
        {#if timer && timer.active}
          <div class="status timer-box">
            <div>
              Total : <b class="hl">{fmtTime(timer.total_seconds + timer.act_seconds)}</b>
              · acte {timer.current_act} : {fmtTime(timer.act_seconds)}
              {#if timer.finished}<span class="flag done">terminé</span>
              {:else if timer.manual_pause}<span class="flag">en pause</span>
              {:else if timer.afk_paused}<span class="flag">{status?.game_focused ? "AFK" : "fenêtre (pas de focus)"}</span>
              {:else if timer.auto_paused}<span class="flag">pause auto (ville)</span>{/if}
            </div>
            {#if timer.run_name}<div class="muted">Run : {timer.run_name}</div>{/if}
            {#if timer.splits.some((s) => s > 0)}
              <div class="splits">
                {#each timer.splits as s, i}
                  {#if s > 0}<span class="split">A{i}: {fmtTime(s)}</span>{/if}
                {/each}
              </div>
            {/if}
          </div>
        {:else}
          <p class="muted">Aucun run en cours. Le timer démarre tout seul en entrant dans la première zone de campagne, ou via « Démarrer ».</p>
        {/if}
        <div class="row">
          <button onclick={() => timerStart()}>▶ Démarrer / redémarrer</button>
          <button onclick={() => timerPause()} disabled={!timer || !timer.active}>
            {timer && timer.manual_pause ? "Reprendre" : "⏸ Pause"}
          </button>
          <button onclick={() => timerReset()} disabled={!timer || !timer.active}>↺ Reset</button>
        </div>
        <label>Hotkey « pause timer »
          <input type="text" bind:value={config.hotkey_timer_pause} onchange={save} />
        </label>
      {/if}
    </section>

    <section>
      <h2>Fichier de log (Client.txt)</h2>
      <div class="row">
        <input
          type="text"
          bind:value={config.log_path}
          placeholder="/chemin/vers/Path of Exile 2/logs/Client.txt"
          style="flex:1"
        />
        <button onclick={save}>Enregistrer</button>
      </div>
      {#if detected.length}
        <label>Détectés :
          <select onchange={(e) => { if (config) { config.log_path = (e.target as HTMLSelectElement).value; save(); } }}>
            <option value="">— choisir —</option>
            {#each detected as d}<option value={d}>{d}</option>{/each}
          </select>
        </label>
      {:else}
        <p class="muted">Aucun log détecté automatiquement. Renseigne le chemin manuellement.</p>
      {/if}
      <button onclick={refreshDetect}>Re-scanner</button>
    </section>

    <section>
      <h2>Réglages</h2>
      <label class="ck">
        <input type="checkbox" bind:checked={config.overlay_only_when_focused} onchange={save} />
        Afficher l'overlay uniquement quand le jeu est au premier plan
      </label>
      <label class="ck">
        <input type="checkbox" bind:checked={config.league_start} onchange={save} />
        Mode « league-start » (profil) — sinon branche non-league-start du guide
      </label>
      <label class="ck">
        <input type="checkbox" bind:checked={config.show_optionals} onchange={save} />
        Afficher le contenu optionnel (profil) — loot/quêtes/rencontres « + »
      </label>
      <label class="ck">
        <input type="checkbox" bind:checked={config.show_recommendation} onchange={save} />
        Afficher les niveaux recommandés par zone
      </label>
      <label>Titre fenêtre du jeu (détection focus)
        <input type="text" bind:value={config.poe_window_match} onchange={save} />
      </label>
      <div class="grid">
        <label>Largeur overlay (px)
          <input type="number" bind:value={config.overlay_width} onchange={save} />
        </label>
        <label>Taille police (px)
          <input type="number" bind:value={config.overlay_font_size} onchange={save} />
        </label>
        <label>Étapes à anticiper
          <input type="number" min="0" max="6" bind:value={config.lookahead} onchange={save} />
        </label>
      </div>
      <div class="grid">
        <label>Hotkey « suivant »
          <input type="text" bind:value={config.hotkey_next} onchange={save} />
        </label>
        <label>Hotkey « précédent »
          <input type="text" bind:value={config.hotkey_prev} onchange={save} />
        </label>
        <label>Hotkey « afficher/masquer »
          <input type="text" bind:value={config.hotkey_toggle} onchange={save} />
        </label>
      </div>
      <p class="muted">Format hotkey : ex. <code>Alt+X</code>, <code>Control+Shift+G</code>, <code>F8</code>.</p>
    </section>
  {/if}
</main>

<style>
  main {
    background: var(--bg);
    min-height: 100vh;
    padding: 16px 22px;
    max-width: 760px;
  }
  h1 {
    margin: 0 0 12px;
    font-size: 1.4em;
    color: var(--accent);
  }
  h1 small {
    color: var(--muted);
    font-size: 0.6em;
  }
  h2 {
    font-size: 1.05em;
    color: var(--accent2);
    border-bottom: 1px solid var(--border);
    padding-bottom: 4px;
  }
  section {
    margin-bottom: 18px;
  }
  .status {
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 10px 14px;
    line-height: 1.6;
  }
  .hl {
    color: var(--accent2);
  }
  .muted {
    color: var(--muted);
    font-size: 0.9em;
  }
  .row {
    display: flex;
    gap: 8px;
    align-items: center;
    margin: 6px 0;
  }
  .grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 8px;
    margin: 6px 0;
  }
  label {
    display: block;
    margin: 6px 0;
    font-size: 0.92em;
  }
  label.ck {
    display: flex;
    gap: 6px;
    align-items: center;
  }
  input[type="text"],
  input[type="number"],
  select {
    width: 100%;
    background: #100d09;
    color: var(--text);
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 5px 7px;
  }
  label.ck input {
    width: auto;
  }
  button {
    background: #2a2218;
    color: var(--text);
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 6px 12px;
    cursor: pointer;
  }
  button:hover {
    border-color: var(--accent);
  }
  .prog {
    color: var(--muted);
  }
  .timer-box {
    margin: 8px 0;
  }
  .splits {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 6px;
  }
  .split {
    background: #100d09;
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 1px 6px;
    font-size: 0.85em;
  }
  .flag {
    margin-left: 8px;
    color: #e0c84a;
    text-transform: uppercase;
    font-size: 0.85em;
  }
  .flag.done {
    color: #7cfc00;
  }
  button:disabled {
    opacity: 0.45;
    cursor: default;
  }
  code {
    background: #100d09;
    padding: 1px 4px;
    border-radius: 3px;
  }
  .char-list {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin: 8px 0;
  }
  .char {
    display: flex;
    align-items: stretch;
    gap: 4px;
  }
  .char.active .char-pick {
    border-color: var(--accent);
    background: rgba(200, 162, 74, 0.12);
  }
  button.char-pick {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex: 1;
    text-align: left;
    gap: 10px;
  }
  button.del {
    color: #e05555;
    padding: 6px 10px;
  }
</style>
