/**
 * Tool routes — /api/tools/*, /api/skills, /api/doccenter
 */
import fs from 'fs';
import path from 'path';
import { DOCCENTER_API_URL, DOCCENTER_LOCAL_URL } from '../../data/doc-paths.js';
import { getCookie } from '../helpers.js';

const DOCCENTER_CLOUD_ACTIONS = {
  list: 'SERVICE_DocCenter_GetDocList',
  get: 'SERVICE_DocCenter_GetDocById',
  create: 'SERVICE_DocCenter_CreateDoc',
  save: 'SERVICE_DocCenter_SaveDoc',
  publish: 'SERVICE_DocCenter_SaveAsVersion',
  delete: 'SERVICE_DocCenter_DeleteDoc',
  tags: 'SERVICE_DocCenter_GetAllTags',
  createTag: 'SERVICE_DocCenter_CreateTag',
  setTags: 'SERVICE_DocCenter_UpdateDocTags',
  versions: 'SERVICE_DocCenter_GetVersionHistory',
  resolve: 'SERVICE_DocCenter_ResolveDocRef',
};

function normalizeCookieHeader(cookie) {
  const value = String(cookie || '').trim();
  if (!value) return '';
  return value.includes('=') ? value : `ih5bearer=${value}`;
}

function buildDocCenterHeaders(cookie) {
  const headers = { 'Content-Type': 'application/json' };
  const cookieHeader = normalizeCookieHeader(cookie);
  if (cookieHeader) headers.Cookie = cookieHeader;
  return headers;
}

async function requestLocalDocCenter(action, body = {}, headers = {}) {
  const timeout = { signal: AbortSignal.timeout(5000) };
  const resolveDocId = async () => {
    if (body.docId) return body.docId;
    if (!body.path) return null;
    const byPathResp = await fetch(`${DOCCENTER_LOCAL_URL}/api/docs/by-path/${encodeURIComponent(body.path)}`, {
      headers,
      ...timeout,
    }).catch(() => null);
    if (!byPathResp?.ok) return null;
    const byPath = await byPathResp.json();
    return byPath?.id || null;
  };

  if (action === 'list') {
    const query = new URLSearchParams({
      keyword: body.keyword || '',
      tagId: String(body.tagId || 0),
      page: String(body.page || 1),
      pageSize: String(body.pageSize || 200),
    });
    const resp = await fetch(`${DOCCENTER_LOCAL_URL}/api/docs?${query.toString()}`, {
      headers,
      ...timeout,
    }).catch(() => null);
    if (!resp?.ok) return null;
    const payload = await resp.json();
    return {
      success: true,
      data: { list: payload.docs || [] },
      list: payload.docs || [],
      total: payload.total || 0,
    };
  }

  if (action === 'get') {
    const docId = await resolveDocId();
    if (!docId) return null;
    const resp = await fetch(`${DOCCENTER_LOCAL_URL}/api/docs/${encodeURIComponent(docId)}`, {
      headers,
      ...timeout,
    }).catch(() => null);
    if (!resp?.ok) return null;
    const payload = await resp.json();
    return {
      success: true,
      data: {
        id: payload.id,
        _id: payload.id,
        name: payload.name,
        description: payload.description,
        path: payload.path,
        latestVersion: payload.latest_version ?? payload.latestVersion ?? payload.version ?? 0,
        currentContent: payload.current_content ?? payload.currentContent ?? '',
        updatedAt: payload.updated_at ?? payload.updatedAt ?? '',
        tags: payload.tags || [],
      },
    };
  }

  if (action === 'create') {
    const resp = await fetch(`${DOCCENTER_LOCAL_URL}/api/docs`, {
      method: 'POST',
      headers,
      body: JSON.stringify({
        name: body.name,
        description: body.description || '',
        path: body.path,
        content: body.content ?? body.currentContent ?? '',
      }),
      ...timeout,
    }).catch(() => null);
    if (!resp?.ok) return null;
    const payload = await resp.json();
    return { success: true, data: payload, docId: payload.id };
  }

  if (action === 'save') {
    const docId = await resolveDocId();
    if (!docId) return null;
    const resp = await fetch(`${DOCCENTER_LOCAL_URL}/api/docs/${encodeURIComponent(docId)}`, {
      method: 'PUT',
      headers,
      body: JSON.stringify({
        name: body.name,
        description: body.description || '',
        content: body.content ?? body.currentContent ?? '',
      }),
      ...timeout,
    }).catch(() => null);
    if (!resp?.ok) return null;
    return resp.json();
  }

  if (action === 'publish') {
    const docId = await resolveDocId();
    if (!docId) return null;
    const resp = await fetch(`${DOCCENTER_LOCAL_URL}/api/docs/${encodeURIComponent(docId)}/publish`, {
      method: 'POST',
      headers,
      body: JSON.stringify({
        content: body.content ?? body.currentContent ?? '',
        changeNote: body.changeNote || body.message || 'Published from VLCode-Lite',
      }),
      ...timeout,
    }).catch(() => null);
    if (!resp?.ok) return null;
    const payload = await resp.json();
    return { success: true, data: payload };
  }

  if (action === 'delete') {
    const docId = await resolveDocId();
    if (!docId) return null;
    const resp = await fetch(`${DOCCENTER_LOCAL_URL}/api/docs/${encodeURIComponent(docId)}`, {
      method: 'DELETE',
      headers,
      ...timeout,
    }).catch(() => null);
    if (!resp?.ok) return null;
    return resp.json();
  }

  if (action === 'tags') {
    const resp = await fetch(`${DOCCENTER_LOCAL_URL}/api/tags`, {
      headers,
      ...timeout,
    }).catch(() => null);
    if (!resp?.ok) return null;
    const payload = await resp.json();
    return { success: true, data: payload, list: payload };
  }

  if (action === 'createTag') {
    const resp = await fetch(`${DOCCENTER_LOCAL_URL}/api/tags`, {
      method: 'POST',
      headers,
      body: JSON.stringify({ name: body.name, color: body.color }),
      ...timeout,
    }).catch(() => null);
    if (!resp?.ok) return null;
    const payload = await resp.json();
    return { success: true, data: payload };
  }

  if (action === 'setTags') {
    const docId = await resolveDocId();
    if (!docId) return null;
    const resp = await fetch(`${DOCCENTER_LOCAL_URL}/api/tags/doc/${encodeURIComponent(docId)}`, {
      method: 'PUT',
      headers,
      body: JSON.stringify({ tagIds: body.tagIds || [] }),
      ...timeout,
    }).catch(() => null);
    if (!resp?.ok) return null;
    return resp.json();
  }

  if (action === 'versions') {
    const docId = await resolveDocId();
    if (!docId) return null;
    const resp = await fetch(`${DOCCENTER_LOCAL_URL}/api/docs/${encodeURIComponent(docId)}/versions`, {
      headers,
      ...timeout,
    }).catch(() => null);
    if (!resp?.ok) return null;
    const payload = await resp.json();
    return { success: true, data: payload };
  }

  if (action === 'resolve') {
    const resp = await fetch(`${DOCCENTER_LOCAL_URL}/api/docs/resolve`, {
      method: 'POST',
      headers,
      body: JSON.stringify({ refString: body.refString }),
      ...timeout,
    }).catch(() => null);
    if (!resp?.ok) return null;
    const payload = await resp.json();
    return { success: true, data: payload };
  }

  return null;
}

