/**
 * app.mjs — Main application bootstrap
 */

import store from './store.mjs';
import eventBus, { EVENTS } from './event-bus.mjs';
import api from './api.mjs';
import router from './router.mjs';

function _tryParseJSON(str) {
  try { return JSON.parse(str); } catch { return {}; }
}

const ACCENT_PRESETS = {
  Indigo:  { primary: '#6366f1', light: '#818cf8', dark: '#4f46e5', secondary: '#8b5cf6' },
  Blue:    { primary: '#3b82f6', light: '#60a5fa', dark: '#2563eb', secondary: '#6366f1' },
  Emerald: { primary: '#10b981', light: '#34d399', dark: '#059669', secondary: '#06b6d4' },
  Rose:    { primary: '#f43f5e', light: '#fb7185', dark: '#e11d48', secondary: '#ec4899' },
  Amber:   { primary: '#f59e0b', light: '#fbbf24', dark: '#d97706', secondary: '#f97316' },
  Violet:  { primary: '#8b5cf6', light: '#a78bfa', dark: '#7c3aed', secondary: '#a855f7' },
};

function applyAccentColor(name) {
  const preset = ACCENT_PRESETS[name];
  if (!preset) return;
  const root = document.documentElement;
  root.style.setProperty('--accent-primary', preset.primary);
  root.style.setProperty('--accent-primary-light', preset.light);
  root.style.setProperty('--accent-primary-dark', preset.dark);
  root.style.setProperty('--accent-secondary', preset.secondary);
  root.style.setProperty('--accent-gradient', `linear-gradient(135deg, ${preset.primary}, ${preset.secondary})`);
  root.style.setProperty('--accent-gradient-hover', `linear-gradient(135deg, ${preset.light}, ${preset.secondary})`);
}

async function initialize() {
  console.log('[app] Initializing AI-Do v4.0...');

  // Apply saved theme
  const theme = store.getState().ui.theme;
  document.documentElement.setAttribute('data-theme', theme);

  // Init API client (reads auth token from meta tag)
  api.init();

  // Init router
  router.init();

  // Connect WebSocket for real-time updates
  api.connectWebSocket();

  // Load initial data in parallel
  await loadInitialData();

  // Load secondary data (non-blocking)
  loadSecondaryData();

  // Setup keyboard shortcuts
  setupKeyboardShortcuts();

  // Setup responsive behavior
  setupResponsive();

  // Init UI components (lazy load)
  await initComponents();

  // Setup desktop bridge listeners (Electron IPC)
  setupDesktopBridge();

  // Setup in-app task notifications (toasts for skill start/complete)
  setupTaskNotifications();

  // Setup browser notifications (non-Electron fallback)
  setupBrowserNotifications();

  console.log('[app] AI-Do ready');
}

async function loadInitialData() {
  try {
    const [config, events] = await Promise.all([
      api.getConfig().catch(err => { console.warn('[app] Config load failed:', err.message); return null; }),
      api.getEvents(50).catch(err => { console.warn('[app] Events load failed:', err.message); return []; })
    ]);

    if (config) {
      store.dispatch('SET_SETTINGS', config);
      // Apply saved accent color
      applyAccentColor(config.accentColor);
    }

    // Convert events to chat messages
    // DB rows use 'type' field (not 'kind'); normalise for both.
    if (Array.isArray(events)) {
      const chatMessages = events
        .filter(e => (e.type || e.kind) === 'chat')
        .map(e => ({
          id: e.id,
          role: e.source === 'user' ? 'user' : 'agent',
          content: e.content,
          timestamp: e.created_at || e.timestamp || Date.now()
        }));
      store.dispatch('SET_MESSAGES', chatMessages);

      // Populate activity feed with ALL events (newest first)
      const activityFeed = events.map(e => ({
        id: e.id,
        kind: e.type || e.kind || 'system',
        source: e.source || '',
        content: e.content || '',
        timestamp: e.created_at || e.timestamp || Date.now(),
        metadata: e.metadata ? (typeof e.metadata === 'string' ? _tryParseJSON(e.metadata) : e.metadata) : {}
      })).reverse();
      store.dispatch('SET_ACTIVITY_FEED', activityFeed);
    }
  } catch (err) {
    console.error('[app] Initial data load error:', err);
  }
}

