import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { config } from '../../config.js';
import { detectProject, resolvePackage } from '../../lib/frameworks/detect.js';
import type { FrameworkAdapter } from '../../lib/frameworks/types.js';
import { runCommand } from '../../lib/runCommand.js';
import { errorResult, jsonResult, packageSchema, targetSchema, toErrorMessage } from '../shared.js';

export function registerRunInstallTool(server: McpServer): void {
  server.registerTool(
    'run_install',
    {
      title: 'Install Dependencies',
      description:
        'Install project dependencies via the detected adapter(s): composer for PHP backends, pip/poetry/uv for Django, bundle for Rails, and/or npm/pnpm/yarn/bun for React/Vue/Nuxt. Installs both sides when present unless `target` narrows it. Optional `package` scopes to a monorepo package.',
      inputSchema: { target: targetSchema, package: packageSchema },
    },
    async ({ target, package: packageName }) => {
      try {
        const root = packageName
          ? resolvePackage(config.workspaceRoot, packageName).pkg.absolutePath
          : config.workspaceRoot;
        const detected = detectProject(root);
        const jobs: Array<{ label: string; adapter: FrameworkAdapter }> = [];

        if (target) {
          const adapter = target === 'backend' ? detected.backend : detected.frontend;
          if (!adapter) return errorResult(`target "${target}" was requested, but no such project was detected.`);
          jobs.push({ label: target, adapter });
        } else if (detected.backend || detected.frontend) {
          if (detected.backend) jobs.push({ label: 'backend', adapter: detected.backend });
          if (detected.frontend) jobs.push({ label: 'frontend', adapter: detected.frontend });
        } else {
          jobs.push({ label: 'primary', adapter: detected.primary });
        }

        const results = [];
        for (const job of jobs) {
          try {
            const cmd = job.adapter.installCommand();
            const result = await runCommand(cmd.command, cmd.args, {
              cwd: cmd.cwd,
              timeoutMs: config.scaffoldCommandTimeoutMs,
            });
            results.push({
              target: job.label,
              adapter: job.adapter.label,
              package: packageName ?? null,
              exitCode: result.exitCode,
              timedOut: result.timedOut,
              failed: result.failed,
              output: result.output,
              cwd: result.cwd,
            });
          } catch (error) {
            results.push({ target: job.label, adapter: job.adapter.label, error: toErrorMessage(error) });
          }
        }
        return jsonResult({ results });
      } catch (error) {
        return errorResult(toErrorMessage(error));
      }
    },
  );
}
