import fs from 'node:fs';
import path from 'node:path';
import { z } from 'zod';
import { config } from '../../config.js';
import { runCommand } from '../../lib/runCommand.js';
import { kebabCase, pascalCase } from '../../lib/strings.js';
import { errorResult, jsonResult, toErrorMessage } from '../shared.js';
import { requireLaravel } from './requireLaravel.js';
function pluralize(word) {
    const lower = word.toLowerCase();
    if (lower.endsWith('ies'))
        return word;
    if (lower.endsWith('y') && !/[aeiou]y$/i.test(word))
        return `${word.slice(0, -1)}ies`;
    if (/(s|x|z|ch|sh)$/i.test(word))
        return `${word}es`;
    if (lower.endsWith('s'))
        return word;
    return `${word}s`;
}
export function registerGenerateLaravelResourceTool(server) {
    server.registerTool('generate_laravel_resource', {
        title: 'Generate Laravel Resource',
        description: 'One-shot scaffold of a full Laravel resource: model + migration + factory + seeder + controller, ' +
            'then wire an apiResource/resource route. Wraps the relevant `php artisan make:*` calls.',
        inputSchema: {
            name: z
                .string()
                .min(1)
                .describe('Resource name, e.g. "Post" or "blog_post". Converted to PascalCase for the model/controller.'),
            api: z
                .boolean()
                .optional()
                .default(true)
                .describe('If true (default), generate an API controller (--api) and register Route::apiResource in routes/api.php. If false, generate a web resource controller and register Route::resource in routes/web.php.'),
            migrate: z
                .boolean()
                .optional()
                .default(false)
                .describe('If true, run `php artisan migrate` after scaffolding. Requires a configured database.'),
        },
    }, async ({ name, api, migrate }) => {
        try {
            const laravel = requireLaravel();
            const model = pascalCase(name);
            const controller = `${model}Controller`;
            const routeName = kebabCase(pluralize(model));
            const steps = [];
            // Model + migration + factory + seeder in one go.
            const modelResult = await runCommand('php', ['artisan', 'make:model', model, '-mfs', '--no-interaction'], { cwd: laravel.root, timeoutMs: config.scaffoldCommandTimeoutMs });
            steps.push({ step: 'make:model -mfs', ...modelResult });
            const controllerArgs = api
                ? ['artisan', 'make:controller', controller, '--api', '--model=' + model, '--no-interaction']
                : ['artisan', 'make:controller', controller, '--resource', '--model=' + model, '--no-interaction'];
            const controllerResult = await runCommand('php', controllerArgs, {
                cwd: laravel.root,
                timeoutMs: config.scaffoldCommandTimeoutMs,
            });
            steps.push({ step: 'make:controller', ...controllerResult });
            const routesFile = path.join(laravel.root, 'routes', api ? 'api.php' : 'web.php');
            const routeLine = api
                ? `Route::apiResource('${routeName}', \\App\\Http\\Controllers\\${controller}::class);`
                : `Route::resource('${routeName}', \\App\\Http\\Controllers\\${controller}::class);`;
            const routeWired = wireRoute(routesFile, routeLine, api);
            steps.push({ step: 'wire-route', routesFile, routeLine, wired: routeWired });
            let migrateResult = null;
            if (migrate) {
                migrateResult = await runCommand('php', ['artisan', 'migrate', '--no-interaction'], {
                    cwd: laravel.root,
                    timeoutMs: config.scaffoldCommandTimeoutMs,
                });
                steps.push({ step: 'migrate', ...migrateResult });
            }
            return jsonResult({
                model,
                controller,
                route: `${api ? 'apiResource' : 'resource'} /${routeName}`,
                routesFile,
                routeWired,
                steps,
            });
        }
        catch (error) {
            return errorResult(toErrorMessage(error));
        }
    });
}
function wireRoute(routesFile, routeLine, api) {
    fs.mkdirSync(path.dirname(routesFile), { recursive: true });
    if (!fs.existsSync(routesFile)) {
        const header = api
            ? `<?php\n\nuse Illuminate\\Support\\Facades\\Route;\n\n`
            : `<?php\n\nuse Illuminate\\Support\\Facades\\Route;\n\n`;
        fs.writeFileSync(routesFile, header + routeLine + '\n');
        return true;
    }
    const existing = fs.readFileSync(routesFile, 'utf8');
    if (existing.includes(routeLine.trim()))
        return false;
    // Ensure the Route facade is imported if the file already exists without it.
    let next = existing;
    if (!/use\s+Illuminate\\Support\\Facades\\Route\s*;/.test(next)) {
        if (next.startsWith('<?php')) {
            next = next.replace('<?php', "<?php\n\nuse Illuminate\\Support\\Facades\\Route;");
        }
        else {
            next = `<?php\n\nuse Illuminate\\Support\\Facades\\Route;\n\n${next}`;
        }
    }
    fs.writeFileSync(routesFile, `${next.trimEnd()}\n${routeLine}\n`);
    return true;
}
//# sourceMappingURL=generateLaravelResource.js.map