'use strict';

/**
 * Contract: dashboard create
 *
 * Generate dashboard endpoint module dari payload (multi-widget aggregator).
 * Emits src/modules/{project}/{name}.js dengan embedded SQL.
 *
 * Inline migration v4.0.0: business logic dari create-dashboard.js
 * dipindah ke handler. Flag legacy `--validate-only` tidak di-expose di
 * contract Fase 04, sehingga inline minimal tanpa support validate-only mode
 * (per keputusan Phase 2 #2).
 */

const fs = require('fs');
const path = require('path');
const PayloadValidator = require('../../lib/validators/payload-validator');
const PayloadProcessor = require('../../lib/utils/payload-processor');
const DashboardValidator = require('../../lib/validators/dashboard-validator');
const MainModuleGenerator = require('../../lib/generators/main-module-generator');
const DashboardGenerator = require('../../lib/generators/dashboard-generator');
const MetadataManager = require('../../lib/utils/metadata-manager');
const projectRegistry = require('../../lib/utils/project-registry');
const cliOutput = require('../../lib/utils/cli-output');
const { validateSafeName } = require('../../lib/utils/path-validator');

module.exports = {
    resource: 'dashboard',
    verb: 'create',
    description: 'Generate dashboard endpoint module dari payload (multi-widget aggregator)',
    category: 'generation',
    flags: {
        project: {
            type: 'string',
            required: true,
            description: 'Nama project target'
        },
        name: {
            type: 'string',
            required: true,
            description: 'Nama dashboard (wajib diawali "dash-", mis. dash-sales)'
        },
        payload: {
            type: 'string',
            required: true,
            description: 'Path atau nama file payload JSON dashboard'
        },
        database: {
            type: 'string',
            required: false,
            default: null,
            description: 'Tipe database (postgres|mysql|oracle|sqlite). Default: postgres'
        },
        force: {
            type: 'boolean',
            required: false,
            default: false,
            description: 'Timpa file existing di output directory'
        },
        'skip-sql-validation': {
            type: 'boolean',
            required: false,
            default: false,
            description: 'Lewati validasi keyword SQL'
        }
    },
    examples: [
        'npx restforge dashboard create --project=mini-inventory --name=dash-sales --payload=dashboard-sales.json',
        'npx restforge dashboard create --project=mini-inventory --name=dash-sales --payload=dashboard-sales.json --force'
    ],
    async handler(args) {
        const startTime = Date.now();
        let muted = false;

        try {
            const project = args.project && args.project.trim();
            const name = args.name && args.name.trim();
            const payloadName = args.payload && args.payload.trim();
            const database = args.database || 'postgres';
            const force = !!args.force;
            const skipSqlValidation = !!args['skip-sql-validation'];

            if (!project) {
                throw new Error('Missing required argument: --project');
            }
            if (!name) {
                throw new Error('Missing required argument: --name (dashboard name)');
            }
            if (!name.startsWith('dash-')) {
                throw new Error("--name must start with 'dash-' prefix (e.g. --name=dash-sales). The prefix becomes part of the URL segment.");
            }
            if (name === 'dash-' || name.length < 6) {
                throw new Error("--name must contain a non-empty suffix after 'dash-' (e.g. --name=dash-sales)");
            }
            validateSafeName(project, 'project');
            validateSafeName(name, 'dashboard name');
            if (!payloadName) {
                throw new Error('Missing required argument: --payload');
            }

            cliOutput.mute();
            muted = true;

            const cwd = process.cwd();
            const summary = {
                config: { project, dashboard: name, database, force },
                payload: null,
                archive: null,
                generated: [],
                endpoint: null
            };

            const payloadPath = PayloadValidator.findPayloadFile(payloadName);
            if (!payloadPath) {
                throw new Error(`Payload file not found: ${payloadName}`);
            }

            const rawPayload = JSON.parse(fs.readFileSync(payloadPath, 'utf8'));
            const payloadDir = path.dirname(payloadPath);

            const payload = PayloadProcessor.processPayload(rawPayload, payloadPath, {
                moduleName: project,
                skipSqlValidation
            });

            DashboardValidator.validateDashboardPayload(payload, payloadDir, {
                projectName: project,
                metadataDir: path.join(cwd, 'metadata')
            });

            summary.payload = {
                source: cliOutput.toRelative(payloadPath, cwd),
                status: 'validated',
                warnings: cliOutput.drainWarnings()
            };

            const registry = projectRegistry.loadProjectRegistry();
            if (registry.projects[project]) {
                const existing = registry.projects[project];
                if (existing.database && database && existing.database !== database && !force) {
                    if (muted) cliOutput.unmute();
                    console.error(`Project "${project}" is already registered with database type "${existing.database}".`);
                    console.error(`Cannot change to "${database}" without --force.`);
                    throw new Error(`Project "${project}" already registered with database "${existing.database}"`);
                }
            }

            MainModuleGenerator.createMainModule(project, database, { force });
            const mainModulePath = path.join(cwd, 'src', 'modules', `${project}.js`);
            if (fs.existsSync(mainModulePath)) {
                summary.generated.push({
                    path: cliOutput.toRelative(mainModulePath, cwd),
                    size: cliOutput.formatSize(fs.statSync(mainModulePath).size)
                });
            }

            const result = DashboardGenerator.createDashboardModule(project, name, payload, {
                force,
                payloadDir,
                database
            });

            if (result.archivedPath) {
                summary.archive = {
                    path: cliOutput.toRelative(result.archivedPath, cwd)
                };
            }

            if (result.filePath && fs.existsSync(result.filePath)) {
                summary.generated.push({
                    path: cliOutput.toRelative(result.filePath, cwd),
                    size: cliOutput.formatSize(fs.statSync(result.filePath).size)
                });
            }

            MetadataManager.updateDashboardMetadata(project, name, payload, database);

            projectRegistry.registerProject(project, database, name);

            summary.endpoint = `POST /api/${project}/${name}/dashboard`;

            if (muted) {
                cliOutput.unmute();
                muted = false;
            }

            summary.duration = ((Date.now() - startTime) / 1000).toFixed(2);
            cliOutput.printDashboardSummary(summary);
        } catch (error) {
            if (muted) cliOutput.unmute();
            console.error(`Error: ${error.message}`);
            throw error;
        }
    }
};
