/**
 * Connectors API — discovery surface for the Forge browser extension.
 *
 * Reads from the standalone connector registry (lib/connectors/), no
 * longer from the plugin registry. The extension hits this endpoint to
 * learn what connectors are installed and what tools each exposes;
 * `page` / `host_match` / `login_redirect` are expanded server-side
 * with the user's saved settings, {args.*} stays literal for the
 * extension runner.
 *
 * Response shape is preserved 1:1 from the old plugin-backed
 * implementation so the extension and Forge chat keep working without
 * any client change.
 */

import { NextResponse } from 'next/server';
import {
  listInstalledConnectors,
  getInstalledConnector,
  getConnectorEntries,
} from '@/lib/connectors/registry';
import { expandSettingsTokens } from '@/lib/plugins/templates';
import type {
  ConnectorDefinition,
  ConnectorEntry,
  ConnectorTool,
} from '@/lib/connectors/types';

function expandTool(tool: ConnectorTool, settings: Record<string, any> | undefined): ConnectorTool {
  if (!tool.page && !tool.script) return tool;
  const page = tool.page
    ? {
        url: expandSettingsTokens(tool.page.url, settings),
        ...(tool.page.on_target
          ? { on_target: expandSettingsTokens(tool.page.on_target, settings) }
          : {}),
      }
    : undefined;
  return { ...tool, ...(page ? { page } : {}) };
}

function expandEntry(entry: ConnectorEntry, settings: Record<string, any> | undefined): ConnectorEntry {
  const out: ConnectorEntry = {
    ...entry,
    tools: Object.fromEntries(
      Object.entries(entry.tools).map(([name, t]) => [name, expandTool(t, settings)]),
    ),
  };
  if (entry.host_match) out.host_match = expandSettingsTokens(entry.host_match, settings);
  if (entry.login_redirect) out.login_redirect = expandSettingsTokens(entry.login_redirect, settings);
  return out;
}

/** Pure UI label derived from tool protocols. The actual dispatch goes by
 *  each tool's `protocol` field (see lib/chat/tool-dispatcher.ts switch) —
 *  this is just so the ConnectorsTab pill stops calling a connector
 *  browser-side when every one of its tools is server-side (e.g. gitlab,
 *  whose tools all use protocol: http). The legacy connector-level `mode`
 *  field is ignored. */
function deriveModeLabel(entries: ConnectorEntry[]): 'server-side' | 'browser-side' | 'mixed' {
  const ps = new Set<string>();
  for (const e of entries) {
    for (const t of Object.values(e.tools || {})) {
      ps.add((t as any).protocol || 'browser');
    }
  }
  if (ps.size === 0) return 'browser-side';
  const allServer = [...ps].every((p) => p === 'http' || p === 'shell' || p === 'ssh');
  const allBrowser = [...ps].every((p) => p === 'browser');
  return allServer ? 'server-side' : allBrowser ? 'browser-side' : 'mixed';
}

function toConnectorPayload(def: ConnectorDefinition, config: Record<string, any> | undefined, installed: boolean) {
  const entries = getConnectorEntries(def).map(e => expandEntry(e, config));

  const hostMatch = def.host_match
    ? expandSettingsTokens(def.host_match, config)
    : entries[0]?.host_match;
  const loginRedirect = def.login_redirect
    ? expandSettingsTokens(def.login_redirect, config)
    : entries[0]?.login_redirect;
  const runner = def.runner || entries[0]?.runner || 'main';

  return {
    plugin_id: def.id,                        // legacy field name preserved
    name: def.name,
    icon: def.icon,
    version: def.version,
    author: def.author || 'forge',
    description: def.description || '',
    mode: deriveModeLabel(entries),
    installed,
    ...(hostMatch ? { host_match: hostMatch } : {}),
    ...(loginRedirect ? { login_redirect: loginRedirect } : {}),
    runner,
    ...(def.tab_strategy ? { tab_strategy: def.tab_strategy } : {}),
    /** Hint for the marketplace UI: a Test button is wired for this connector. */
    has_test: !!def.test,
    /** Optional human description of what the test does (no request shape exposed). */
    test_description: def.test?.description,
    entries,
  };
}

export async function GET(req: Request) {
  const url = new URL(req.url);
  const id = url.searchParams.get('id');

  if (id) {
    const inst = getInstalledConnector(id);
    if (!inst) return NextResponse.json({ error: 'connector not found' }, { status: 404 });
    return NextResponse.json({ connector: toConnectorPayload(inst.definition, inst.config, true) });
  }

  // The extension always wants the installed list — there is no "not
  // installed but visible" path on this endpoint anymore (that lives
  // in /api/connectors/marketplace, coming in P1.6).
  const connectors = listInstalledConnectors()
    .filter(c => c.enabled)
    .map(c => toConnectorPayload(c.definition, c.config, true));

  return NextResponse.json({ connectors });
}
