import { compile } from 'json-schema-to-typescript';
import { sharedJSONSchemaTypes, sharedSchemaReferences } from '../types.js';
import fs from 'fs';
import { definitions as bankAccountDefinitions } from '../addresses/bank-account/index.generated.js';
import { definitions as mobileWalletAccountDefinitions } from '../addresses/mobile-wallet/index.generated.js';
function firstCharUpper(str) {
    if (str.length === 0) {
        return (str);
    }
    return (str.charAt(0).toUpperCase() + str.slice(1));
}
function toPascalCase(str) {
    const split = str.split(/[-_]/g);
    const mapped = split.map(function (part) {
        return (firstCharUpper(part));
    });
    return (mapped.join(''));
}
async function compileToString(schema, name) {
    return (await compile(schema, name, {
        additionalProperties: false,
        bannerComment: ''
    }));
}
function parseArgs(argv) {
    let typesOutput = undefined;
    for (const arg of argv) {
        if (arg.startsWith('--types-output=')) {
            typesOutput = arg.substring('--types-output='.length);
        }
    }
    if (!typesOutput?.endsWith('.ts')) {
        throw (new Error('Missing or invalid required argument: --types-output=path/to/types.generated.ts'));
    }
    return ({
        typesOutput
    });
}
(async function () {
    const config = parseArgs(process.argv.slice(2));
    const out = [];
    out.push('// This file is generated by src/services/asset-movement/lib/data/scripts/generator.ts - do not edit');
    out.push('import type { ISOCountryCode } from "@keetanetwork/currency-info";');
    const obfuscatedNames = {
        'mobile-wallet': [],
        'bank-account': []
    };
    const resolvedNames = {
        'mobile-wallet': [],
        'bank-account': []
    };
    const allDefinitions = { ...sharedJSONSchemaTypes };
    for (const [schemaType, schemas] of [
        ['mobile-wallet', mobileWalletAccountDefinitions],
        ['bank-account', bankAccountDefinitions]
    ]) {
        for (const [name, schema] of Object.entries(schemas)) {
            for (const value of ['resolved', 'obfuscated']) {
                const interfaceName = toPascalCase(`${name}_${schemaType}_${value}`);
                const allOfIncludes = [];
                if (schema.includeFields.accountOwner) {
                    if (value === 'resolved') {
                        allOfIncludes.push(sharedSchemaReferences.ResolvedAccountOwner);
                    }
                    else {
                        allOfIncludes.push(sharedSchemaReferences.ObfuscatedAccountOwner);
                    }
                }
                if (schema.includeFields.phoneNumber) {
                    allOfIncludes.push(sharedSchemaReferences.PhoneNumberObjectExtends);
                }
                if (schema.includeFields.bankName) {
                    allOfIncludes.push({
                        type: 'object',
                        properties: {
                            bankName: { type: 'string' }
                        }
                    });
                }
                if (schema.includeFields.accountNumberEnding && value === 'obfuscated') {
                    allOfIncludes.push({
                        type: 'object',
                        properties: {
                            accountNumberEnding: { type: 'string' }
                        }
                    });
                }
                allDefinitions[interfaceName] = {
                    allOf: [
                        ...(schema.additionalProperties?.[value] ? [schema.additionalProperties[value]] : []),
                        {
                            type: 'object',
                            properties: {
                                type: { const: schemaType },
                                accountType: { const: name },
                                obfuscated: { const: value === 'obfuscated' }
                            },
                            required: [
                                'type', 'accountType',
                                ...(value === 'resolved' ? [] : ['obfuscated'])
                            ]
                        },
                        ...allOfIncludes
                    ]
                };
                if (value === 'resolved') {
                    resolvedNames[schemaType].push(interfaceName);
                }
                else {
                    obfuscatedNames[schemaType].push(interfaceName);
                }
            }
        }
    }
    const unionsToMake = [
        ['BankAccountAddressResolved', resolvedNames['bank-account']],
        ['BankAccountAddressObfuscated', obfuscatedNames['bank-account']],
        ['MobileWalletAddressResolved', resolvedNames['mobile-wallet']],
        ['MobileWalletAddressObfuscated', obfuscatedNames['mobile-wallet']],
        ['GeneratedAddressResolved', ['BankAccountAddressResolved', 'MobileWalletAddressResolved']],
        ['GeneratedAddressObfuscated', ['BankAccountAddressObfuscated', 'MobileWalletAddressObfuscated']]
    ];
    for (const [unionName, memberNames] of unionsToMake) {
        allDefinitions[unionName] = { oneOf: memberNames.map((name) => ({ $ref: `#/definitions/${name}` })) };
    }
    const jsonSchemaDefinitions = { definitions: allDefinitions };
    const compiled = await compileToString({
        ...jsonSchemaDefinitions,
        oneOf: Object.keys(allDefinitions).map((name) => ({ $ref: `#/definitions/${name}` }))
    }, 'TempType');
    const compiledWithoutTemp = compiled.replaceAll(/export type (TempType|ISOCountryCode) =([\w\n |'"]+);\n/gm, '');
    out.push(compiledWithoutTemp);
    const schema = JSON.stringify(jsonSchemaDefinitions, null, 2);
    out.push(`export const accountJSONSchema = ${schema} as const;`);
    fs.writeFileSync(config.typesOutput, out.join('\n'));
})().catch(function (err) {
    console.error(err);
    process.exit(1);
});
//# sourceMappingURL=generator.js.map