import {
  listDirectory,
  readWorkspaceFile,
  vigthoriaHttpProxy,
} from '@/lib/tauri-bridge';

const BROWSER_SOURCE_EXTENSIONS = new Set([
  '.css', '.html', '.htm', '.js', '.jsx', '.mjs', '.cjs',
  '.ts', '.tsx', '.vue', '.svelte', '.json',
]);
const BROWSER_SOURCE_NAMES = new Set(['.browserslistrc']);
const BROWSER_SKIP_DIRS = new Set([
  '.git', '.next', '.nuxt', '.svelte-kit', 'build', 'coverage',
  'dist', 'node_modules', 'target', 'vendor',
]);
const BROWSER_INLINE_FILE_LIMIT = 120;
const BROWSER_INLINE_BYTE_LIMIT = 750_000;

function trimBase(url: string, fallback: string): string {
  const trimmed = (url || '').trim().replace(/\/+$/, '');
  return trimmed || fallback;
}

/** Resolve the direct authenticated user endpoint while preserving self-hosted overrides. */
export function hyperloopUserBase(url: string): string {
  return trimBase(url, 'https://hyperloop.vigthoria.io');
}

export async function hyperloopPreflight(
  baseUrl: string,
  token: string,
  prompt: string,
  workspacePath?: string,
): Promise<Record<string, unknown>> {
  const url = `${hyperloopUserBase(baseUrl)}/api/hyperloop/preflight`;
  const res = await vigthoriaHttpProxy(
    'POST',
    url,
    token,
    JSON.stringify({
      request: prompt,
      context: workspacePath ? { project_path: workspacePath } : {},
    }),
  );
  if (!res.ok) {
    throw new Error(parseError(res.body) || `Hyper-Loop error (${res.status})`);
  }
  return JSON.parse(res.body) as Record<string, unknown>;
}

export async function hyperloopProcess(
  baseUrl: string,
  token: string,
  prompt: string,
  workspacePath?: string,
): Promise<Record<string, unknown>> {
  const url = `${hyperloopUserBase(baseUrl)}/api/hyperloop/process`;
  const res = await vigthoriaHttpProxy(
    'POST',
    url,
    token,
    JSON.stringify({
      request: prompt,
      context: workspacePath ? { project_path: workspacePath } : {},
      execution_mode: 'classic',
    }),
  );
  if (!res.ok) {
    throw new Error(parseError(res.body) || `Hyper-Loop error (${res.status})`);
  }
  return JSON.parse(res.body) as Record<string, unknown>;
}

export async function hyperloopExecute(
  baseUrl: string,
  token: string,
  module: string,
  payload: Record<string, unknown>,
  context?: Record<string, unknown>,
): Promise<Record<string, unknown>> {
  const url = `${hyperloopUserBase(baseUrl)}/api/hyperloop/execute`;
  const res = await vigthoriaHttpProxy(
    'POST',
    url,
    token,
    JSON.stringify({
      module,
      payload,
      context: context ?? {},
    }),
  );
  if (!res.ok) {
    throw new Error(parseError(res.body) || `Hyper-Loop execute error (${res.status})`);
  }
  return JSON.parse(res.body) as Record<string, unknown>;
}

export async function collectBrowserCompatibilityFiles(
  workspaceRoot: string,
): Promise<Array<{ path: string; content: string }>> {
  const files: Array<{ path: string; content: string }> = [];
  let bytes = 0;
  const queue: Array<{ absolute: string; relative: string; depth: number }> = [
    { absolute: workspaceRoot, relative: '', depth: 0 },
  ];

  while (queue.length > 0 && files.length < BROWSER_INLINE_FILE_LIMIT && bytes < BROWSER_INLINE_BYTE_LIMIT) {
    const current = queue.shift();
    if (!current) break;
    const entries = (await listDirectory(current.absolute, 500)).sort((a, b) => a.name.localeCompare(b.name));
    for (const entry of entries) {
      if (files.length >= BROWSER_INLINE_FILE_LIMIT || bytes >= BROWSER_INLINE_BYTE_LIMIT) break;
      const relative = current.relative ? `${current.relative}/${entry.name}` : entry.name;
      if (entry.isDir) {
        if (current.depth < 8 && !BROWSER_SKIP_DIRS.has(entry.name)) {
          queue.push({ absolute: entry.path, relative, depth: current.depth + 1 });
        }
        continue;
      }
      const dot = entry.name.lastIndexOf('.');
      const extension = dot >= 0 ? entry.name.slice(dot).toLowerCase() : '';
      if (!BROWSER_SOURCE_EXTENSIONS.has(extension) && !BROWSER_SOURCE_NAMES.has(entry.name)) continue;
      let content: string;
      try {
        content = await readWorkspaceFile(workspaceRoot, relative);
      } catch {
        continue;
      }
      const encodedBytes = new TextEncoder().encode(content).length;
      if (bytes + encodedBytes > BROWSER_INLINE_BYTE_LIMIT) break;
      files.push({ path: relative.replace(/\\/g, '/'), content });
      bytes += encodedBytes;
    }
  }
  return files;
}

