/**
 * Workspace routes — /api/workspaces, /api/workspace-tabs
 */
import fs from 'fs';
import os from 'os';
import path from 'path';
import { spawn } from 'child_process';
import { fileURLToPath } from 'url';
import { resolveSeedWorkflowDir } from '../../utils/bundle-paths.js';
import { loadWorkspaces, saveWorkspaces, cleanInstances, deregisterInstance, findFreePort, ensureProjectProfile } from '../helpers.js';

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const _binPath = path.resolve(__dirname, '../../../bin/vlcode-lite.js');

function resolveUserPath(inputPath) {
  if (!inputPath || typeof inputPath !== 'string') return '';
  const expanded = inputPath.startsWith('~')
    ? path.join(os.homedir(), inputPath.slice(1))
    : inputPath;
  return path.resolve(expanded);
}

async function waitForHealthcheck(port, timeoutMs = 15000) {
  const deadline = Date.now() + timeoutMs;
  let lastError = null;
  while (Date.now() < deadline) {
    try {
      const resp = await fetch(`http://127.0.0.1:${port}/api/health`);
      if (resp.ok) return;
      lastError = new Error(`HTTP ${resp.status}`);
    } catch (err) {
      lastError = err;
    }
    await new Promise((resolve) => setTimeout(resolve, 250));
  }
  throw new Error(lastError?.message || `Timed out waiting for instance on port ${port}`);
}

