'use strict';

/**
 * Contract: query validate
 *
 * Validate SQL statement (SELECT/CTE) terhadap database live menggunakan
 * EXPLAIN (read-only, tidak mengeksekusi data modification). SELECT-only
 * enforcement terjadi sebelum koneksi DB via regex sederhana.
 *
 * Inline migration v4.0.0: business logic asli dari `query-validate.js`
 * di-inline langsung ke handler. Adapter `process.argv` override dihapus.
 * `process.exit()` di legacy dikonversi menjadi `throw new Error(...)` agar
 * `cli-entry.js` yang handle exit code.
 */

const { DatabaseIntrospector } = require('../../lib/utils/database-introspector');
const { resolveConfig, printDefaultConfigWarning } = require('../../lib/utils/config-resolver');

function isReadOnlySql(sql) {
    const stripped = sql
        .split('\n')
        .filter(line => !line.trim().startsWith('--'))
        .join('\n')
        .trim();
    return /^(SELECT|WITH)\b/i.test(stripped);
}

module.exports = {
    resource: 'query',
    verb: 'validate',
    description: 'Validate SQL statement (SELECT/CTE) terhadap database live menggunakan EXPLAIN (read-only, tidak mengeksekusi data modification)',
    category: 'introspection',
    flags: {
        config: {
            type: 'string',
            required: false,
            default: null,
            description: 'File config database (.env). Fallback ke `.restforge/defaults.json` bila tidak disediakan eksplisit (set via `config set-default`)'
        },
        sql: {
            type: 'string',
            required: true,
            description: 'SQL statement untuk divalidasi (hanya SELECT atau WITH/CTE)'
        },
        pretty: {
            type: 'boolean',
            required: false,
            default: true,
            description: 'Pretty-print output JSON'
        }
    },
    examples: [
        'npx restforge query validate --config=db.env --sql="SELECT * FROM users WHERE id = 1"',
        'npx restforge query validate --config=db.env --sql="WITH t AS (SELECT 1 a) SELECT * FROM t"'
    ],
    async handler(args) {
        const resolved = resolveConfig(args.config, process.cwd());
        if (!resolved) {
            console.error('Error: --config=<file.env> is required');
            console.error("Tip: set a default with 'npx restforge config set-default --config=<file>' to omit --config in future runs");
            console.error("Run 'npx restforge query validate --help' for usage information");
            throw new Error('--config=<file.env> is required');
        }

        if (!isReadOnlySql(args.sql)) {
            const preview = args.sql.trim().substring(0, 50);
            console.error(`Error: Only SELECT or WITH (CTE) statements are allowed. Got: ${preview}`);
            throw new Error('Only SELECT or WITH (CTE) statements are allowed');
        }

        if (resolved.source === 'default') {
            printDefaultConfigWarning(resolved.defaultName);
        }

        const introspector = new DatabaseIntrospector({ quiet: true });
        const configPath = resolved.path;

        if (!introspector.loadConfig(configPath)) {
            throw new Error(`Failed to load config from ${configPath}`);
        }

        const connected = await introspector.connect();
        if (!connected) {
            throw new Error('Failed to connect to database');
        }

        try {
            const result = await introspector.validateQuery(args.sql);

            const output = {
                schemaVersion: '1.0',
                source: 'query-validate',
                ok: result.ok,
                database: introspector.dbType,
                ...(result.error ? { error: result.error } : {})
            };

            const json = args.pretty
                ? JSON.stringify(output, null, 2)
                : JSON.stringify(output);
            process.stdout.write(json + '\n');
        } catch (error) {
            console.error(`Error: ${error.message}`);
            if (process.env.DEBUG) {
                console.error(error.stack);
            }
            throw error;
        } finally {
            await introspector.disconnect();
        }
    }
};
