import { z } from 'zod';
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { config } from '../../config.js';
import { hasComposerDependency, readComposerJson } from '../../lib/frameworks/composer.js';
import { runCommand } from '../../lib/runCommand.js';
import { pascalCase } from '../../lib/strings.js';
import { errorResult, jsonResult, toErrorMessage } from '../shared.js';
import { requireLaravel } from './requireLaravel.js';

export function registerGenerateFilamentResourceTool(server: McpServer): void {
  server.registerTool(
    'generate_filament_resource',
    {
      title: 'Generate Filament Resource',
      description:
        'Generate a Filament admin resource via `php artisan make:filament-resource`. Requires filament/filament to be installed.',
      inputSchema: {
        name: z.string().min(1).describe('Resource/model name, e.g. "Post".'),
        generate: z
          .boolean()
          .optional()
          .default(true)
          .describe('Pass --generate to Filament when true (default).'),
      },
    },
    async ({ name, generate }) => {
      try {
        const laravel = requireLaravel();
        const composer = readComposerJson(laravel.root);
        if (!hasComposerDependency(composer, 'filament/filament')) {
          return errorResult(
            'filament/filament is not installed. Run composer_require with package "filament/filament" first ' +
              '(or `composer require filament/filament`).',
          );
        }

        const resource = pascalCase(name);
        const args = ['artisan', 'make:filament-resource', resource, '--no-interaction'];
        if (generate !== false) args.push('--generate');

        const result = await runCommand('php', args, {
          cwd: laravel.root,
          timeoutMs: config.scaffoldCommandTimeoutMs,
        });
        return jsonResult({
          package: 'filament/filament',
          resource,
          exitCode: result.exitCode,
          failed: result.failed,
          output: result.output,
        });
      } catch (error) {
        return errorResult(toErrorMessage(error));
      }
    },
  );
}

export function registerGenerateNovaResourceTool(server: McpServer): void {
  server.registerTool(
    'generate_nova_resource',
    {
      title: 'Generate Nova Resource',
      description:
        'Generate a Laravel Nova resource via `php artisan nova:resource`. Requires laravel/nova to be installed.',
      inputSchema: {
        name: z.string().min(1).describe('Resource name, e.g. "Post".'),
      },
    },
    async ({ name }) => {
      try {
        const laravel = requireLaravel();
        const composer = readComposerJson(laravel.root);
        if (!hasComposerDependency(composer, 'laravel/nova')) {
          return errorResult(
            'laravel/nova is not installed. Install Nova (license required) then re-run this tool. ' +
              'See https://nova.laravel.com/docs for installation.',
          );
        }

        const resource = pascalCase(name);
        const result = await runCommand('php', ['artisan', 'nova:resource', resource, '--no-interaction'], {
          cwd: laravel.root,
          timeoutMs: config.scaffoldCommandTimeoutMs,
        });
        return jsonResult({
          package: 'laravel/nova',
          resource,
          exitCode: result.exitCode,
          failed: result.failed,
          output: result.output,
        });
      } catch (error) {
        return errorResult(toErrorMessage(error));
      }
    },
  );
}
