import { spawnSync } from "node:child_process";
import { readFileSync } from "node:fs";
import { join } from "node:path";

import { findWorkspaceRootSync } from "./findWorkspaceRoot.js";

type LernaListItem = {
    name: string;
    version: string;
    private: boolean;
    location: string;
    readPackageJson: () => Record<string, any>;
};

let GET_PACKAGES_CACHE: Record<string, LernaListItem>;

/**
 * Get all packages for this monorepo.
 */
function getPackages() {
    if (GET_PACKAGES_CACHE) {
        return GET_PACKAGES_CACHE;
    }

    GET_PACKAGES_CACHE = (
        JSON.parse(
            // eslint-disable-next-line n/no-sync
            spawnSync("lerna", ["list", "--loglevel", "silent", "--json", "--all"], {
                stdio: "pipe",
                // eslint-disable-next-line n/no-sync
                cwd: findWorkspaceRootSync(),
                encoding: "utf-8",
            }).stdout,
        ) as LernaListItem[]
    ).reduce(
        (obj, item) => {
            obj[item.name] = item;
            obj[item.name].readPackageJson = () => {
                // eslint-disable-next-line n/no-sync
                return JSON.parse(readFileSync(join(item.location, "package.json"), { encoding: "utf-8" }));
            };
            return obj;
        },
        {} as Record<string, LernaListItem>,
    );

    return GET_PACKAGES_CACHE;
}

function getPackagesArray() {
    return Object.values(getPackages()) as LernaListItem[];
}

export { getPackages, getPackagesArray, type LernaListItem };
