// Multi-instance UI — the "New instance" flow for multi-instance-capable apps.
//
// An instance is just another app (slug <type>_<id>), so once created it flows
// through the existing grid / detail / config / routing / backups pages with no
// special-casing. This file only owns the *creation* affordance: a small modal
// that collects a name + domain + subdomain and dispatches the standard task
// (libreportal instance create …) through the same task pipeline as install.
//
// Capability + instance-of are read straight off app.config (the apps.json
// generator already emits every CFG_<SLUG>_* var), so the grid stays declarative.

class InstanceManager {
  constructor() {
    this.domains = [];
  }

  // Read configured domains (CFG_DOMAIN_1..9) from the generated system config.
  async _loadDomains() {
    try {
      const r = await fetch('/data/config/generated/configs.json', { cache: 'no-store' });
      if (!r.ok) return [];
      const data = await r.json();
      const cfg = data.config || {};
      const out = [];
      for (let i = 1; i <= 9; i++) {
        const k = `CFG_DOMAIN_${i}`;
        const v = ((cfg[k] && cfg[k].value !== undefined ? cfg[k].value : cfg[k]) || '').toString().trim();
        if (v) out.push({ number: i, domain: v });
      }
      return out;
    } catch (_) {
      return [];
    }
  }

  // The type's display title, for the modal heading.
  _typeTitle(typeSlug) {
    const a = (window.apps || []).find(x => (x.command || '').split(' ').pop() === typeSlug);
    return a ? (a.name || typeSlug).split(' - ')[0].trim() : typeSlug;
  }

  // user text -> [a-z0-9] id (mirrors the backend's instanceIdPart)
  _idPart(raw) {
    return String(raw || '').toLowerCase().replace(/[^a-z0-9]/g, '');
  }