export function setupWorkspaceRoutes(app, server) {
  // --- List workspaces ---
  app.get('/api/workspaces', (req, res) => {
    const list = loadWorkspaces();
    res.json(list);
  });

  // --- Add workspace ---
  app.post('/api/workspaces', (req, res) => {
    const { path: rawDirPath, name } = req.body;
    const dirPath = resolveUserPath(rawDirPath);
    if (!dirPath) return res.status(400).json({ error: 'path required' });
    const list = loadWorkspaces();
    if (!list.find(w => w.path === dirPath)) {
      list.push({ path: dirPath, name: name || path.basename(dirPath), addedAt: new Date().toISOString() });
      saveWorkspaces(list);
    }
    res.json({ ok: true });
  });

  // --- Switch workspace ---
  app.post('/api/workspaces/switch', async (req, res) => {
    const dirPath = resolveUserPath(req.body?.dirPath);
    if (!dirPath || !fs.existsSync(dirPath)) return res.status(400).json({ error: 'Invalid directory' });

    try {
      const result = await server.switchWorkspace(dirPath, {
        name: path.basename(dirPath),
        noWorkspace: false,
        saveAsRecent: true,
      });
      res.json(result);
    } catch (e) {
      res.status(500).json({ error: e.message });
    }
  });

  // --- Close current workspace (return to empty window) ---
  app.post('/api/workspaces/close', async (_req, res) => {
    try {
      const emptyDir = server.config.emptyWorkspaceDir || path.join(os.homedir(), '.vl-code', 'empty-window');
      if (!fs.existsSync(emptyDir)) fs.mkdirSync(emptyDir, { recursive: true });
      const result = await server.switchWorkspace(emptyDir, {
        noWorkspace: true,
        saveAsRecent: false,
      });
      res.json(result);
    } catch (e) {
      res.status(500).json({ error: e.message });
    }
  });

  // --- Delete workspace from list ---
  app.delete('/api/workspaces/:id', (req, res) => {
    const list = loadWorkspaces();
    const idx = parseInt(req.params.id);
    if (idx >= 0 && idx < list.length) list.splice(idx, 1);
    saveWorkspaces(list);
    res.json({ ok: true });
  });

  // --- Create new VL project ---
  app.post('/api/workspaces/create-project', async (req, res) => {
    const { projectName, parentDir } = req.body;
    if (!projectName) return res.status(400).json({ error: 'projectName required' });
    const base = resolveUserPath(parentDir || path.join(os.homedir(), 'Documents', 'VLProjects'));
    const projDir = path.join(base, projectName);
    try {
      if (!fs.existsSync(projDir)) fs.mkdirSync(projDir, { recursive: true });
      for (const d of ['Config', 'Apps', 'Sections', 'ExtComponents', 'Services', 'Database', 'Theme', 'Process']) {
        const dp = path.join(projDir, d);
        if (!fs.existsSync(dp)) fs.mkdirSync(dp, { recursive: true });
      }
      const seedDir = resolveSeedWorkflowDir();
      ensureProjectProfile(projDir, seedDir);
      // Add to workspace list
      const list = loadWorkspaces();
      if (!list.find(w => w.path === projDir)) {
        list.push({ path: projDir, name: projectName, addedAt: new Date().toISOString() });
        saveWorkspaces(list);
      }
      res.json({ ok: true, path: projDir, name: projectName });
    } catch (e) {
      res.status(500).json({ error: e.message });
    }
  });

  // --- Workspace tabs ---
  app.get('/api/workspace-tabs', (_req, res) => {
    res.json({
      tabs: server._openTabs,
      activeDir: server.getVisibleWorkDir(),
    });
  });

  app.post('/api/workspace-tabs/close', async (req, res) => {
    const tabPath = req.body.path || req.body.dirPath;
    if (!tabPath) return res.status(400).json({ error: 'path required' });
    // If closing the active tab, switch to another tab first
    if (tabPath === server.config.workDir) {
      const otherTab = server._openTabs.find(t => t.path !== tabPath);
      server._openTabs = server._openTabs.filter(t => t.path !== tabPath);
      server._saveOpenTabs();
      server._workspaceStates.delete(tabPath);
      if (otherTab) {
        server.broadcast({ type: 'ws_tabs_changed', tabs: server._openTabs, activeDir: server.getVisibleWorkDir() });
        return res.json({ ok: true, switchTo: otherTab.path });
      }
      const emptyDir = server.config.emptyWorkspaceDir || path.join(os.homedir(), '.vl-code', 'empty-window');
      if (!fs.existsSync(emptyDir)) fs.mkdirSync(emptyDir, { recursive: true });
      await server.switchWorkspace(emptyDir, { noWorkspace: true, saveAsRecent: false });
      return res.json({ ok: true });
    }
    server._openTabs = server._openTabs.filter(t => t.path !== tabPath);
    server._saveOpenTabs();
    server._workspaceStates.delete(tabPath);
    server.broadcast({ type: 'ws_tabs_changed', tabs: server._openTabs, activeDir: server.getVisibleWorkDir() });
    res.json({ ok: true });
  });

  app.post('/api/workspace-tabs/reorder', (req, res) => {
    const { tabs } = req.body;
    if (Array.isArray(tabs)) {
      server._openTabs = tabs;
      server._saveOpenTabs();
      server.broadcast({ type: 'ws_tabs_changed', tabs: server._openTabs, activeDir: server.getVisibleWorkDir() });
    }
    res.json({ ok: true });
  });

  // --- Workspace UI state ---
  app.get('/api/workspace/state', (req, res) => {
    try {
      if (!server.hasSelectedWorkspace()) return res.json({});
      const wsPath = path.join(server.config.workDir, '.vl-code', 'workspace.json');
      if (fs.existsSync(wsPath)) {
        res.json(JSON.parse(fs.readFileSync(wsPath, 'utf-8')));
      } else {
        res.json({});
      }
    } catch (e) {
      res.json({});
    }
  });

  app.post('/api/workspace/state', (req, res) => {
    try {
      if (!server.hasSelectedWorkspace()) return res.json({ ok: true });
      const wsDir = path.join(server.config.workDir, '.vl-code');
      if (!fs.existsSync(wsDir)) fs.mkdirSync(wsDir, { recursive: true });
      const wsPath = path.join(wsDir, 'workspace.json');
      let ws = {};
      try { ws = JSON.parse(fs.readFileSync(wsPath, 'utf-8')); } catch {}
      Object.assign(ws, req.body, { updatedAt: new Date().toISOString() });
      fs.writeFileSync(wsPath, JSON.stringify(ws, null, 2));
      res.json({ ok: true });
    } catch (e) {
      res.status(500).json({ error: e.message });
    }
  });

  // ===================== WINDOW MANAGEMENT =====================

  // GET /api/windows — list all running VLCode-Lite instances
  app.get('/api/windows', (req, res) => {
    const instances = cleanInstances();
    res.json(instances);
  });

  // POST /api/windows/open — open a workspace in a new window (spawns new process)
  app.post('/api/windows/open', async (req, res) => {
    const dirPath = resolveUserPath(req.body?.dirPath);
    if (!dirPath || !fs.existsSync(dirPath)) return res.status(400).json({ error: 'Invalid directory' });

    // If already running, return its URL
    const instances = cleanInstances();
    const existing = instances.find(i => i.workDir === dirPath);
    if (existing) return res.json({ ok: true, url: `http://localhost:${existing.port}`, port: existing.port, alreadyRunning: true });

    // Find a free port and spawn a new server process
    let port;
    try {
      const nextPortStart = Math.max((server._serverPort || 3999) + 1, 4000);
      port = await findFreePort(nextPortStart, 4099);
    }
    catch (e) { return res.status(500).json({ error: e.message }); }

    const child = spawn(process.execPath, [_binPath, '--web', '--dir', dirPath, '--port', String(port)], {
      detached: true,
      stdio: 'ignore',
    });

    try {
      await waitForHealthcheck(port);
      child.unref();
      res.json({ ok: true, url: `http://localhost:${port}`, port });
    } catch (e) {
      try { process.kill(child.pid, 'SIGTERM'); } catch {}
      res.status(500).json({ error: `Workspace window failed to start: ${e.message}` });
    }
  });

  // DELETE /api/windows/:port — close a window by killing its process
  app.delete('/api/windows/:port', (req, res) => {
    const port = parseInt(req.params.port, 10);
    const instances = cleanInstances();
    const inst = instances.find(i => i.port === port);
    if (inst) {
      try { process.kill(inst.pid, 'SIGTERM'); } catch {}
      deregisterInstance(port);
    }
    res.json({ ok: true });
  });
}