async function loadSecondaryData() {
  const loads = [
    api.getSkillsPalette()
      .then(palette => store.dispatch('SET_SKILL_PALETTE', palette))
      .catch(() => {}),
    api.getPersona()
      .then(persona => store.dispatch('SET_PERSONA', persona))
      .catch(() => {}),
    api.getVoiceStatus()
      .then(status => {
        store.dispatch('SET_VOICE_ENABLED', status?.enabled || false);
        // On page load, the browser voice orb should always start idle.
        // Server voice states (listening, detecting, etc.) are server-side
        // and don't mean the browser mic is active.
        store.dispatch('SET_VOICE_STATUS', 'idle');
      })
      .catch(() => {}),
    api.getWorkspaces()
      .then(ws => {
        store.dispatch('SET_WORKSPACES', ws?.workspaces || ws || []);
        if (ws?.active) store.dispatch('SET_ACTIVE_WORKSPACE', ws.active);
      })
      .catch(() => {}),
    api.getKGStats()
      .then(stats => store.dispatch('SET_KG_STATS', stats))
      .catch(() => {}),
    api.checkForUpdates()
      .then(result => {
        if (result?.available) showUpdateBanner(result.remoteVersion);
      })
      .catch(() => {})
  ];

  await Promise.allSettled(loads);
}

function showUpdateBanner(version) {
  if (document.getElementById('update-banner')) return; // already shown
  const banner = document.createElement('div');
  banner.id = 'update-banner';
  banner.className = 'update-banner';
  banner.innerHTML = `
    <span>A new version is available${version ? ` (v${version})` : ''}</span>
    <a href="https://ai-do-site.pages.dev" target="_blank" rel="noopener">Download</a>
    <button class="update-banner-close" aria-label="Dismiss">&times;</button>
  `;
  banner.querySelector('.update-banner-close').addEventListener('click', () => banner.remove());
  document.body.prepend(banner);
}

function setupKeyboardShortcuts() {
  document.addEventListener('keydown', (e) => {
    // Escape: exit focus mode
    if (e.key === 'Escape') {
      if (store.getState().ui.focusMode) {
        store.dispatch('SET_FOCUS_MODE', false);
        e.preventDefault();
      }
    }

    // Cmd/Ctrl+K: focus chat input
    if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
      const input = document.querySelector('.chat-input textarea');
      if (input) {
        input.focus();
        e.preventDefault();
      }
    }

    // Cmd/Ctrl+\: toggle sidebar
    if ((e.metaKey || e.ctrlKey) && e.key === '\\') {
      store.dispatch('TOGGLE_SIDEBAR');
      e.preventDefault();
    }

    // Cmd/Ctrl+Shift+F: toggle focus mode
    if ((e.metaKey || e.ctrlKey) && e.shiftKey && e.key === 'f') {
      store.dispatch('SET_FOCUS_MODE', !store.getState().ui.focusMode);
      e.preventDefault();
    }

    // ?: show keyboard shortcuts help modal
    if (e.key === '?' && !e.metaKey && !e.ctrlKey) {
      const tag = document.activeElement?.tagName;
      if (tag === 'INPUT' || tag === 'TEXTAREA') return;
      e.preventDefault();
      showShortcutsModal();
    }
  });
}

async function showShortcutsModal() {
  const { show } = await import('./components/modal.mjs');

  const shortcuts = [
    { keys: ['?'], desc: 'Show keyboard shortcuts' },
    { keys: ['Esc'], desc: 'Exit focus mode / close dialog' },
    { keys: ['⌘', 'K'], desc: 'Focus chat input' },
    { keys: ['⌘', '\\'], desc: 'Toggle sidebar' },
    { keys: ['⌘', '⇧', 'F'], desc: 'Toggle focus mode' },
  ];

  const grid = document.createElement('div');
  grid.className = 'shortcuts-grid';

  for (const { keys, desc } of shortcuts) {
    const keyGroup = document.createElement('div');
    keyGroup.className = 'shortcuts-keys';
    keys.forEach((k, i) => {
      if (i > 0) {
        const plus = document.createElement('span');
        plus.className = 'shortcuts-plus';
        plus.textContent = '+';
        keyGroup.appendChild(plus);
      }
      const kbd = document.createElement('kbd');
      kbd.textContent = k;
      keyGroup.appendChild(kbd);
    });

    const label = document.createElement('span');
    label.className = 'shortcuts-desc';
    label.textContent = desc;

    grid.appendChild(keyGroup);
    grid.appendChild(label);
  }

  show({ title: 'Keyboard Shortcuts', content: grid });
}

