"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const core_1 = require("@cromwell/core");
const cms_settings_1 = require("@cromwell/core-backend/dist/helpers/cms-settings");
const logger_1 = require("@cromwell/core-backend/dist/helpers/logger");
const paths_1 = require("@cromwell/core-backend/dist/helpers/paths");
const CRestApiClient_1 = require("@cromwell/core-frontend/dist/api/CRestApiClient");
const static_1 = require("@cromwell/utils/build/static");
const fs_extra_1 = __importDefault(require("fs-extra"));
const normalize_path_1 = __importDefault(require("normalize-path"));
const path_1 = require("path");
const symlink_dir_1 = __importDefault(require("symlink-dir"));
const yargs_parser_1 = __importDefault(require("yargs-parser"));
const logger = (0, logger_1.getLogger)();
const start = async () => {
    const args = (0, yargs_parser_1.default)(process.argv.slice(2));
    if (args.serverUrl) {
        process.env.API_URL = args.serverUrl;
    }
    const env = process.argv[2];
    const isProduction = env === 'production' || env === 'prod';
    const isDevelopment = env === 'development' || env === 'dev';
    if (!isDevelopment && !isProduction)
        throw `devServer::startDevServer: process.argv[2] is invalid - ${env} valid values - "development" and "production"`;
    const configsDir = isDevelopment
        ? (0, path_1.resolve)((0, paths_1.getAdminPanelTempDir)((0, paths_1.getAdminPanelDir)()), 'configs')
        : (0, path_1.resolve)((0, paths_1.getAdminPanelTempDir)(), 'configs');
    await linkFiles({ isProduction, configsDir });
    await outputEnv({ isProduction, configsDir });
    if (isProduction) {
        await startProdServer(args.port);
    }
    else {
        // await startDevServer(args.port);
    }
    logger.info('Admin startup successfully ran');
};
const linkFiles = async ({ isProduction, configsDir }) => {
    const projectPublicDir = (0, normalize_path_1.default)((0, paths_1.getPublicDir)());
    const adminPanelStaticDir = (0, normalize_path_1.default)((0, paths_1.getAdminPanelStaticDir)());
    const webTempDir = (0, normalize_path_1.default)((0, paths_1.getAdminPanelTempDir)());
    const adminPublicStaticDir = (0, path_1.resolve)(projectPublicDir, 'admin/static');
    if (!fs_extra_1.default.pathExistsSync(webTempDir))
        await fs_extra_1.default.ensureDir(webTempDir);
    fs_extra_1.default.ensureDirSync(configsDir);
    if (isProduction) {
        const tempPublicDir = (0, normalize_path_1.default)((0, paths_1.getAdminPanelWebPublicDir)());
        const serviceNextBuildDir = (0, path_1.resolve)((0, paths_1.getAdminPanelServiceBuildDir)(), '.next');
        const tempNextBuildDir = (0, path_1.resolve)(webTempDir, '.next');
        // Remove old links
        await fs_extra_1.default.remove(tempPublicDir).catch(() => null);
        await fs_extra_1.default.remove(tempNextBuildDir).catch(() => null);
        await new Promise((res) => setTimeout(res, 500));
        // console.log('publicDir', publicDir);
        // Link public dir in project root to admin panel temp public dir for Fastify web server
        if (fs_extra_1.default.pathExistsSync(projectPublicDir)) {
            if (!fs_extra_1.default.pathExistsSync(tempPublicDir)) {
                await (0, symlink_dir_1.default)(projectPublicDir, tempPublicDir);
            }
        }
        else {
            fs_extra_1.default.ensureDirSync(tempPublicDir);
        }
        // Link admin static
        if (fs_extra_1.default.pathExistsSync(adminPanelStaticDir) && !fs_extra_1.default.pathExistsSync(adminPublicStaticDir)) {
            await (0, symlink_dir_1.default)(adminPanelStaticDir, adminPublicStaticDir);
        }
        // Link prod next.js build
        if (!fs_extra_1.default.existsSync(tempNextBuildDir) && fs_extra_1.default.existsSync(serviceNextBuildDir)) {
            await (0, symlink_dir_1.default)(serviceNextBuildDir, tempNextBuildDir);
        }
        fs_extra_1.default.copyFileSync((0, path_1.resolve)((0, paths_1.getAdminPanelDir)(), 'next.config.js'), (0, path_1.resolve)(webTempDir, 'next.config.js'));
    }
    else {
        // Link public dir in project root to admin panel temp public dir
        const publicDir = (0, path_1.resolve)((0, paths_1.getAdminPanelDir)(), 'public');
        fs_extra_1.default.ensureDirSync(projectPublicDir);
        if (fs_extra_1.default.pathExistsSync(projectPublicDir)) {
            if (!fs_extra_1.default.pathExistsSync(publicDir)) {
                await (0, symlink_dir_1.default)(projectPublicDir, publicDir);
            }
        }
        else {
            fs_extra_1.default.ensureDirSync(publicDir);
        }
        // Link admin static
        if (fs_extra_1.default.pathExistsSync(adminPanelStaticDir) && !fs_extra_1.default.pathExistsSync(adminPublicStaticDir)) {
            await (0, symlink_dir_1.default)(adminPanelStaticDir, adminPublicStaticDir);
        }
    }
};
const outputEnv = async ({ isProduction, configsDir }) => {
    var _a;
    let cmsSettings = (0, cms_settings_1.readCMSConfigSync)();
    (0, core_1.setStoreItem)('cmsSettings', cmsSettings);
    try {
        cmsSettings = (_a = (await (0, CRestApiClient_1.getRestApiClient)().getCmsSettings())) !== null && _a !== void 0 ? _a : cmsSettings;
        (0, core_1.setStoreItem)('cmsSettings', cmsSettings);
    }
    catch (error) {
        console.error(error);
    }
    fs_extra_1.default.outputJSONSync((0, path_1.resolve)(configsDir, 'public-env.json'), {
        cmsSettings: {
            domain: cmsSettings === null || cmsSettings === void 0 ? void 0 : cmsSettings.domain,
            url: cmsSettings === null || cmsSettings === void 0 ? void 0 : cmsSettings.url,
            apiUrl: cmsSettings === null || cmsSettings === void 0 ? void 0 : cmsSettings.apiUrl,
            adminUrl: cmsSettings === null || cmsSettings === void 0 ? void 0 : cmsSettings.adminUrl,
            frontendUrl: cmsSettings === null || cmsSettings === void 0 ? void 0 : cmsSettings.frontendUrl,
            redirects: cmsSettings === null || cmsSettings === void 0 ? void 0 : cmsSettings.redirects,
            rewrites: cmsSettings === null || cmsSettings === void 0 ? void 0 : cmsSettings.rewrites,
            themeName: cmsSettings === null || cmsSettings === void 0 ? void 0 : cmsSettings.themeName,
            defaultPageSize: cmsSettings === null || cmsSettings === void 0 ? void 0 : cmsSettings.defaultPageSize,
            currencies: cmsSettings === null || cmsSettings === void 0 ? void 0 : cmsSettings.currencies,
            timezone: cmsSettings === null || cmsSettings === void 0 ? void 0 : cmsSettings.timezone,
            language: cmsSettings === null || cmsSettings === void 0 ? void 0 : cmsSettings.language,
            favicon: cmsSettings === null || cmsSettings === void 0 ? void 0 : cmsSettings.favicon,
            logo: cmsSettings === null || cmsSettings === void 0 ? void 0 : cmsSettings.logo,
            defaultShippingPrice: cmsSettings === null || cmsSettings === void 0 ? void 0 : cmsSettings.defaultShippingPrice,
            disablePayLater: cmsSettings === null || cmsSettings === void 0 ? void 0 : cmsSettings.disablePayLater,
            headHtml: cmsSettings === null || cmsSettings === void 0 ? void 0 : cmsSettings.headHtml,
            footerHtml: cmsSettings === null || cmsSettings === void 0 ? void 0 : cmsSettings.footerHtml,
            customMeta: cmsSettings === null || cmsSettings === void 0 ? void 0 : cmsSettings.customMeta,
            modules: cmsSettings === null || cmsSettings === void 0 ? void 0 : cmsSettings.modules,
        },
        environment: {
            isAdminPanel: true,
            mode: isProduction ? 'prod' : 'dev',
        },
    });
};
const startProdServer = (port) => {
    // start fastify server:
    const fastify = require('fastify')({ logger: false });
    fastify.get('/*', async function (req, reply) {
        const url = new URL('http://localhost' + req.raw.url);
        const publicPath = (0, normalize_path_1.default)(url.pathname).replace(/^(\.\.(\/|\\|$))+/, '');
        if (publicPath.indexOf('\0') !== -1) {
            throw new Error('Poison Null Bytes');
        }
        if (publicPath.startsWith('/admin/_next/static')) {
            const filePath = (0, path_1.join)((0, paths_1.getAdminPanelTempDir)(), '.next/static', publicPath.replace('/admin/_next/static', ''));
            return (0, static_1.fastifySendFile)(reply, filePath);
        }
        if (publicPath.startsWith('/admin/static')) {
            const filePath = (0, path_1.join)((0, paths_1.getAdminPanelTempDir)(), 'public/admin/static', publicPath.replace('/admin/static', ''));
            return (0, static_1.fastifySendFile)(reply, filePath);
        }
        if (publicPath.startsWith('/admin')) {
            return reply
                .type('text/html')
                .send(fs_extra_1.default.createReadStream((0, path_1.join)((0, paths_1.getAdminPanelTempDir)(), '.next/server/pages/index.html')));
        }
        const { pathInPublicDir } = await (0, static_1.resolvePublicFilePathToServe)(req.raw.url);
        if (pathInPublicDir) {
            return (0, static_1.fastifySendFile)(reply, pathInPublicDir);
        }
        return reply.status(404).send('Not found');
    });
    fastify.get('/admin/api/public-env', function () {
        const configPath = (0, path_1.resolve)(process.cwd(), '.cromwell/admin/configs/public-env.json');
        return fs_extra_1.default.readJsonSync(configPath);
    });
    fastify.listen({ port }, (err, address) => {
        if (err)
            throw err;
        logger.info(`Admin panel server listening on ${address}`);
    });
};
start().catch((e) => console.error(e));
