import fs from 'node:fs';
import { z } from 'zod';
import { config } from '../../config.js';
import { detectProject, resolvePackage } from '../../lib/frameworks/detect.js';
import { resolveWorkspacePath } from '../../lib/sandbox.js';
import { runCommand } from '../../lib/runCommand.js';
import { requireLaravel } from '../laravel/requireLaravel.js';
import { errorResult, jsonResult, packageSchema, toErrorMessage } from '../shared.js';
function nodeDockerfile() {
    return `# Generated by web-dev-mcp
FROM node:24-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:24-alpine
WORKDIR /app
ENV NODE_ENV=production
COPY package*.json ./
RUN npm ci --omit=dev && npm cache clean --force
COPY --from=builder /app/dist ./dist
EXPOSE 3000
CMD ["node", "dist/index.js"]
`;
}
function phpDockerfile(kind) {
    const publicDir = kind === 'laravel' ? 'public' : 'public';
    return `# Generated by web-dev-mcp for ${kind}
FROM php:8.3-cli-alpine AS vendor
WORKDIR /app
COPY composer.json composer.lock* ./
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer \\
  && composer install --no-dev --optimize-autoloader --no-interaction --prefer-dist || composer install --no-interaction --prefer-dist

FROM php:8.3-apache
WORKDIR /var/www/html
RUN docker-php-ext-install pdo pdo_mysql
COPY --from=vendor /app/vendor ./vendor
COPY . .
ENV APACHE_DOCUMENT_ROOT=/var/www/html/${publicDir}
RUN sed -ri -e 's!/var/www/html!\\\${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf \\
  && a2enmod rewrite
EXPOSE 80
`;
}
function nginxNodeCompose() {
    return `# Generated by web-dev-mcp
services:
  app:
    build: .
    ports:
      - "3000:3000"
    environment:
      NODE_ENV: production
    depends_on:
      - redis
  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: app
      POSTGRES_PASSWORD: app
      POSTGRES_DB: app
    ports:
      - "5432:5432"
    volumes:
      - db_data:/var/lib/postgresql/data
  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
volumes:
  db_data:
`;
}
function phpCompose() {
    return `# Generated by web-dev-mcp
services:
  app:
    build: .
    ports:
      - "8080:80"
    environment:
      APP_ENV: local
      DB_HOST: db
      DB_DATABASE: app
      DB_USERNAME: app
      DB_PASSWORD: app
      REDIS_HOST: redis
    depends_on:
      - db
      - redis
  db:
    image: mysql:8.0
    environment:
      MYSQL_DATABASE: app
      MYSQL_USER: app
      MYSQL_PASSWORD: app
      MYSQL_ROOT_PASSWORD: root
    ports:
      - "3306:3306"
    volumes:
      - db_data:/var/lib/mysql
  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
volumes:
  db_data:
`;
}
export function registerGenerateDockerfileTool(server) {
    server.registerTool('generate_dockerfile', {
        title: 'Generate Dockerfile',
        description: 'Write a stack-aware Dockerfile at the workspace (or package) root based on detected framework (Node multi-stage or PHP/Apache for Laravel/CodeIgniter).',
        inputSchema: {
            package: packageSchema,
            overwrite: z.boolean().optional().default(false),
        },
    }, async ({ package: packageName, overwrite }) => {
        try {
            const root = packageName
                ? resolvePackage(config.workspaceRoot, packageName).pkg.absolutePath
                : config.workspaceRoot;
            const detected = detectProject(root);
            const file = resolveWorkspacePath(root, 'Dockerfile');
            if (!overwrite && fs.existsSync(file)) {
                return errorResult(`"${file}" already exists. Pass overwrite: true to replace it.`);
            }
            let contents;
            let stack;
            if (detected.backend?.kind === 'laravel' ||
                detected.backend?.kind === 'codeigniter' ||
                detected.backend?.kind === 'symfony') {
                stack = detected.backend.kind;
                contents = phpDockerfile(detected.backend.kind === 'codeigniter' ? 'codeigniter' : 'laravel');
            }
            else {
                const front = detected.frontend?.kind;
                stack =
                    front === 'react' || front === 'vue' || front === 'nuxt'
                        ? `${front}/node`
                        : detected.backend?.kind === 'django' || detected.backend?.kind === 'rails'
                            ? detected.backend.kind
                            : 'node';
                contents = nodeDockerfile();
            }
            fs.writeFileSync(file, contents);
            return jsonResult({ file, stack, package: packageName ?? null });
        }
        catch (error) {
            return errorResult(toErrorMessage(error));
        }
    });
}
export function registerGenerateComposeTool(server) {
    server.registerTool('generate_compose', {
        title: 'Generate docker-compose.yml',
        description: 'Write a docker-compose.yml with app + db + redis presets inferred from the detected stack (Postgres for Node, MySQL for PHP).',
        inputSchema: {
            package: packageSchema,
            overwrite: z.boolean().optional().default(false),
        },
    }, async ({ package: packageName, overwrite }) => {
        try {
            const root = packageName
                ? resolvePackage(config.workspaceRoot, packageName).pkg.absolutePath
                : config.workspaceRoot;
            const detected = detectProject(root);
            const file = resolveWorkspacePath(root, 'docker-compose.yml');
            if (!overwrite && fs.existsSync(file)) {
                return errorResult(`"${file}" already exists. Pass overwrite: true to replace it.`);
            }
            const isPhp = detected.backend?.kind === 'laravel' ||
                detected.backend?.kind === 'codeigniter' ||
                detected.backend?.kind === 'symfony';
            const contents = isPhp ? phpCompose() : nginxNodeCompose();
            fs.writeFileSync(file, contents);
            return jsonResult({
                file,
                stack: isPhp
                    ? detected.backend?.kind
                    : (detected.frontend?.kind ?? detected.backend?.kind ?? 'node'),
                services: ['app', 'db', 'redis'],
                package: packageName ?? null,
            });
        }
        catch (error) {
            return errorResult(toErrorMessage(error));
        }
    });
}
export function registerGenerateSailTool(server) {
    server.registerTool('generate_sail', {
        title: 'Install Laravel Sail',
        description: 'Run `php artisan sail:install` in a detected Laravel project. Requires confirm: true because it modifies docker-compose and related files.',
        inputSchema: {
            with: z
                .array(z.string())
                .optional()
                .describe('Optional Sail services, e.g. ["mysql", "redis", "mailpit"].'),
            confirm: z.boolean().optional().describe('Required as true to run sail:install.'),
        },
    }, async ({ with: services, confirm }) => {
        try {
            if (confirm !== true) {
                return errorResult('generate_sail requires confirm: true.');
            }
            const laravel = requireLaravel();
            const args = ['artisan', 'sail:install', '--no-interaction'];
            if (services && services.length > 0) {
                args.push(`--with=${services.join(',')}`);
            }
            const result = await runCommand('php', args, {
                cwd: laravel.root,
                timeoutMs: config.scaffoldCommandTimeoutMs,
            });
            return jsonResult({
                services: services ?? null,
                exitCode: result.exitCode,
                failed: result.failed,
                output: result.output,
                cwd: result.cwd,
            });
        }
        catch (error) {
            return errorResult(toErrorMessage(error));
        }
    });
}
//# sourceMappingURL=generate.js.map