function setupResponsive() {
  const mq = window.matchMedia('(max-width: 768px)');

  const handleResize = (e) => {
    store.dispatch('SET_MOBILE', e.matches);
  };

  mq.addEventListener('change', handleResize);
  handleResize(mq);

  // Sync sidebar/right-panel collapsed state to DOM
  store.subscribe(
    (s) => s.ui.sidebarCollapsed,
    (collapsed) => {
      document.getElementById('app')?.classList.toggle('sidebar-collapsed', collapsed);
    }
  );

  store.subscribe(
    (s) => s.ui.rightPanelCollapsed,
    (collapsed) => {
      document.getElementById('app')?.classList.toggle('right-panel-collapsed', collapsed);
    }
  );

  store.subscribe(
    (s) => s.ui.focusMode,
    (focusMode) => {
      document.getElementById('app')?.classList.toggle('focus-mode', focusMode);
    }
  );

  // Panel backdrop click closes panels on mobile
  const backdrop = document.querySelector('.panel-backdrop');
  if (backdrop) {
    backdrop.addEventListener('click', () => {
      store.dispatch('TOGGLE_SIDEBAR');
    });
  }
}

async function initComponents() {
  // Lazy-load components — each registers itself
  const componentPaths = [
    './components/onboarding.mjs',
    './components/toast.mjs',
    './components/modal.mjs',
    './components/avatar.mjs',
    './components/preview-panel.mjs',
    './components/chat.mjs',
    './components/voice-orb.mjs',
    './components/dock.mjs',
    './components/sidebar.mjs',
    './components/activity-feed.mjs',
    './components/function-palette.mjs',
    './components/knowledge-explorer.mjs',
    './components/workspace-panel.mjs',
    './components/settings.mjs',
    './components/help.mjs',
    './components/voice-mode.mjs'
  ];

  const results = await Promise.allSettled(
    componentPaths.map(async (path) => {
      try {
        const mod = await import(path);
        if (mod.init) mod.init();
      } catch (err) {
        console.warn(`[app] Component ${path} load deferred:`, err.message);
      }
    })
  );
}

function setupDesktopBridge() {
  if (!window.desktopBridge) return;

  // Theme change from Electron menu
  if (window.desktopBridge.onThemeChange) {
    window.desktopBridge.onThemeChange((theme) => {
      document.documentElement.setAttribute('data-theme', theme);
      store.dispatch('SET_THEME', theme);
    });
  }

  // Focus mode toggle from Electron menu/hotkey
  if (window.desktopBridge.onFocusModeToggle) {
    window.desktopBridge.onFocusModeToggle(() => {
      store.dispatch('SET_FOCUS_MODE', !store.getState().ui.focusMode);
    });
  }

  // Open persona editor from Electron menu
  if (window.desktopBridge.onOpenPersonaEditor) {
    window.desktopBridge.onOpenPersonaEditor(async () => {
      try {
        const { openPersonaEditor } = await import('./components/persona-editor.mjs');
        openPersonaEditor();
      } catch (err) {
        console.warn('[app] Could not open persona editor:', err.message);
      }
    });
  }
}

function setupTaskNotifications() {
  // In-app toast notifications for background task progress.
  // These fire regardless of which view the user is on.

  eventBus.on(EVENTS.SKILL_START, async (data) => {
    const name = data?.name || 'task';
    const { info } = await import('./components/toast.mjs');
    info(`Working on: ${name}...`);
  });

  eventBus.on(EVENTS.SKILL_COMPLETE, async (data) => {
    const name = data?.name || 'task';
    const result = data?.result;
    const hasFile = result?.path || result?.publicPath;
    const { success } = await import('./components/toast.mjs');
    success(hasFile ? `${name} finished — file created!` : `${name} completed`);
  });
}

function setupBrowserNotifications() {
  // Skip in Electron — native notifications handled in main.mjs
  if (window.desktopBridge) return;
  if (!('Notification' in window)) return;

  // Request permission on first user interaction
  const requestPermission = () => {
    if (Notification.permission === 'default') {
      Notification.requestPermission();
    }
  };
  document.addEventListener('click', requestPermission, { once: true });
  document.addEventListener('keydown', requestPermission, { once: true });

  function maybeNotify(title, body, tag) {
    const settings = store.getState().settings || {};
    if (settings.notifications?.enabled === false) return;
    if (!document.hidden) return;
    if (Notification.permission !== 'granted') return;
    new Notification(title, { body, tag });
  }

  eventBus.on(EVENTS.SKILL_COMPLETE, (data) => {
    const name = data?.name || 'Skill';
    const result = data?.result;
    const hasFile = result?.path || result?.publicPath;
    maybeNotify('AI-Do', hasFile ? `${name} created a file` : `${name} completed`, 'skill-complete');
  });

  eventBus.on(EVENTS.ACTIVITY_EVENT, (data) => {
    if (data?.kind !== 'error') return;
    maybeNotify('AI-Do — Error', data?.content || 'An error occurred', 'agent-error');
  });
}

// Boot on DOM ready
if (document.readyState === 'loading') {
  document.addEventListener('DOMContentLoaded', initialize);
} else {
  initialize();
}

export { initialize };
