"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getDBMLData = exports.addTable = void 0;
/* eslint-disable no-nested-ternary */
const core_1 = require("@asapjs/core");
const promises_1 = __importDefault(require("fs/promises"));
const idColumnData = `id int PK`;
class DBMLApplication {
    constructor() {
        this.tableNames = {};
        this.tables = [];
        this.relations = [];
        this.enums = [];
        this.generatedDBMLData = null;
        this.addTable = (name, className, data) => __awaiter(this, void 0, void 0, function* () {
            this.tableNames = Object.assign(Object.assign({}, this.tableNames), { [className]: name });
            // console.log(this.tableNames);
            const tableInfo = { name, columns: [], data };
            this.tables.push(tableInfo);
        });
        this.generateProjectData = () => {
            var _a;
            const config = (0, core_1.getConfig)();
            const projectName = config === null || config === void 0 ? void 0 : config.projectName;
            const databaseType = ((_a = config === null || config === void 0 ? void 0 : config.db) === null || _a === void 0 ? void 0 : _a.dialect) || 'MySQL';
            return `Project ${projectName} {
  database_type: '${databaseType}'
  Note: '''
    # ${projectName}-erd
  '''
}`;
        };
        this.generateEnumColumn = (columnData) => {
            return `${columnData.name} ${columnData.type} ${columnData.note ? `[note: '${columnData.note}']` : ''}`;
        };
        this.generateGeneralColumn = (columnData) => {
            return `${columnData.name} ${columnData.type} ${columnData.note ? `[note: '${columnData.note}']` : ''}`;
        };
        this.generateTableData = (tableInfo) => {
            const columnDatas = tableInfo.columns.map((v) => {
                if (v.type === 'enum') {
                    return this.generateEnumColumn(v);
                }
                else {
                    return this.generateGeneralColumn(v);
                }
            });
            return `Table ${tableInfo.name} {
  ${[idColumnData, ...columnDatas].join('\n  ')}
}`;
        };
        this.generateEnumData = (enumData) => {
            return `Enum ${enumData.name} {
  ${enumData.values.join('\n  ')}
}`;
        };
        this.generateRelationData = (relationInfo) => {
            var _a;
            return `ref: ${relationInfo.fromTableName}.${relationInfo.fromTableColumnName} > ${((_a = this.tableNames) === null || _a === void 0 ? void 0 : _a[relationInfo.toTableClassName]) || relationInfo.toTableClassName}.id`;
        };
        this.generateDBMLData = () => __awaiter(this, void 0, void 0, function* () {
            const projectData = this.generateProjectData();
            const tableData = yield Promise.all(this.tables.map((tableInfo) => {
                Object.entries(tableInfo.data).forEach(([key, v]) => {
                    var _a, _b, _c, _d;
                    if (v.__name === 'foreignkey') {
                        tableInfo.columns.push({
                            name: key,
                            type: 'int',
                            note: '',
                        });
                        this.relations.push({
                            fromTableName: tableInfo === null || tableInfo === void 0 ? void 0 : tableInfo.name,
                            fromTableColumnName: key,
                            toTableClassName: (_a = v.toSequelize) === null || _a === void 0 ? void 0 : _a.call(v)().name,
                        });
                    }
                    else if (v.__name !== 'belongsto') {
                        const enumData = (_c = (_b = v.toSwagger) === null || _b === void 0 ? void 0 : _b.call(v)) === null || _c === void 0 ? void 0 : _c.enum;
                        const enumName = `${tableInfo === null || tableInfo === void 0 ? void 0 : tableInfo.name}_${key}_enum`;
                        tableInfo.columns.push({
                            name: key,
                            type: enumData ? enumName : v.__name,
                            note: (_d = v.toSwagger) === null || _d === void 0 ? void 0 : _d.call(v).description,
                            enum: enumData,
                        });
                        if (enumData) {
                            this.enums.push({
                                name: enumName,
                                values: enumData,
                            });
                        }
                    }
                });
                return tableInfo;
            }));
            const tableDatas = tableData.map((table) => this.generateTableData(table));
            const enumDatas = this.enums.map((enumData) => this.generateEnumData(enumData));
            const relationDatas = this.relations.map((relationData) => this.generateRelationData(relationData));
            const combinedData = [projectData, ...tableDatas, ...enumDatas, ...relationDatas];
            this.generatedDBMLData = combinedData.join('\n\n');
        });
        this.getDBMLData = () => __awaiter(this, void 0, void 0, function* () {
            if (this.generatedDBMLData === null) {
                this.generateDBMLData();
            }
            yield promises_1.default.mkdir('./src/dbml', { recursive: true });
            yield promises_1.default.writeFile('./src/dbml/database.dbml', this.generatedDBMLData);
            return this.generatedDBMLData;
        });
    }
}
_a = new DBMLApplication(), exports.addTable = _a.addTable, exports.getDBMLData = _a.getDBMLData;
//# sourceMappingURL=index.js.map