async function requestCloudDocCenter(action, body = {}, headers = {}) {
  const endpoint = DOCCENTER_CLOUD_ACTIONS[action];
  if (!endpoint) throw new Error(`Unknown DocCenter action: ${action}`);
  const resp = await fetch(`${DOCCENTER_API_URL}/${endpoint}`, {
    method: 'POST',
    headers,
    body: JSON.stringify(body),
    signal: AbortSignal.timeout(10000),
  });
  const text = await resp.text();
  let payload = {};
  try {
    payload = text ? JSON.parse(text) : {};
  } catch {
    payload = { raw: text };
  }
  if (!resp.ok) {
    throw new Error(payload?.error || payload?.message || `DocCenter request failed: ${resp.status}`);
  }
  return payload;
}

export function setupToolRoutes(app, server) {
  // --- Tool list (MCP proxy — returns full schemas for MCP server) ---
  app.get('/api/tools/list', (req, res) => {
    const tools = server.toolRegistry.getToolSchemas();
    res.json(tools);
  });

  // --- Tool execute (MCP proxy) ---
  app.post('/api/tools/execute', async (req, res) => {
    const { name, input } = req.body;
    if (!name) return res.status(400).json({ error: 'name required' });
    try {
      const result = await server.toolRegistry.execute(name, input || {});
      res.json(result);
    } catch (e) {
      res.status(500).json({ error: e.message });
    }
  });

  // --- Skills ---
  app.get('/api/skills', (req, res) => {
    const session = server.getSession(req);
    const skills = session.orchestrator?.getSkills?.() || [];
    res.json(skills);
  });

  app.post('/api/skill', async (req, res) => {
    res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive' });
    const send = (event, data) => res.write(`event: ${event}\ndata: ${JSON.stringify(data)}\n\n`);
    const { skill, args, message } = req.body;
    const session = server.getSession(req);
    try {
      const callbacks = {
        onText: (text) => send('text', { text }),
        onThinking: (phase, text) => send('thinking', { phase, text }),
        onToolCall: (name, input) => send('tool_call', { name }),
        onToolResult: (name, result) => send('tool_result', { name }),
        onTodo: (todos) => send('todo', { todos }),
        onDone: () => send('done', {}),
        onError: (err) => send('error', { message: err }),
      };
      if (skill && session.orchestrator?.executeSkill) {
        // Use executeSkill — handles tool filtering, loop skills, prompt expansion
        await session.orchestrator.executeSkill(skill, message || args, callbacks);
      } else {
        // Fallback: direct message processing
        const prompt = message || args || `/${skill}`;
        await session.orchestrator.processUserMessageStreaming(prompt, callbacks);
      }
    } catch (e) { send('error', { message: e.message }); }
    // Autosave after skill execution (success or failure)
    server.autosaveSession(session.chatId || '0', session).catch(() => {});
    res.end();
  });

  app.get('/api/doccenter/embed-status', async (req, res) => {
    let localAvailable = false;
    try {
      const localHealth = await fetch(`${DOCCENTER_LOCAL_URL}/api/health`, {
        signal: AbortSignal.timeout(1200),
      }).catch(() => null);
      localAvailable = !!localHealth?.ok;
    } catch {}
    res.json({ available: true, localAvailable, src: '/doc-center.html?embed=ide' });
  });

  // --- DocCenter proxy ---
  app.post('/api/doccenter/:action', async (req, res) => {
    const action = req.params.action;
    try {
      const body = { ...(req.body || {}) };
      const headers = buildDocCenterHeaders(getCookie(server.config));
      if (action === 'publish' && body.docId && (!body.path || !(body.content ?? body.currentContent))) {
        const existingDoc = await requestCloudDocCenter('get', { docId: body.docId }, headers).catch(() => null)
          || await requestLocalDocCenter('get', { docId: body.docId }, headers).catch(() => null);
        const existingData = existingDoc?.data || {};
        if (!body.path && existingData.path) body.path = existingData.path;
        if (!(body.content ?? body.currentContent) && existingData.currentContent) {
          body.currentContent = existingData.currentContent;
        }
        if (!body.changeNote && body.message) body.changeNote = body.message;
      }
      const hasCookie = Boolean(normalizeCookieHeader(getCookie(server.config)));
      if (hasCookie) {
        const cloudResult = await requestCloudDocCenter(action, body, headers).catch(() => null);
        if (cloudResult) return res.json(cloudResult);
        const localResult = await requestLocalDocCenter(action, body, headers).catch(() => null);
        if (localResult) return res.json(localResult);
      } else {
        const localResult = await requestLocalDocCenter(action, body, headers).catch(() => null);
        if (localResult) return res.json(localResult);
        const cloudResult = await requestCloudDocCenter(action, body, headers).catch(() => null);
        if (cloudResult) return res.json(cloudResult);
      }
      throw new Error(`DocCenter ${action} failed in both cloud and local backends`);
    } catch (e) {
      res.status(500).json({ error: e.message });
    }
  });

  // --- Agent state ---
  app.get('/api/agent/state', (req, res) => {
    const session = server.getSession(req);
    const state = session.orchestrator?.getResumeState?.() || {};
    res.json(state);
  });

  app.get('/api/agents', (req, res) => {
    const session = server.getSession(req);
    const agents = session.orchestrator?._backgroundAgents || [];
    res.json(agents.map(a => ({ id: a.id, status: a.status, startedAt: a.startedAt })));
  });

  app.get('/api/agents/:id', (req, res) => {
    const session = server.getSession(req);
    const agent = session.orchestrator?._backgroundAgents?.find(a => a.id === req.params.id);
    if (agent) res.json(agent);
    else res.status(404).json({ error: 'Agent not found' });
  });

  // --- VL Docs management ---
  app.get('/api/vl-docs', (req, res) => {
    try {
      const vlDir = path.join(server.config.workDir, '.vl-code');
      const docsFile = path.join(vlDir, 'vl-docs.json');
      if (fs.existsSync(docsFile)) res.json(JSON.parse(fs.readFileSync(docsFile, 'utf-8')));
      else res.json([]);
    } catch { res.json([]); }
  });

  app.post('/api/vl-docs/sync', async (req, res) => {
    try {
      const result = await server.toolRegistry.execute('DocCenter', { action: 'list' });
      res.json(result);
    } catch (e) { res.status(500).json({ error: e.message }); }
  });

  app.get('/api/vl-docs/content', (req, res) => {
    const docPath = req.query.path;
    if (!docPath) return res.status(400).json({ error: 'path required' });
    try {
      const fullPath = path.resolve(server.config.workDir, docPath);
      if (fs.existsSync(fullPath)) res.json({ content: fs.readFileSync(fullPath, 'utf-8') });
      else res.status(404).json({ error: 'Not found' });
    } catch (e) { res.status(500).json({ error: e.message }); }
  });
}