  _esc(s) {
    return String(s == null ? '' : s).replace(/[&<>"']/g, c => (
      { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[c]
    ));
  }

  close() {
    const el = document.getElementById('lp-instance-modal');
    if (el) el.remove();
    document.removeEventListener('keydown', this._onKey);
  }

  async openCreateModal(typeSlug) {
    if (document.getElementById('lp-instance-modal')) return;
    const title = this._typeTitle(typeSlug);
    this.domains = await this._loadDomains();

    const domainOptions = this.domains.length
      ? this.domains.map(d => `<option value="${d.number}">${this._esc(d.domain)}</option>`).join('')
      : '<option value="1">Domain 1 (set one in Admin → Config)</option>';

    const overlay = document.createElement('div');
    overlay.id = 'lp-instance-modal';
    overlay.className = 'lp-instance-overlay';
    overlay.innerHTML = `
      <div class="lp-instance-modal" role="dialog" aria-modal="true" aria-label="New ${this._esc(title)} instance">
        <div class="lp-instance-head">
          <h3>New ${this._esc(title)} instance</h3>
          <button type="button" class="lp-instance-x" aria-label="Close">&times;</button>
        </div>
        <p class="lp-instance-sub">A fully isolated second copy — its own data, database, subdomain, backups and update cadence.</p>

        <label class="lp-instance-field">
          <span>Instance name</span>
          <input type="text" id="lp-instance-name" placeholder="e.g. blog" autocomplete="off" spellcheck="false" />
          <small id="lp-instance-slug" class="lp-instance-hint"></small>
        </label>

        <div class="lp-instance-row">
          <label class="lp-instance-field">
            <span>Domain</span>
            <select id="lp-instance-domain" class="form-control">${domainOptions}</select>
          </label>
          <label class="lp-instance-field">
            <span>Subdomain</span>
            <input type="text" id="lp-instance-subdomain" placeholder="auto" autocomplete="off" spellcheck="false" />
          </label>
        </div>

        <div class="lp-instance-preview">
          Will be served at <code id="lp-instance-host">…</code>
        </div>

        <div class="lp-instance-actions">
          <button type="button" class="lp-instance-btn lp-instance-cancel">Cancel</button>
          <button type="button" class="lp-instance-btn lp-instance-create" disabled>Create instance</button>
        </div>
      </div>`;

    document.body.appendChild(overlay);

    const nameEl = overlay.querySelector('#lp-instance-name');
    const slugEl = overlay.querySelector('#lp-instance-slug');
    const subEl = overlay.querySelector('#lp-instance-subdomain');
    const domEl = overlay.querySelector('#lp-instance-domain');
    const hostEl = overlay.querySelector('#lp-instance-host');
    const createBtn = overlay.querySelector('.lp-instance-create');

    let subEdited = false;
    subEl.addEventListener('input', () => { subEdited = true; });

    const refresh = () => {
      const id = this._idPart(nameEl.value);
      const slug = id ? `${typeSlug}_${id}` : '';
      slugEl.textContent = slug ? `Created as ${slug}` : 'Letters and numbers only';
      if (!subEdited) subEl.value = slug ? slug.replace(/_/g, '-') : '';
      const dom = (this.domains.find(d => String(d.number) === domEl.value) || {}).domain || '<your-domain>';
      const sub = (subEl.value || '').trim();
      hostEl.textContent = sub ? `${sub}.${dom}` : `…`;
      createBtn.disabled = !id;
    };
    nameEl.addEventListener('input', refresh);
    domEl.addEventListener('change', refresh);
    subEl.addEventListener('input', refresh);
    refresh();
    setTimeout(() => nameEl.focus(), 30);

    this._onKey = (e) => { if (e.key === 'Escape') this.close(); };
    document.addEventListener('keydown', this._onKey);
    overlay.querySelector('.lp-instance-x').addEventListener('click', () => this.close());
    overlay.querySelector('.lp-instance-cancel').addEventListener('click', () => this.close());
    overlay.addEventListener('click', (e) => { if (e.target === overlay) this.close(); });

    createBtn.addEventListener('click', () => this._submit(typeSlug, nameEl.value, domEl.value, subEl.value));
  }

  async _submit(typeSlug, name, domainIndex, subdomain) {
    const id = this._idPart(name);
    if (!id) return;
    const slug = `${typeSlug}_${id}`;

    // Ensure the task system is up (same on-demand load path install uses).
    if ((!window.tasksManager || !window.tasksManager.router) && window.appsManager && window.appsManager.loadTaskSystem) {
      try { await window.appsManager.loadTaskSystem(); } catch (_) {}
    }

    const notify = (msg, kind) => {
      const sys = (typeof window.ensureNotificationSystem === 'function')
        ? window.ensureNotificationSystem() : window.notificationSystem;
      if (sys && typeof sys.show === 'function') sys.show(msg, kind || 'info');
    };

    if (!window.tasksManager || !window.tasksManager.router) {
      notify('Task system unavailable — could not start instance creation.', 'error');
      return;
    }

    try {
      await window.tasksManager.router.routeAction('instance_create', {
        type: typeSlug,
        name: name,
        domainIndex: domainIndex,
        subdomain: subdomain
      });
      this.close();
      notify(`Creating instance ${slug} — track progress in Tasks.`, 'success');
      if (window.librePortalSPA && window.librePortalSPA.navigateTo) {
        window.librePortalSPA.navigateTo('/tasks');
      } else if (window.navigateToRoute) {
        window.navigateToRoute('tasks');
      } else {
        window.location.href = '/tasks';
      }
    } catch (error) {
      notify(`Failed to create instance: ${error.message}`, 'error');
    }
  }

  // Confirm + remove a single instance. typeSlug is where we land afterwards
  // (the instance's own page is going away).
  confirmRemove(slug, typeSlug) {
    if (document.getElementById('lp-instance-modal')) return;
    const overlay = document.createElement('div');
    overlay.id = 'lp-instance-modal';
    overlay.className = 'lp-instance-overlay';
    overlay.innerHTML = `
      <div class="lp-instance-modal" role="dialog" aria-modal="true" aria-label="Remove instance">
        <div class="lp-instance-head">
          <h3>Remove instance</h3>
          <button type="button" class="lp-instance-x" aria-label="Close">&times;</button>
        </div>
        <p class="lp-instance-sub">This uninstalls <code>${this._esc(slug)}</code> and permanently deletes its data, database and backup config. This can't be undone.</p>
        <div class="lp-instance-actions">
          <button type="button" class="lp-instance-btn lp-instance-cancel">Cancel</button>
          <button type="button" class="lp-instance-btn lp-instance-danger">Remove instance</button>
        </div>
      </div>`;
    document.body.appendChild(overlay);
    this._onKey = (e) => { if (e.key === 'Escape') this.close(); };
    document.addEventListener('keydown', this._onKey);
    overlay.querySelector('.lp-instance-x').addEventListener('click', () => this.close());
    overlay.querySelector('.lp-instance-cancel').addEventListener('click', () => this.close());
    overlay.addEventListener('click', (e) => { if (e.target === overlay) this.close(); });
    overlay.querySelector('.lp-instance-danger').addEventListener('click', () => this._remove(slug, typeSlug));
  }

  async _remove(slug, typeSlug) {
    if ((!window.tasksManager || !window.tasksManager.router) && window.appsManager && window.appsManager.loadTaskSystem) {
      try { await window.appsManager.loadTaskSystem(); } catch (_) {}
    }
    const notify = (msg, kind) => {
      const sys = (typeof window.ensureNotificationSystem === 'function')
        ? window.ensureNotificationSystem() : window.notificationSystem;
      if (sys && typeof sys.show === 'function') sys.show(msg, kind || 'info');
    };
    if (!window.tasksManager || !window.tasksManager.router) {
      notify('Task system unavailable — could not remove instance.', 'error');
      return;
    }
    try {
      await window.tasksManager.router.routeAction('instance_remove', { appName: slug });
      this.close();
      notify(`Removing instance ${slug} — track progress in Tasks.`, 'success');
      const path = (typeof window.appPath === 'function') ? window.appPath(typeSlug, 'config') : `/app/${typeSlug}/config`;
      if (window.librePortalSPA && window.librePortalSPA.navigateTo) {
        window.librePortalSPA.navigateTo(path);
      } else if (window.navigateToRoute) {
        window.navigateToRoute(path.replace(/^\//, ''));
      } else {
        window.location.href = path;
      }
    } catch (error) {
      notify(`Failed to remove instance: ${error.message}`, 'error');
    }
  }
}

window.instanceManager = window.instanceManager || new InstanceManager();
