import axios from "axios";
import fs from "fs-extra/esm";
import { createWriteStream } from "node:fs";
import { mkdir, rm, } from "node:fs/promises";
import { join } from "node:path";
import { MANIFEST_URL, NPM_ORG_SCOPE, TEMP_ZIP_NAME, TEMPLATES_REPO_URL, getTemplatesVersionRepoUrl } from "../shared/constants.js";
import { runCommand } from "../utils/exec.js";
export class DownloaderService {
    currentDir = process.cwd();
    templatesRepoUrl = process.env.TEMPLATES_REPO_URL || TEMPLATES_REPO_URL;
    async downloadNpmPackage(config) {
        const { appDir, destination, destinationMap, distFileName, distFileNameMap, packageNameNoScope, version } = config;
        const tempDir = join(appDir, "temp");
        await mkdir(tempDir);
        await runCommand("npm init --yes", { cwd: tempDir });
        const tag = version === "latest" ? "latest" : `${version}-lts`;
        await runCommand(`npm install ${NPM_ORG_SCOPE}/${packageNameNoScope}@${tag}`, { cwd: tempDir });
        const source = join(appDir, "temp", "node_modules", NPM_ORG_SCOPE, packageNameNoScope, "dist", distFileName);
        fs.copySync(source, destination, { overwrite: true });
        const sourceMap = join(appDir, "temp", "node_modules", NPM_ORG_SCOPE, packageNameNoScope, "dist", distFileNameMap);
        fs.copySync(sourceMap, destinationMap, { overwrite: true });
        await rm(join(appDir, "temp"), { force: true, recursive: true });
    }
    async downloadRemoteManifest() {
        const latestManifestUrl = process.env.LATEST_MANIFEST_URL || MANIFEST_URL;
        const response = await axios.get(latestManifestUrl);
        return response.data;
    }
    downloadRemoteZip(version, destination) {
        const url = version === "latest" ? this.templatesRepoUrl : getTemplatesVersionRepoUrl(version);
        return new Promise((resolve, reject) => {
            axios.get(url, { responseType: "stream" })
                .then((response) => {
                const zipStream = response.data.pipe(createWriteStream(destination ?? join(this.currentDir, TEMP_ZIP_NAME)));
                zipStream.on("finish", () => resolve());
                zipStream.on("error", (error) => reject(error));
            })
                .catch(reject);
        });
    }
    async npmInstall(config) {
        const { appDir, noScopePackages: packages, version } = config;
        const tag = version === "latest" ? "latest" : `${version}-lts`;
        const parsedPackages = packages.map((pkg) => `${NPM_ORG_SCOPE}/${pkg}@${tag}`).join(" ");
        await runCommand(`npm install ${parsedPackages}`, { cwd: appDir });
    }
}
