(function () {
  'use strict';

  const TAB_SECTION_MAP = {
    library:      's-voices',
    source:       's-clone',
    save:         's-clone',
    design:       's-design',
    custom:       's-design',
    getvoices:    's-studio',
    generation:   's-tryout',
    'stt-tts':    's-tryout',
    performance:  's-performance',
    routing:      's-routing',
    integrations: 's-connect',
    howto:        's-connect',
    settings:     's-settings',
    llms:         's-llms'
  };

  const SECTIONS = ['s-voices', 's-clone', 's-design', 's-studio', 's-tryout', 's-rehearser', 's-reader', 's-performance', 's-routing', 's-connect', 's-settings', 's-llms', 's-conversation', 's-characters'];

  function storedSection() {
    try { return localStorage.getItem('ttsvc_section') || ''; } catch (_) { return ''; }
  }

  function setStoredSection(sectionId) {
    try { localStorage.setItem('ttsvc_section', sectionId); } catch (_) {}
  }

  function hashSection() {
    var raw = String(location.hash || '').replace(/^#/, '').trim();
    if (!raw) return '';
    if (raw.indexOf('section=') === 0) raw = raw.slice(8);
    raw = decodeURIComponent(raw).replace(/^\/?/, '');
    return SECTIONS.includes(raw) ? raw : '';
  }

  function setSectionHash(sectionId) {
    if (!SECTIONS.includes(sectionId)) return;
    var next = '#' + encodeURIComponent(sectionId);
    if (location.hash === next) return;
    try { history.replaceState(null, '', location.pathname + location.search + next); }
    catch (_) { location.hash = next; }
  }

  function runSideEffects(name) {
    if ((name === 'source' || name === 'save') && typeof initCloneSampleText === 'function') initCloneSampleText();
    if (name === 'library' && typeof loadVoiceLibrary === 'function') loadVoiceLibrary();
    if ((name === 'integrations' || name === 'howto') && typeof renderIntegrationSnippets === 'function') {
      if (typeof loadVoiceLibrary === 'function' && !(window._voices && window._voices.length)) loadVoiceLibrary();
      renderIntegrationSnippets();
    }
    if (name === 'routing' && typeof loadRoutingTab === 'function') loadRoutingTab();
    if (name === 'getvoices' && typeof loadGetVoices === 'function') loadGetVoices();
  }

  function applySettingsPage(cat) {
    document.querySelectorAll('.s-settings-page').forEach(function (p) {
      p.classList.toggle('is-active', p.dataset.page === cat);
    });
    document.querySelectorAll('[data-settings-cat]').forEach(function (el) {
      el.classList.toggle('is-active', el.dataset.settingsCat === cat);
    });
  }

  // ── Tree open/close state — each tree is independent ─────────────────────
  // Load persisted open state (default: open voices + the active section's tree)
  var _treeOpen = {};
  try { _treeOpen = JSON.parse(localStorage.getItem('ttsvc_trees') || '{}'); } catch(_) {}

  var TREES = [
    { tree: 'nav-voices-tree',    chevron: 'nav-voices-chevron',    section: 's-voices'    },
    { tree: 'nav-engines-tree',   chevron: 'nav-engines-chevron',   section: 's-llms'      },
    { tree: 'nav-settings-tree',  chevron: 'nav-settings-chevron',  section: 's-settings'  },
    { tree: 'nav-rehearser-tree', chevron: 'nav-rehearser-chevron', section: 's-rehearser' },
    { tree: 'nav-reader-tree',    chevron: 'nav-reader-chevron',    section: 's-reader'    },
  ];

  function _applyTreeStates() {
    TREES.forEach(function (t) {
      var open = !!_treeOpen[t.tree];
      var treeEl = document.getElementById(t.tree);
      var chevEl = document.getElementById(t.chevron);
      if (treeEl)    treeEl.classList.toggle('open', open);
      if (chevEl)    chevEl.classList.toggle('open', open);
    });
  }

  window.toggleNavTree = function (treeId, chevronId) {
    _treeOpen[treeId] = !_treeOpen[treeId];
    localStorage.setItem('ttsvc_trees', JSON.stringify(_treeOpen));
    _applyTreeStates();
  };

  function showSection(sectionId) {
    if (!SECTIONS.includes(sectionId)) sectionId = 's-voices';
    // Leaving the Read Aloud reader: stop playback so audio doesn't keep running
    if (sectionId !== 's-reader' && typeof window.readerStop === 'function') window.readerStop();
    if (sectionId === 's-reader' && typeof window.readerOnShow === 'function') window.readerOnShow();
    if (sectionId === 's-characters' && typeof window.clRender === 'function') window.clRender();
    setStoredSection(sectionId);
    setSectionHash(sectionId);
    SECTIONS.forEach(function (id) {
      var el = document.getElementById(id);
      if (el) el.classList.toggle('is-active', id === sectionId);
    });
    document.querySelectorAll('[data-nav-section]').forEach(function (item) {
      item.classList.toggle('active', item.dataset.navSection === sectionId);
    });

    // Navigating to a section auto-opens its tree (but never closes others)
    TREES.forEach(function (t) {
      if (t.section === sectionId && !_treeOpen[t.tree]) {
        _treeOpen[t.tree] = true;
        localStorage.setItem('ttsvc_trees', JSON.stringify(_treeOpen));
      }
    });
    _applyTreeStates();

    // When entering settings, show the active sub-page (default: connections)
    if (sectionId === 's-settings') {
      applySettingsPage(window._settingsSidebarCat || 'connections');
    }

    // When entering engines, show the active sub-page (default: llm)
    if (sectionId === 's-llms') {
      applyEnginesPage(window._enginesSidebarCat || 'llm');
    }

    var main = document.getElementById('main-content');
    if (main) main.scrollTop = 0;
  }

  window.navTo = function (sectionId) {
    showSection(sectionId);
    var tabName = Object.keys(TAB_SECTION_MAP).find(function (k) {
      return TAB_SECTION_MAP[k] === sectionId;
    });
    if (tabName) runSideEffects(tabName);
  };

  window.switchTab = function (name) {
    var sectionId = TAB_SECTION_MAP[name];
    if (sectionId) showSection(sectionId);
    runSideEffects(name);
    return true;
  };

  // ── Voice tree sub-navigation ─────────────────────────────────────────────
  window._voiceSidebarCat = 'all';

  window._voiceTagFilter = '';

  window.navVoicesCat = function (cat) {
    navTo('s-voices');
    window._voiceSidebarCat = cat;
    window._voiceTagFilter = '';   // a fixed category clears any tag subfolder filter
    document.querySelectorAll('[data-voice-cat]').forEach(function (el) {
      el.classList.toggle('is-active', el.dataset.voiceCat === cat);
    });
    document.querySelectorAll('[data-voice-tag]').forEach(function (el) { el.classList.remove('is-active'); });
    if (typeof renderVoiceList === 'function') renderVoiceList();
  };

  // Click a tag "subfolder" in the My Voices tree → filter the list to that tag.
  window.navVoicesTag = function (tag) {
    navTo('s-voices');
    window._voiceTagFilter = (window._voiceTagFilter === tag) ? '' : tag;  // toggle off if re-clicked
    window._voiceSidebarCat = 'all';
    document.querySelectorAll('[data-voice-cat]').forEach(function (el) {
      el.classList.toggle('is-active', el.dataset.voiceCat === 'all' && !window._voiceTagFilter);
    });
    document.querySelectorAll('[data-voice-tag]').forEach(function (el) {
      el.classList.toggle('is-active', el.dataset.voiceTag === window._voiceTagFilter);
    });
    if (typeof renderVoiceList === 'function') renderVoiceList();
  };

  window.updateVoiceTree = function (voices) {
    if (!voices) return;
    function n(fn) { return voices.filter(fn).length; }
    function set(id, v) { var el = document.getElementById(id); if (el) el.textContent = v || ''; }
    set('ntc-all',      n(function () { return true; }));
    set('ntc-cloned',   n(function (v) { return v.has_ref; }));
    set('ntc-designed', n(function (v) { return !v.has_ref; }));
    set('ntc-favorites',n(function (v) { return (v.rating || 0) >= 4; }));
    set('ntc-hidden',   n(function (v) { return v.enabled === false; }));
    set('nav-voices-count', voices.length);

    // ── Virtual tag "subfolders" under the fixed categories ──────────────────
    var tree = document.getElementById('nav-voices-tree');
    if (!tree) return;
    tree.querySelectorAll('.nav-tree-tag').forEach(function (e) { e.remove(); });
    var counts = {};
    voices.forEach(function (v) {
      String(v.tag || '').split(',').map(function (t) { return t.trim(); }).filter(Boolean)
        .forEach(function (t) { counts[t] = (counts[t] || 0) + 1; });
    });
    var names = Object.keys(counts).sort(function (a, b) { return a.toLowerCase().localeCompare(b.toLowerCase()); });
    if (!names.length) return;
    var lbl = document.createElement('div');
    lbl.className = 'nav-tree-tag nav-tree-tag-label';
    lbl.textContent = 'Tags';
    tree.appendChild(lbl);
    names.forEach(function (tag) {
      var el = document.createElement('div');
      el.className = 'nav-tree-item nav-tree-tag' + (window._voiceTagFilter === tag ? ' is-active' : '');
      el.dataset.voiceTag = tag;
      var icon = document.createElement('span'); icon.className = 'mdi mdi-tag-outline'; el.appendChild(icon);
      el.appendChild(document.createTextNode(' ' + tag + ' '));
      var c = document.createElement('span'); c.className = 'ntc'; c.textContent = counts[tag]; el.appendChild(c);
      el.addEventListener('click', function () { window.navVoicesTag(tag); });
      tree.appendChild(el);
    });
  };

  // ── Settings tree sub-navigation ──────────────────────────────────────────
  window._settingsSidebarCat = 'connections';

  window.navSettingsCat = function (cat) {
    window._settingsSidebarCat = cat;
    localStorage.setItem('ttsvc_settings_cat', cat);
    navTo('s-settings');   // showSection will call applySettingsPage(cat)
    if (cat === 'logs' && typeof loadSettingsLogs === 'function') loadSettingsLogs();
    if (cat === 'about' && typeof renderSettingsAbout === 'function') renderSettingsAbout();
  };

  // ── Engines tree sub-navigation ───────────────────────────────────────────
  function applyEnginesPage(cat) {
    document.querySelectorAll('.s-engines-page').forEach(function (p) {
      p.classList.toggle('is-active', p.dataset.page === cat);
    });
    document.querySelectorAll('[data-engines-cat]').forEach(function (el) {
      el.classList.toggle('is-active', el.dataset.enginesCat === cat);
    });
  }

  window._enginesSidebarCat = 'llm';

  window.navEnginesCat = function (cat) {
    window._enginesSidebarCat = cat;
    localStorage.setItem('ttsvc_engines_cat', cat);
    navTo('s-llms');   // showSection will call applyEnginesPage(cat)
    if ((cat === 'tts' || cat === 'stt') && typeof loadLocalContainers === 'function') loadLocalContainers();
  };

  // ── Rehearser tree sub-navigation ────────────────────────────────────────
  window.navRehearserImpEx = function () {
    navTo('s-rehearser');
    // Clear phase highlights — Import/Export is its own panel, not a numbered phase
    document.querySelectorAll('[data-rehearser-phase]').forEach(function (el) {
      el.classList.remove('is-active');
    });
    document.getElementById('nav-reh-impex')?.classList.add('is-active');
    if (typeof showRehImpEx === 'function') showRehImpEx();
    else window._rehearserStartImpEx = true;
  };

  window.navRehearserPhase = function (phase) {
    navTo('s-rehearser');
    // highlight the correct tree item immediately
    document.querySelectorAll('[data-rehearser-phase]').forEach(function (el) {
      el.classList.toggle('is-active', Number(el.dataset.rehearserPhase) === phase);
    });
    // delegate to rehearser's own showPhase() when it's ready
    if (typeof showPhase === 'function') {
      showPhase(phase);
    } else {
      // rehearser.js not yet loaded — store the intent and let init pick it up
      window._rehearserStartPhase = phase;
    }
  };

  // Keep sidebar tree in sync when rehearser changes phase internally
  window.onRehearserPhaseChange = function (phase) {
    document.querySelectorAll('[data-rehearser-phase]').forEach(function (el) {
      el.classList.toggle('is-active', Number(el.dataset.rehearserPhase) === phase);
    });
  };

  // ── Reader tree sub-navigation ───────────────────────────────────────────
  window.navReaderView = function (view) {
    navTo('s-reader');
    document.querySelectorAll('[data-reader-view]').forEach(function (el) {
      el.classList.toggle('is-active', el.dataset.readerView === view);
    });
    if (typeof showReaderView === 'function') {
      showReaderView(view);
    } else {
      window._readerStartView = view;
    }
  };

  // Restore last-used section from hash/localStorage (fallback: My Voices)
  var _savedSection = storedSection();
  // On very first visit, default voices tree open
  if (!localStorage.getItem('ttsvc_trees')) {
    _treeOpen['nav-voices-tree'] = true;
  }
  window._settingsSidebarCat = localStorage.getItem('ttsvc_settings_cat') || 'connections';
  window._enginesSidebarCat  = localStorage.getItem('ttsvc_engines_cat')  || 'llm';
  var _startSection = hashSection() || ((_savedSection && SECTIONS.includes(_savedSection)) ? _savedSection : 's-voices');
  showSection(_startSection);

  window.addEventListener('hashchange', function () {
    var section = hashSection();
    if (section && section !== storedSection()) showSection(section);
  });
  var _startTab = Object.keys(TAB_SECTION_MAP).find(function (k) { return TAB_SECTION_MAP[k] === _startSection; }) || 'library';
  runSideEffects(_startTab);

  // ── Mobile sidebar drawer ────────────────────────────────────────────────
  var sidebar   = document.getElementById('sidebar');
  var backdrop  = document.getElementById('sidebar-backdrop');
  var toggleBtn = document.getElementById('sidebar-toggle');

  function openSidebar() {
    if (!sidebar) return;
    sidebar.classList.add('open');
    if (backdrop) backdrop.classList.add('open');
    document.body.style.overflow = 'hidden'; // prevent scroll behind drawer
  }
  function closeSidebar() {
    if (!sidebar) return;
    sidebar.classList.remove('open');
    if (backdrop) backdrop.classList.remove('open');
    document.body.style.overflow = '';
  }

  if (toggleBtn) toggleBtn.addEventListener('click', openSidebar);
  if (backdrop)  backdrop.addEventListener('click', closeSidebar);

  // Close drawer when a nav item is tapped on mobile
  document.querySelectorAll('#sidebar .nav-item, #sidebar .nav-tree-item').forEach(function (el) {
    el.addEventListener('click', function () {
      if (window.innerWidth <= 767) closeSidebar();
    });
  });

  // ── Mobile voice inspector: back button ──────────────────────────────────
  // When a voice row is selected on mobile, show inspector full-height.
  // The inspector JS will call window.onMobileInspectorOpen/Close as hooks.
  window.onMobileInspectorOpen = function () {
    var wb = document.querySelector('.voices-workbench');
    if (!wb || window.innerWidth > 767) return;
    wb.classList.add('mobile-inspector-open');
    // Inject back button if not already there
    var insp = document.getElementById('voices-inspector');
    if (insp && !insp.querySelector('.insp-mobile-back')) {
      var back = document.createElement('div');
      back.className = 'insp-mobile-back';
      back.innerHTML = '<span class="mdi mdi-arrow-left"></span> All voices';
      back.addEventListener('click', function () { window.onMobileInspectorClose && window.onMobileInspectorClose(); });
      insp.insertBefore(back, insp.firstChild);
    }
  };
  window.onMobileInspectorClose = function () {
    var wb = document.querySelector('.voices-workbench');
    if (wb) wb.classList.remove('mobile-inspector-open');
    var back = document.querySelector('.insp-mobile-back');
    if (back) back.remove();
  };
})();
