// auxsystem.js — AUX startup, config, routes, state, and sidepanel message intake
// Owns system boot and shared runtime state.
// Does not own CODE / JSON / AUXCALL belt logic.

import { initEq } from './auxequalizer.js';
import { showInquiryMenu } from './auxmenu.js';
import { applyAuxSkin, initRender, pushTrace, setProviderStatus, setVerbatimStatus as renderVerbatimStatus } from './auxrender.js';
import * as auxio from './auxio.js';

export const STORAGE_KEYS = {
  verbatimHost: 'verbatim.host',
  verbatimPort: 'verbatim.port',
  skin: 'aux.skin'
};

export const ROUTES = {
  verbatimWrite: '/verbatim/input',
  verbatimRead: '/verbatim/output'
};

export const cfg = {
  [STORAGE_KEYS.verbatimHost]: '127.0.0.1',
  [STORAGE_KEYS.verbatimPort]: ''
};

export const state = {
  verbatimConnected: false,

  activeTab: {
    provider: 'IDLE',
    surfaceType: 'UNKNOWN',
    surfaceName: '',
    contractAware: false
  },

  fileTree: null,
  fileTreeFiles: [],
  fileTreeRootPrefix: '',
  readyScanPlayed: false
};

export function get(key) {
  if (key in cfg) return cfg[key];
  if (key in state) return state[key];
  return null;
}

export async function loadConfig() {
  const stored = await chrome.storage.local.get([
    STORAGE_KEYS.verbatimHost,
    STORAGE_KEYS.verbatimPort
  ]);

  cfg[STORAGE_KEYS.verbatimHost] = stored[STORAGE_KEYS.verbatimHost] || '127.0.0.1';
  cfg[STORAGE_KEYS.verbatimPort] = stored[STORAGE_KEYS.verbatimPort] || '';

  return getConfig();
}

export function getConfig() {
  return {
    host: cfg[STORAGE_KEYS.verbatimHost],
    port: cfg[STORAGE_KEYS.verbatimPort]
  };
}

export async function saveConfig(newHost, newPort) {
  const host = String(newHost || '127.0.0.1').trim();
  const port = String(newPort || '').trim();

  cfg[STORAGE_KEYS.verbatimHost] = host;
  cfg[STORAGE_KEYS.verbatimPort] = port;

  await chrome.storage.local.set({
    [STORAGE_KEYS.verbatimHost]: host,
    [STORAGE_KEYS.verbatimPort]: port
  });

  return { host, port };
}

function activeTabIsReadyForScan(profile = state.activeTab) {
  const provider = String(profile?.provider || '').trim().toUpperCase();
  return Boolean(provider && provider !== 'IDLE' && provider !== 'UNKNOWN');
}

function isReadyScanAllowedUrl(url = '') {
  try {
    const parsed = new URL(String(url || ''));
    const host = parsed.hostname.toLowerCase();
    return host === 'chatgpt.com'
      || host === 'chat.openai.com'
      || host === 'gemini.google.com'
      || host === 'claude.ai'
      || host === 'copilot.microsoft.com'
      || host === 'aistudio.google.com';
  } catch {
    return false;
  }
}

async function getReadyScanTargetTab() {
  const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
  if (typeof tab?.id !== 'number') return null;
  if (!isReadyScanAllowedUrl(tab.url)) return null;
  return tab;
}

async function runReadyScanTheatre(reason = 'ready') {
  if (state.readyScanPlayed) return false;
  if (!state.verbatimConnected || !activeTabIsReadyForScan()) return false;

  try {
    const tab = await getReadyScanTargetTab();
    if (!tab) {
      pushTrace({
        file: 'auxsystem.js',
        fn: 'runReadyScanTheatre',
        step: 'startup scan theatre skipped',
        note: 'active tab is not a supported AI surface'
      });
      return false;
    }

    const scanText = `AUX READY · VERBATIM CONNECTED · ${state.activeTab.surfaceName || state.activeTab.provider || 'AI CONNECTED'}`;

    await chrome.scripting.executeScript({
      target: { tabId: tab.id },
      args: [scanText],
      func: async text => {
        const url = chrome.runtime.getURL('auxmeter.js');
        const module = await import(url);
        module.executeFireAndForgetScan?.(String(text || 'AUX READY'));
      }
    });

    state.readyScanPlayed = true;

    pushTrace({
      file: 'auxsystem.js',
      fn: 'runReadyScanTheatre',
      step: 'startup scan theatre played',
      note: state.activeTab.surfaceName || state.activeTab.provider || reason
    });

    return true;
  } catch (error) {
    pushTrace({
      file: 'auxsystem.js',
      fn: 'runReadyScanTheatre',
      step: 'startup scan theatre unavailable',
      note: error?.message || reason
    });

    return false;
  }
}
function queueReadyScanTheatre(reason = 'ready') {
  setTimeout(() => void runReadyScanTheatre(reason), 180);
}

