#!/usr/bin/env node
/* eslint-disable security/detect-object-injection, @typescript-eslint/no-explicit-any */
/**
 * from-schema CLI
 *
 * Usage:
 *   from-schema generate <type> --models <path> --output <dir> [options]
 *
 * Types:
 *   json-models   Generate TypeScript types + TSON schemas from PostgreSQL models
 *   db-types      Generate Kysely Database type from PostgreSQL models
 *   api-types     Generate request/response TypeScript types from API models
 *   handles       Generate server handler factories from API models
 *   client        Generate type-safe API client from API models
 *
 * Examples:
 *   from-schema generate json-models --models ./src/pg-models --output ./dist/json-models
 *   from-schema generate handles --models ./src/api-models --output ./dist/handles \
 *     --models-pkg @myapp/api-models --types-pkg @myapp/api-types
 *   from-schema generate client --models ./src/api-models --output ./dist/client \
 *     --types-pkg @myapp/api-types
 */

import { resolve } from 'path';
import {
	generateJsonModels,
	generateDbTypes,
	generateApiTypes,
	generateHandles,
	generateClient,
} from './generators';

function parseArgs(argv: string[]): Record<string, string> {
	const args: Record<string, string> = {};
	for (let i = 0; i < argv.length; i++) {
		const arg = argv[i];
		if (arg.startsWith('--')) {
			const key = arg.slice(2);
			const next = argv[i + 1];
			if (next && !next.startsWith('--')) {
				args[key] = next;
				i++;
			} else {
				args[key] = 'true';
			}
		} else if (!args['_cmd']) {
			args['_cmd'] = arg;
		} else if (!args['_sub']) {
			args['_sub'] = arg;
		}
	}
	return args;
}

function required(args: Record<string, string>, key: string): string {
	const val = args[key];
	if (!val) {
		console.error(`Missing required argument: --${key}`);
		process.exit(1);
	}
	return val;
}

async function loadModule(
	modulePath: string,
): Promise<Record<string, unknown>> {
	const resolved = resolve(modulePath);
	return import(resolved);
}

async function main() {
	const args = parseArgs(process.argv.slice(2));
	const cmd = args['_cmd'];
	const sub = args['_sub'];

	if (cmd !== 'generate' || !sub) {
		console.error(
			'Usage: from-schema generate <json-models|db-types|api-types|handles|client> [options]',
		);
		process.exit(1);
	}

	const outputDir = required(args, 'output');

	switch (sub) {
		case 'json-models': {
			const models = await loadModule(required(args, 'models'));
			const extras = args['extras']
				? await loadModule(args['extras'])
				: undefined;
			await generateJsonModels({
				models: models as Record<string, unknown>,
				extras: extras as Record<string, unknown> | undefined,
				outputDir,
			});
			console.log(`Generated json-models → ${outputDir}`);
			break;
		}

		case 'db-types': {
			const tables = await loadModule(required(args, 'models'));
			await generateDbTypes({
				tables: tables as Record<string, unknown>,
				outputDir,
				outputFile: args['file'] || 'index.d.ts',
			});
			console.log(`Generated db-types → ${outputDir}`);
			break;
		}

		case 'api-types': {
			const models = await loadModule(required(args, 'models'));
			await generateApiTypes({
				models: models as Record<string, any>,
				outputDir,
				typesName: args['types-name'] || 'ApiTypes',
			});
			console.log(`Generated api-types → ${outputDir}`);
			break;
		}

		case 'handles': {
			const models = await loadModule(required(args, 'models'));
			await generateHandles({
				models: models as Record<string, any>,
				outputDir,
				modelsPackage: required(args, 'models-pkg'),
				typesPackage: required(args, 'types-pkg'),
				contextPackage: args['context-pkg'] || '@lyku/lockstep-core/contexts',
				typesName: args['types-name'] || 'ApiTypes',
			});
			console.log(`Generated handles → ${outputDir}`);
			break;
		}

		case 'client': {
			const models = await loadModule(required(args, 'models'));
			await generateClient({
				models: models as Record<string, any>,
				outputDir,
				typesPackage: required(args, 'types-pkg'),
				typesName: args['types-name'] || 'ApiTypes',
			});
			console.log(`Generated client → ${outputDir}`);
			break;
		}

		default:
			console.error(`Unknown generator: ${sub}`);
			console.error(
				'Available: json-models, db-types, api-types, handles, client',
			);
			process.exit(1);
	}
}

main().catch((err) => {
	console.error(err);
	process.exit(1);
});
