#!/usr/bin/env node
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.genProto = genProto;
const node_child_process_1 = require("node:child_process");
const node_fs_1 = require("node:fs");
const node_path_1 = require("node:path");
const env_1 = require("../env");
function genProto(args = process.argv.slice(2)) {
    if (args.includes('-h') || args.includes('--help')) {
        printUsage();
        return 0;
    }
    if (args.length < 2) {
        printUsage();
        return 1;
    }
    const inputPath = (0, node_path_1.resolve)(args[0]);
    const outputDir = (0, node_path_1.resolve)(args[1]);
    if (!(0, node_fs_1.existsSync)(inputPath)) {
        console.error(`Error: Input path does not exist: ${inputPath}`);
        return 1;
    }
    const { protoFiles, protoDir, outputBaseName } = collectProtoFiles(inputPath);
    if (protoFiles.length === 0) {
        console.log('No .proto files found, nothing to generate.');
        return 0;
    }
    (0, node_fs_1.mkdirSync)(outputDir, { recursive: true });
    const plugin = findTsProtoPlugin();
    if (!plugin) {
        console.error('Error: ts-proto not found. Reinstall @zyno-io/ts-server-foundation or add ts-proto to the current project.');
        return 1;
    }
    const options = buildTsProtoOptions(args.slice(2));
    const protoc = resolveProtocCommand();
    const result = (0, node_child_process_1.spawnSync)(protoc.command, [
        ...protoc.args,
        `--plugin=protoc-gen-ts_proto=${plugin}`,
        `--ts_proto_out=${outputDir}`,
        `--ts_proto_opt=${options.join(',')}`,
        `-I${protoDir}`,
        ...protoFiles
    ], { stdio: 'inherit' });
    if (result.error) {
        console.error(result.error.message);
        return 1;
    }
    if (result.status !== 0)
        return result.status ?? 1;
    console.log(`Generated ${protoFiles.length} proto file(s) into ${outputDir}.`);
    console.log(`Import generated types from ${(0, node_path_1.join)(outputDir, outputBaseName).replace(process.cwd(), '.')}.`);
    return 0;
}
function resolveProtocCommand() {
    if (env_1.Env.PROTOC)
        return { command: env_1.Env.PROTOC, args: [] };
    const bundledProtoc = findProtocBin();
    if (bundledProtoc)
        return { command: process.execPath, args: [bundledProtoc] };
    return { command: 'protoc', args: [] };
}
function printUsage() {
    console.log(`Usage: tsf-gen-proto <proto-file-or-dir> <output-dir> [options]

Options:
  --only-types       Only generate type definitions
  --use-date         Use Date for google.protobuf.Timestamp
  --use-map-type     Use ES6 Map for proto maps`);
}
function collectProtoFiles(inputPath) {
    const stat = (0, node_fs_1.statSync)(inputPath);
    if (stat.isFile()) {
        if (!inputPath.endsWith('.proto'))
            throw new Error(`Input file must be a .proto file: ${inputPath}`);
        return {
            protoFiles: [inputPath],
            protoDir: (0, node_path_1.dirname)(inputPath),
            outputBaseName: (0, node_path_1.basename)(inputPath, '.proto')
        };
    }
    if (!stat.isDirectory())
        throw new Error(`Input path is neither a file nor directory: ${inputPath}`);
    return {
        protoFiles: (0, node_fs_1.readdirSync)(inputPath)
            .filter(file => file.endsWith('.proto'))
            .map(file => (0, node_path_1.join)(inputPath, file)),
        protoDir: inputPath,
        outputBaseName: 'proto'
    };
}
function findTsProtoPlugin() {
    return findPackageBin('ts-proto', 'protoc-gen-ts_proto');
}
function findProtocBin() {
    return findPackageBin('protoc', 'protoc');
}
function findPackageBin(packageName, binName) {
    try {
        const packageJson = require.resolve(`${packageName}/package.json`, {
            paths: [process.cwd(), __dirname]
        });
        const manifest = JSON.parse((0, node_fs_1.readFileSync)(packageJson, 'utf8'));
        const bin = typeof manifest.bin === 'string' ? manifest.bin : manifest.bin?.[binName];
        if (!bin)
            return undefined;
        const binPath = (0, node_path_1.join)((0, node_path_1.dirname)(packageJson), bin);
        return (0, node_fs_1.existsSync)(binPath) ? binPath : undefined;
    }
    catch {
        return undefined;
    }
}
function buildTsProtoOptions(args) {
    const options = [];
    if (args.includes('--only-types'))
        options.push('onlyTypes=true');
    if (!args.includes('--use-date'))
        options.push('useDate=false');
    if (!args.includes('--use-map-type'))
        options.push('useMapType=false');
    options.push('esModuleInterop=true', 'outputServices=false');
    return options;
}
if (require.main === module) {
    try {
        process.exit(genProto());
    }
    catch (error) {
        console.error(error instanceof Error ? error.message : error);
        process.exit(1);
    }
}
//# sourceMappingURL=tsf-gen-proto.js.map