"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 });
const open_1 = __importDefault(require("open"));
const path_1 = __importDefault(require("path"));
const feishu_devtools_core_1 = require("@bdeefe/feishu-devtools-core");
const api_1 = require("@bdeefe/feishu-devtools-core/libs/config/api");
const csp_1 = __importDefault(require("../utils/csp"));
const resolve_safe_domain_1 = require("../utils/resolve-safe-domain");
const base_1 = __importDefault(require("./base"));
class Dev extends base_1.default {
    constructor() {
        super(feishu_devtools_core_1.ModuleName.service);
    }
    returnSuccess(code, data) {
        return {
            code,
            msg: '',
            data,
        };
    }
    getAppMeta(blockTypeID, previewToken) {
        var _a;
        return __awaiter(this, void 0, void 0, function* () {
            const response = yield this.manager.execute(feishu_devtools_core_1.ModuleName.service, feishu_devtools_core_1.ServiceCmdEnum.Request, api_1.API.getBlockMeta, {
                lark_version: '',
                lang: 'zh_CN',
                app_queries: [
                    {
                        extension_queries: [
                            {
                                extension_type: 'block',
                                extension_id: blockTypeID,
                                preview_token: previewToken,
                            },
                        ],
                    },
                ],
            });
            return (((_a = response === null || response === void 0 ? void 0 : response.app_metas) === null || _a === void 0 ? void 0 : _a[0]) || { app_base_info: {} });
        });
    }
    getBlockitApi({ projectConfig, blockConfigMap, devServerHost, basePath = '/block', }) {
        return __awaiter(this, void 0, void 0, function* () {
            const blockTypeID = Object.values(blockConfigMap)[0].blockTypeID;
            const onlineAppMeta = yield this.getAppMeta(blockTypeID);
            return {
                getAppMeta: () => {
                    const { appid } = projectConfig;
                    const { app_base_info } = onlineAppMeta;
                    const pkgType = 'block_h5';
                    return this.returnSuccess(0, {
                        app_metas: [
                            {
                                app_base_info: {
                                    app_id: appid,
                                    bot_id: (app_base_info === null || app_base_info === void 0 ? void 0 : app_base_info.bot_id) || '',
                                    icon: (app_base_info === null || app_base_info === void 0 ? void 0 : app_base_info.icon) || '',
                                    name: (app_base_info === null || app_base_info === void 0 ? void 0 : app_base_info.name) || '',
                                    openSchemaWhiteList: (app_base_info === null || app_base_info === void 0 ? void 0 : app_base_info.openSchemaWhiteList) || [],
                                    useOpenSchemaWhiteList: (app_base_info === null || app_base_info === void 0 ? void 0 : app_base_info.useOpenSchemaWhiteList) || [],
                                    version: (app_base_info === null || app_base_info === void 0 ? void 0 : app_base_info.version) || '',
                                },
                                extension_metas: Object.entries(blockConfigMap).map(([, blockConfig]) => {
                                    const url = new URL(devServerHost);
                                    url.pathname = basePath;
                                    const fallbackPathList = [url.href];
                                    return {
                                        app_id: appid,
                                        basic_lib_version: '',
                                        ext_config: JSON.stringify({
                                            pkg_type: pkgType,
                                            v_host: '',
                                            fallback_path_list: fallbackPathList,
                                        }),
                                        extension_id: blockConfig.blockTypeID,
                                        meta: JSON.stringify({
                                            pkg: {
                                                [`${pkgType}_zip`]: {
                                                    url: '',
                                                    md5: '',
                                                    components: null,
                                                    backup_urls: [''],
                                                    lib_version: null,
                                                    schema_data: null,
                                                    need_interface: true,
                                                    base_path: basePath,
                                                    fallback_path_list: fallbackPathList,
                                                    offline_web_config: blockConfig.offlineWebConfig,
                                                },
                                            },
                                        }),
                                        schema_data: '',
                                        update_description: '',
                                        update_type: 0,
                                        version: '99.99.99',
                                    };
                                }),
                            },
                        ],
                    });
                },
                getBlocks: () => {
                    const { appid } = projectConfig;
                    const defaultIcon = 'https://s1-imfile.feishucdn.com/static-resource/v1/95250c48-ba3b-4708-befe-a95078b19271~?image_size=noop&cut_type=&quality=_q100&format=image&sticker_format=.webp';
                    return this.returnSuccess(0, {
                        blocks: Object.entries(blockConfigMap).map(([, blockConfig]) => {
                            return {
                                name: {
                                    'zh-CN': blockConfig.blockTypeID,
                                    'en-US': blockConfig.blockTypeID,
                                    'ja-JP': blockConfig.blockTypeID,
                                },
                                appName: {
                                    'zh-CN': '开发者工具',
                                    'en-US': 'DevTools',
                                    'ja-JP': '開発者ツール',
                                },
                                icon: defaultIcon,
                                filledIcon: defaultIcon,
                                outlinedIcon: defaultIcon,
                                blockTypeID: blockConfig.blockTypeID,
                                appid,
                            };
                        }),
                    });
                },
                getProjectConfig: () => projectConfig,
                getBlockConfig: (blockPath) => blockConfigMap[blockPath],
            };
        });
    }
    getBlockitDevMiddleware({ projectConfig, blockConfigMap, devServerHost, basePath = '/', }) {
        return __awaiter(this, void 0, void 0, function* () {
            const blockitApi = yield this.getBlockitApi({
                projectConfig,
                blockConfigMap,
                devServerHost,
                basePath,
            });
            return function (req, res, next) {
                if (req.url.startsWith(path_1.default.join(basePath, 'project.config.json'))) {
                    const data = blockitApi.getProjectConfig();
                    res.send(data);
                }
                else if (req.url.startsWith('/api/block')) {
                    const data = blockitApi.getBlocks();
                    res.send(data);
                }
                else if (req.url.startsWith('/api/meta')) {
                    const data = blockitApi.getAppMeta();
                    res.send(data);
                }
                else if (req.url.startsWith(basePath)) {
                    const blocks = projectConfig.blocks || [];
                    const p = blocks.find((blockPath) => req.url.match(blockPath));
                    if (p) {
                        const data = blockitApi.getBlockConfig(p);
                        res.send(data);
                    }
                }
                else {
                    next && next();
                }
            };
        });
    }
    openHost(params) {
        return __awaiter(this, void 0, void 0, function* () {
            const { getHostUrl, debugPort, debugUrl, previewResourceMap, autoOpen } = params;
            const hostUrl = yield getHostUrl();
            const url = new URL(hostUrl);
            const searchParams = new URLSearchParams(url.search.slice(1));
            if (debugUrl) {
                searchParams.set('debugPort', debugUrl);
            }
            else if (debugPort) {
                searchParams.set('debugPort', `${debugPort}`);
            }
            if (previewResourceMap) {
                searchParams.set('previewResourceMap', JSON.stringify(previewResourceMap));
            }
            url.search = `?${searchParams.toString()}`;
            if (autoOpen) {
                (0, open_1.default)(url.href);
            }
            return url.href;
        });
    }
    getSafeSetting(appid) {
        return __awaiter(this, void 0, void 0, function* () {
            const response = yield this.manager.execute(feishu_devtools_core_1.ModuleName.service, feishu_devtools_core_1.ServiceCmdEnum.Request, api_1.API.getSafeSetting, {
                appId: appid,
            }, {
                logId: true,
            });
            return response;
        });
    }
    getAppCSPConfig(appid) {
        return __awaiter(this, void 0, void 0, function* () {
            const safeSetting = yield this.getSafeSetting(appid);
            const safe_server_domain = ((safeSetting === null || safeSetting === void 0 ? void 0 : safeSetting.safe_server_domain) || {
                safeServerDomain: [],
                baseSafeServerDomain: [],
                defaultProtocolWhitelist: [],
                isFrameCheckfreeApp: false,
            });
            const domainList = [
                ...((safe_server_domain === null || safe_server_domain === void 0 ? void 0 : safe_server_domain.baseSafeServerDomain) || []),
                ...((safe_server_domain === null || safe_server_domain === void 0 ? void 0 : safe_server_domain.safeServerDomain) || []),
            ].reduce((prev, cur) => {
                prev.push(cur);
                const wildcardDomain = (0, resolve_safe_domain_1.toWildcardDomain)(cur);
                if (wildcardDomain) {
                    prev.push(wildcardDomain);
                }
                return prev;
            }, []);
            const csp = new csp_1.default();
            csp.add('default-src', safe_server_domain.defaultProtocolWhitelist || []);
            csp.add('default-src', domainList);
            if (safe_server_domain.isFrameCheckfreeApp) {
                csp.add('iframe-src', '*');
            }
            return csp.getStr();
        });
    }
    updateServiceEnv(environment) {
        this.manager.execute(feishu_devtools_core_1.ModuleName.service, feishu_devtools_core_1.ServiceCmdEnum.Update, {
            environment,
        });
    }
}
exports.default = Dev;