export function setVerbatimStatus(isConnected) {
  const next = Boolean(isConnected);
  const wasConnected = Boolean(state.verbatimConnected);

  state.verbatimConnected = next;
  if (!next) state.readyScanPlayed = false;

  renderVerbatimStatus(next);

  window.dispatchEvent(new CustomEvent('aux:verbatim-connection-changed', {
    detail: { isConnected: next }
  }));

  if (next && !wasConnected && activeTabIsReadyForScan(state.activeTab)) {
    queueReadyScanTheatre('ready_connected');
  }

  return next;
}
export function setActiveTab(profile = {}) {
  const wasReady = activeTabIsReadyForScan(state.activeTab);

  state.activeTab = {
    provider: profile.provider || 'IDLE',
    surfaceType: profile.surfaceType || 'UNKNOWN',
    surfaceName: profile.surfaceName || '',
    contractAware: Boolean(profile.contractAware)
  };

  const isReady = activeTabIsReadyForScan(state.activeTab);

  setProviderStatus(state.activeTab.provider, state.activeTab);

  window.dispatchEvent(new CustomEvent('aux:active-tab-updated', {
    detail: state.activeTab
  }));

  if (state.verbatimConnected && isReady && !wasReady && !state.readyScanPlayed) {
    queueReadyScanTheatre('ready_connected');
  }

  return state.activeTab;
}
export function setFileTree(treeData = {}) {
  state.fileTree = treeData.tree || null;
  state.fileTreeFiles = Array.isArray(treeData.files) ? treeData.files : [];
  state.fileTreeRootPrefix = treeData.prefix || '';

  window.dispatchEvent(new CustomEvent('aux:filetree-updated', {
    detail: { filesCount: state.fileTreeFiles.length }
  }));

  return getFileTree();
}

export function getFileTree() {
  return {
    tree: state.fileTree,
    files: state.fileTreeFiles,
    prefix: state.fileTreeRootPrefix
  };
}

export function clearFileTree() {
  return setFileTree({
    tree: null,
    files: [],
    prefix: ''
  });
}

async function initSkin() {
  let skin = 'cruise';

  try {
    const stored = await chrome.storage.local.get(STORAGE_KEYS.skin);
    skin = stored?.[STORAGE_KEYS.skin] === 'studio' ? 'studio' : 'cruise';
  } catch {}

  applyAuxSkin(skin);

  const toggle = document.getElementById('skin-toggle');
  if (!toggle || toggle.dataset.auxSkinBound === 'true') return;

  toggle.dataset.auxSkinBound = 'true';

  toggle.addEventListener('click', async () => {
    const next = document.body?.dataset?.skin === 'studio' ? 'cruise' : 'studio';

    applyAuxSkin(next);

    try {
      await chrome.storage.local.set({ [STORAGE_KEYS.skin]: next });
    } catch {}
  });
}

function installSystemMessages() {
  chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
    if (message?.type === 'AUX_DETECTED_ITEM_TO_SYSTEM') {
      auxio.handleDetectedItem(message.item)
        .then(result => sendResponse(result))
        .catch(error => sendResponse({ ok: false, msg: error?.message || 'AUX item failed' }));

      return true;
    }

    if (message?.type === 'AUX_DETECTED_ITEMS_TO_SYSTEM') {
      auxio.handleDetectedItems(message.items)
        .then(result => sendResponse(result))
        .catch(error => sendResponse({ ok: false, msg: error?.message || 'AUX items failed' }));

      return true;
    }

    if (message?.type === 'AUX_STATE_PROFILE_MUTATED') {
      setActiveTab(message.activeTabModel || message.profile || {});
      sendResponse({ ok: true });
      return true;
    }

    if (message?.type === 'AUX_CONTEXT_DROP_IN_FULL_FILE') {
      const payload = message.payload?.payload || message.payload?.text || message.payload || '';

      auxio.handleDetectedItem({
        stream: 'CODE',
        action: 'codetoaux',
        payload,
        source: {
          source: 'context-menu-drop-in',
          url: message.payload?.url || ''
        }
      }).then(result => sendResponse(result))
        .catch(error => sendResponse({ ok: false, msg: error?.message || 'Drop-in intake failed' }));

      return true;
    }

    return false;
  });
}
async function requestActiveTabProfile() {
  try {
    const profile = await chrome.runtime.sendMessage({ type: 'AUX_REQUEST_STATE_PROFILE' });
    if (profile) setActiveTab(profile);

    const pending = Array.isArray(profile?.pendingDetectedItems)
      ? profile.pendingDetectedItems
      : [];

    if (pending.length) {
      await auxio.handleDetectedItems(pending);
    }
  } catch {}
}
async function bootSystem() {
  try {
    await loadConfig();
    initEq();
    await initSkin();
    installSystemMessages();

    window.AUX = {
      config: {
        get,
        loadConfig,
        saveConfig,
        getConfig
      },

      state,

      io: auxio,

      showInquiryMenu,

      getHealth: auxio.getHealth,
      endpoint: auxio.endpoint,

      lineIn: auxio.lineIn,
      lineOut: auxio.lineOut,

      handleDetectedItem: auxio.handleDetectedItem,
      handleDetectedItems: auxio.handleDetectedItems,

      addCodeToLineOut: auxio.addCodeToLineOut,
      addJsonToLineOut: auxio.addJsonToLineOut,
      addFileInquiryToLineIn: auxio.addFileInquiryToLineIn,

      requestFileInquiry: auxio.requestFileInquiry,
      autoFileInquiry: auxio.autoFileInquiry,

      feedLineInItem: auxio.feedLineInItem,
      sendLineOutItem: auxio.sendLineOutItem,
      sendAllLineOut: auxio.sendAllLineOut,
      runHardwareButton: auxio.runHardwareButton,

      lineInRetrieve: auxio.retrieve
    };

    await initRender({
      saveConfig,
      getConfig
    });
    await auxio.getHealth();
    await requestActiveTabProfile();

    pushTrace({
      file: 'auxsystem.js',
      fn: 'bootSystem',
      step: 'system boot complete',
      note: 'AUX side system ready'
    });
  } catch (error) {
    console.error('[AUX SYSTEM] boot failed:', error);
  }
}

bootSystem();