/* eslint-disable import/default */
/* eslint-disable @typescript-eslint/no-explicit-any */
import { ux } from "@oclif/core";
import decompress from "decompress";
import fs from "fs-extra/esm";
import log4js from "log4js";
import { existsSync } from "node:fs";
import { copyFile, mkdir, rm } from "node:fs/promises";
import { join } from "node:path";
import { TEMP_ZIP_NAME } from "../../shared/constants.js";
import locatorService from "../locator.service.js";
export class BrowserClientService {
    currentDir = process.cwd();
    logger = log4js.getLogger("NewBrowserClientService");
    async build(config) {
        const { appName, template, version } = config;
        this.logger.info(`Creating new ${appName} app with io.CB version ${version} and template ${template}`);
        ux.info(`Creating new ${appName} app with io.CB version ${version} and template ${template}`);
        const cliConfig = await locatorService.configurationService.getCliConfig();
        const appDir = join(this.currentDir, appName);
        this.logger.info(`Making new app directory at ${appDir}`);
        await mkdir(appDir);
        this.logger.info(`New app directory created at ${appDir}, proceeding with fetching ${template} template`);
        const resolvedMode = await this.getZipTemplate(config, cliConfig);
        this.logger.info(`Fetched ${template} template with mode ${resolvedMode}, proceeding with unpacking`);
        ux.info(`Proceeding with ${resolvedMode} template`);
        await this.unpackZipTemplate(appDir, template, join(appDir, TEMP_ZIP_NAME));
        this.logger.info(`New ${appName} app creation complete.`);
        ux.info(`New Browser Client Creation Complete. Please run "cd ./${appName}" and "npm install" to install dependencies and "npm start" to start the app.`);
    }
    async clean(config) {
        const appDir = join(this.currentDir, config.appName);
        this.logger.info(`Cleaning up the app directory at ${appDir}`);
        await rm(appDir, { force: true, recursive: true });
        ux.action.stop(`New "Browser Client" Creation Failed. Cleaned up the app directory.`);
        this.logger.info(`Cleaned up the app directory at ${appDir}`);
    }
    async getZipTemplate(config, cliConfig) {
        const { appName, version } = config;
        const appDir = join(this.currentDir, appName);
        const zipLocation = join(appDir, TEMP_ZIP_NAME);
        if (cliConfig.mode === "remote") {
            this.logger.info(`Fetching remote template ${version}, to zip location ${zipLocation}`);
            await this.resolveRemoteZip(version, zipLocation);
            this.logger.info(`Completed remote template fetch`);
            return "remote";
        }
        if (cliConfig.mode === "offline") {
            this.logger.info(`Fetching offline template ${version}, to zip location ${zipLocation}`);
            await this.resolveLocalZip(version, zipLocation);
            this.logger.info(`Completed local template fetch`);
            return "offline";
        }
        try {
            this.logger.info(`Fetching remote template ${version}, to zip location ${zipLocation}, with auto mode`);
            await this.resolveRemoteZip(version, zipLocation);
            this.logger.info(`Completed remote template fetch with auto mode`);
            return "remote";
        }
        catch (error) {
            this.logger.warn(`Could not get the remote template, falling back to the offline template. Reason: ${error.message}`);
            ux.warn(`Could not get the remote template, falling back to the offline template. Reason: ${error.message}`);
            await this.resolveLocalZip(version, zipLocation, `Unable to get the remote template, resolved to the offline template ${version}`);
            this.logger.info(`Completed local fallback template fetch with auto mode`);
            return "offline";
        }
    }
    async resolveLocalZip(version, zipLocation, stopMessage) {
        ux.action.start(`Fetching offline template ${version}`);
        const verifiedVersion = await locatorService.validationService.transformVersion(version, "ioCb", "offline");
        const { root } = locatorService.configurationService.directoryConfig;
        const templateLocation = join(root, "templates", verifiedVersion ? `${verifiedVersion}.zip` : "latest.zip");
        existsSync(templateLocation) || ux.error(`Could not find the offline template ${version}`);
        await copyFile(templateLocation, zipLocation);
        ux.action.stop(stopMessage);
    }
    async resolveRemoteZip(version, zipLocation, stopMessage) {
        ux.action.start(`Downloading remote template ${version}`);
        const verifiedVersion = await locatorService.validationService.transformVersion(version, "ioCb", "remote");
        await locatorService.downloaderService.downloadRemoteZip(verifiedVersion, zipLocation);
        ux.action.stop(stopMessage);
    }
    async unpackZipTemplate(appDir, template, zipLocation) {
        await mkdir(join(appDir, "temp"));
        await decompress(zipLocation, join(appDir, "temp"), { strip: 1 });
        const source = join(appDir, "temp", `browser-client-${template}`);
        existsSync(source) || ux.error(`Could not find the template ${join(appDir, "temp", `browser-client-${template}`)}`);
        fs.copySync(source, appDir, { overwrite: true });
        await rm(zipLocation, { force: true, recursive: true });
        await rm(join(appDir, "temp"), { force: true, recursive: true });
    }
}
