import fs from 'node:fs';
import path from 'node:path';
import { z } from 'zod';
import { resolveWorkspacePath } from '../../lib/sandbox.js';
import { pascalCase } from '../../lib/strings.js';
import { errorResult, jsonResult, toErrorMessage } from '../shared.js';
import { requireReact } from './requireReact.js';
function resolveAppDir(root) {
    if (fs.existsSync(path.join(root, 'src', 'app')))
        return path.join(root, 'src', 'app');
    return path.join(root, 'app');
}
function routeSegments(routePath) {
    return routePath.split('/').filter(Boolean);
}
function assertNextAppRouter(root) {
    const appDir = resolveAppDir(root);
    const hasLayout = fs.existsSync(path.join(appDir, 'layout.tsx')) ||
        fs.existsSync(path.join(appDir, 'layout.jsx')) ||
        fs.existsSync(path.join(root, 'next.config.js')) ||
        fs.existsSync(path.join(root, 'next.config.mjs')) ||
        fs.existsSync(path.join(root, 'next.config.ts'));
    if (!hasLayout && !fs.existsSync(appDir)) {
        throw new Error('Next.js App Router not detected. Expected an app/ (or src/app/) directory or next.config.*.');
    }
}
export function registerGenerateNextPageTool(server) {
    server.registerTool('generate_next_page', {
        title: 'Generate Next.js Page',
        description: 'Scaffold a Next.js App Router page.tsx under app/{path}/ (or src/app/). Optionally also creates loading.tsx and error.tsx.',
        inputSchema: {
            path: z.string().min(1).describe('URL path, e.g. "/users" or "/blog/[slug]".'),
            title: z.string().optional().describe('Optional heading text; defaults to a PascalCase name from the path.'),
            withLoading: z.boolean().optional().default(false).describe('Also create loading.tsx.'),
            withError: z.boolean().optional().default(false).describe('Also create error.tsx.'),
            overwrite: z.boolean().optional().default(false),
        },
    }, async ({ path: routePath, title, withLoading, withError, overwrite }) => {
        try {
            const react = requireReact();
            assertNextAppRouter(react.root);
            const typescript = fs.existsSync(path.join(react.root, 'tsconfig.json'));
            const ext = typescript ? 'tsx' : 'jsx';
            const appDir = resolveAppDir(react.root);
            const dir = resolveWorkspacePath(appDir, path.join(...routeSegments(routePath)));
            fs.mkdirSync(dir, { recursive: true });
            const heading = title ?? pascalCase(routeSegments(routePath).join(' ') || 'Page');
            const files = [];
            const pageFile = path.join(dir, `page.${ext}`);
            if (!overwrite && fs.existsSync(pageFile)) {
                return errorResult(`"${pageFile}" already exists. Pass overwrite: true to replace it.`);
            }
            fs.writeFileSync(pageFile, `export default function ${heading.replace(/[^A-Za-z0-9]/g, '') || 'Page'}Page() {
  return (
    <main>
      <h1>${heading}</h1>
    </main>
  );
}
`);
            files.push(pageFile);
            if (withLoading) {
                const loadingFile = path.join(dir, `loading.${ext}`);
                if (overwrite || !fs.existsSync(loadingFile)) {
                    fs.writeFileSync(loadingFile, `export default function Loading() {\n  return <p>Loading…</p>;\n}\n`);
                    files.push(loadingFile);
                }
            }
            if (withError) {
                const errorFile = path.join(dir, `error.${ext}`);
                if (overwrite || !fs.existsSync(errorFile)) {
                    fs.writeFileSync(errorFile, `'use client';\n\nexport default function Error({ error, reset }: { error: Error; reset: () => void }) {\n  return (\n    <div>\n      <p>{error.message}</p>\n      <button type="button" onClick={() => reset()}>\n        Try again\n      </button>\n    </div>\n  );\n}\n`);
                    files.push(errorFile);
                }
            }
            return jsonResult({ router: 'app', path: routePath, files });
        }
        catch (error) {
            return errorResult(toErrorMessage(error));
        }
    });
}
export function registerGenerateNextLayoutTool(server) {
    server.registerTool('generate_next_layout', {
        title: 'Generate Next.js Layout',
        description: 'Scaffold a Next.js App Router layout.tsx under app/{path}/ (or src/app/).',
        inputSchema: {
            path: z
                .string()
                .optional()
                .default('')
                .describe('URL path segment for a nested layout, e.g. "/dashboard". Empty for the root layout.'),
            overwrite: z.boolean().optional().default(false),
        },
    }, async ({ path: routePath, overwrite }) => {
        try {
            const react = requireReact();
            assertNextAppRouter(react.root);
            const typescript = fs.existsSync(path.join(react.root, 'tsconfig.json'));
            const ext = typescript ? 'tsx' : 'jsx';
            const appDir = resolveAppDir(react.root);
            const segments = routeSegments(routePath ?? '');
            const dir = segments.length === 0 ? appDir : resolveWorkspacePath(appDir, path.join(...segments));
            fs.mkdirSync(dir, { recursive: true });
            const layoutFile = path.join(dir, `layout.${ext}`);
            if (!overwrite && fs.existsSync(layoutFile)) {
                return errorResult(`"${layoutFile}" already exists. Pass overwrite: true to replace it.`);
            }
            const childrenType = typescript ? '{ children }: { children: React.ReactNode }' : '{ children }';
            fs.writeFileSync(layoutFile, `export default function Layout(${childrenType}) {
  return (
    <section>
      {children}
    </section>
  );
}
`);
            return jsonResult({ router: 'app', path: routePath || '/', file: layoutFile });
        }
        catch (error) {
            return errorResult(toErrorMessage(error));
        }
    });
}
//# sourceMappingURL=generateNextFiles.js.map