import fs from 'node:fs';
import path from 'node:path';
import { z } from 'zod';
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { config } from '../../config.js';
import { detectProject } from '../../lib/frameworks/detect.js';
import { readPackageJson } from '../../lib/frameworks/packageManager.js';
import { readComposerJson } from '../../lib/frameworks/composer.js';
import { errorResult, jsonResult, targetSchema, toErrorMessage } from '../shared.js';

export function registerGetPackageInfoTool(server: McpServer): void {
  server.registerTool(
    'get_package_info',
    {
      title: 'Get Package Info',
      description:
        'Return installed package metadata from package.json (React/Node projects) or composer.json (PHP projects): version, scripts, and key dependencies.',
      inputSchema: {
        target: targetSchema,
        ecosystem: z
          .enum(['npm', 'composer', 'auto'])
          .optional()
          .default('auto')
          .describe('Which manifest to read. Auto detects from the resolved project.'),
      },
    },
    async ({ target, ecosystem }) => {
      try {
        const detected = detectProject(config.workspaceRoot);
        const adapter =
          target === 'frontend'
            ? detected.frontend
            : target === 'backend'
              ? detected.backend
              : (detected.frontend ?? detected.backend ?? detected.primary);
        if (!adapter) return errorResult('No project detected in WORKSPACE_ROOT.');

        const resolvedEcosystem = ecosystem === 'auto' ? (adapter.packageManager === 'composer' ? 'composer' : 'npm') : ecosystem;
        const root = adapter.root;

        if (resolvedEcosystem === 'composer') {
          const composerJson = readComposerJson(root);
          if (!composerJson) return errorResult(`No composer.json found at ${root}`);
          const lockPath = path.join(root, 'composer.lock');
          let installed: Record<string, string> = {};
          if (fs.existsSync(lockPath)) {
            try {
              const lock = JSON.parse(fs.readFileSync(lockPath, 'utf8')) as {
                packages?: Array<{ name: string; version: string }>;
              };
              installed = Object.fromEntries(
                (lock.packages ?? []).slice(0, 50).map((p) => [p.name, p.version]),
              );
            } catch {
              // ignore lock parse errors
            }
          }
          return jsonResult({
            ecosystem: 'composer',
            root,
            name: composerJson.name ?? null,
            require: composerJson.require ?? {},
            requireDev: composerJson['require-dev'] ?? {},
            scripts: composerJson.scripts ?? {},
            installedSample: installed,
          });
        }

        const packageJson = readPackageJson(root);
        if (!packageJson) return errorResult(`No package.json found at ${root}`);
        return jsonResult({
          ecosystem: 'npm',
          root,
          name: packageJson.name ?? null,
          scripts: packageJson.scripts ?? {},
          dependencies: packageJson.dependencies ?? {},
          devDependencies: packageJson.devDependencies ?? {},
        });
      } catch (error) {
        return errorResult(toErrorMessage(error));
      }
    },
  );
}
