"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 };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.writeRealizeControllers = void 0;
const NestiaMigrateNestMethodProgrammer_1 = require("@nestia/migrate/lib/programmers/NestiaMigrateNestMethodProgrammer");
const path_1 = __importDefault(require("path"));
const typescript_1 = __importDefault(require("typescript"));
const createMigrateApplication_1 = require("../interface/createMigrateApplication");
const ArrayUtil_1 = require("../utils/ArrayUtil");
const FilePrinter_1 = require("../utils/FilePrinter");
const writeRealizeControllers = (props) => __awaiter(void 0, void 0, void 0, function* () {
    const app = (0, createMigrateApplication_1.createMigrateApplication)(props.document);
    const result = app.nest({
        simulate: false,
        e2e: false,
        programmer: {
            controllerMethod: (ctx) => {
                const method = NestiaMigrateNestMethodProgrammer_1.NestiaMigrateNestMethodProgrammer.write(ctx);
                const func = props.functions.find((f) => f.endpoint.method === ctx.route.method &&
                    f.endpoint.path === ctx.route.path);
                if (func === undefined)
                    return method; // unreachable
                const auth = func.role
                    ? props.authorizations.find((d) => d.role === func.role)
                    : undefined;
                if (func.role && auth === undefined)
                    return method; // unreachable
                ctx.importer.external({
                    type: "instance",
                    library: path_1.default
                        .relative(ctx.controller.location, func.location)
                        .replaceAll(path_1.default.sep, "/")
                        .split(".ts")[0],
                    name: func.name,
                });
                const call = typescript_1.default.factory.createCallExpression(typescript_1.default.factory.createIdentifier(func.name), undefined, [
                    ...(func.role ? [func.role] : []),
                    ...ctx.route.parameters.map((p) => p.name),
                    ...(ctx.route.query ? [ctx.route.query.name] : []),
                    ...(ctx.route.body ? [ctx.route.body.name] : []),
                ].map((name) => typescript_1.default.factory.createIdentifier(name)));
                return typescript_1.default.factory.updateMethodDeclaration(method, method.modifiers, method.asteriskToken, method.name, method.questionToken, method.typeParameters, auth
                    ? [
                        typescript_1.default.factory.createParameterDeclaration([
                            typescript_1.default.factory.createDecorator(typescript_1.default.factory.createCallExpression(typescript_1.default.factory.createIdentifier(ctx.importer.external({
                                type: "instance",
                                library: path_1.default
                                    .relative(ctx.controller.location, auth.decorator.location)
                                    .replaceAll(path_1.default.sep, "/")
                                    .split(".ts")[0],
                                name: auth.decorator.name,
                            })), undefined, [])),
                        ], undefined, auth.role, undefined, typescript_1.default.factory.createTypeReferenceNode(ctx.importer.external({
                            type: "instance",
                            library: path_1.default
                                .relative(ctx.controller.location, auth.payload.location)
                                .replaceAll(path_1.default.sep, "/")
                                .split(".ts")[0],
                            name: auth.payload.name,
                        })), undefined),
                        ...method.parameters,
                    ]
                    : method.parameters, method.type, typescript_1.default.factory.createBlock([typescript_1.default.factory.createReturnStatement(call)]));
            },
        },
    });
    const entries = yield ArrayUtil_1.ArrayUtil.asyncMap(Object.entries(result).filter(([key]) => key.startsWith("src/controllers/")), (_a) => __awaiter(void 0, [_a], void 0, function* ([key, value]) { return [key, yield FilePrinter_1.FilePrinter.beautify(value)]; }));
    return Object.fromEntries(entries);
});
exports.writeRealizeControllers = writeRealizeControllers;
//# sourceMappingURL=writeRealizeControllers.js.map