export async function templateMatch(
  baseUrl: string,
  token: string | null,
  vision: string,
): Promise<Record<string, unknown>> {
  const url = `${trimBase(baseUrl, 'https://coder.vigthoria.io/api/template-service')}/match`;
  const res = await vigthoriaHttpProxy(
    'POST',
    url,
    token && token.length > 0 ? token : null,
    JSON.stringify({ vision }),
  );
  if (!res.ok) {
    throw new Error(parseError(res.body) || `Template service error (${res.status})`);
  }
  return JSON.parse(res.body) as Record<string, unknown>;
}

export async function templateScaffold(
  baseUrl: string,
  token: string | null,
  vision: string,
): Promise<Record<string, unknown>> {
  const url = `${trimBase(baseUrl, 'https://coder.vigthoria.io/api/template-service')}/scaffold`;
  const res = await vigthoriaHttpProxy(
    'POST',
    url,
    token && token.length > 0 ? token : null,
    JSON.stringify({ vision }),
  );
  if (!res.ok) {
    throw new Error(parseError(res.body) || `Template scaffold error (${res.status})`);
  }
  return JSON.parse(res.body) as Record<string, unknown>;
}

export async function templateStats(
  baseUrl: string,
  token?: string | null,
): Promise<Record<string, unknown>> {
  const url = `${trimBase(baseUrl, 'https://coder.vigthoria.io/api/template-service')}/stats`;
  const res = await vigthoriaHttpProxy('GET', url, token ?? null, null);
  if (!res.ok) throw new Error(parseError(res.body) || `Template stats error (${res.status})`);
  return JSON.parse(res.body) as Record<string, unknown>;
}

export async function templateList(
  baseUrl: string,
  token?: string | null,
  category?: string,
): Promise<Record<string, unknown>> {
  const base = trimBase(baseUrl, 'https://coder.vigthoria.io/api/template-service');
  const url = category ? `${base}/templates?category=${encodeURIComponent(category)}` : `${base}/templates`;
  const res = await vigthoriaHttpProxy('GET', url, token ?? null, null);
  if (!res.ok) throw new Error(parseError(res.body) || `Template list error (${res.status})`);
  return JSON.parse(res.body) as Record<string, unknown>;
}

function parseError(body: string): string | null {
  try {
    const parsed = JSON.parse(body) as { error?: string; message?: string; detail?: string };
    return parsed.error || parsed.message || parsed.detail || null;
  } catch {
    return body.trim().slice(0, 240) || null;
  }
}

export function formatServiceResult(data: Record<string, unknown>): string {
  const parts: string[] = [];
  if (typeof data.status === 'string') parts.push(`Status: ${data.status}`);
  if (typeof data.task_id === 'string') parts.push(`Task: ${data.task_id}`);
  if (typeof data.module === 'string') parts.push(`Module: ${data.module}`);
  if (data.route && typeof data.route === 'object') {
    const route = data.route as Record<string, unknown>;
    if (typeof route.module === 'string') parts.push(`Route module: ${route.module}`);
    if (typeof route.action === 'string') parts.push(`Action: ${route.action}`);
  } else if (typeof data.route === 'string') {
    parts.push(`Route: ${data.route}`);
  }
  const template = data.template;
  if (template && typeof template === 'object') {
    const t = template as Record<string, unknown>;
    if (typeof t.name === 'string') parts.push(`Template: ${t.name}`);
    if (typeof t.category === 'string') parts.push(`Category: ${t.category}`);
  } else if (typeof data.template === 'string') {
    parts.push(`Template: ${data.template}`);
  }
  if (typeof data.confidence === 'number') parts.push(`Confidence: ${Math.round(data.confidence * 100)}%`);
  const timeMs = typeof data.time_ms === 'number' ? data.time_ms : data.processing_time;
  if (typeof timeMs === 'number') parts.push(`Time: ${Math.round(timeMs)}ms`);
  const summary = typeof data.summary === 'string' ? data.summary : null;
  const result = typeof data.result === 'string' ? data.result : null;
  const structuredResult = data.result && typeof data.result === 'object'
    ? data.result as Record<string, unknown>
    : null;
  const output = typeof data.output === 'string' ? data.output : null;
  const markdown = typeof data.markdown === 'string' ? data.markdown : null;
  const html = typeof data.html === 'string' ? data.html : null;
  if (summary) parts.push('', summary);
  if (result) parts.push('', result);
  if (structuredResult) {
    const inner = structuredResult.result && typeof structuredResult.result === 'object'
      ? structuredResult.result
      : structuredResult;
    parts.push('', '```json', JSON.stringify(inner, null, 2).slice(0, 12000), '```');
  }
  if (output) parts.push('', output);
  if (markdown) parts.push('', markdown);
  if (html) parts.push('', `[HTML output ${html.length} chars — open in browser from project if saved]`);
  if (parts.length === 0) {
    return '```json\n' + JSON.stringify(data, null, 2).slice(0, 12000) + '\n```';
  }
  return parts.join('\n');
}
