// Entry point legacy: sin GRIDDO_INFRA_MODE=render (que solo estampa cli.mjs,
// la interfaz del pipeline nuevo) todo el código se evalúa ya en modo legacy.
import type { RenderDB } from "../../shared/types/render";
import type { LegacyDomain } from "./types";

import { execSync } from "node:child_process";
import fsp from "node:fs/promises";
import path from "node:path";

import { version as griddoVersion } from "../../../package.json";
import { checkEnvironmentHealth } from "../../core/check-env-health";
import { readDB, writeDB } from "../../core/db";
import { pathExists, rmDirs } from "../../core/fs";
import { GriddoLog } from "../../core/GriddoLog";
import { resolveComponentsPath } from "../../core/instance";
import { AuthService } from "../../services/auth";
import { getInstanceDomains } from "../../services/domains";
import { resolveDomainRenderMode } from "../../services/render";
import {
	GRIDDO_LEGACY_IGNORE_DRYRUN,
	GRIDDO_RENDER_ROOT,
	GRIDDO_SKIP_BUILD_CHECKS,
} from "../../shared/envs";
import { pkgDirSync } from "../../shared/npm-modules/pkg-dir";
import { countPendingPages } from "../lib/count-pending-pages";

async function initRenderLegacy() {
	// Layout de develop: todo cuelga del root del repo que instala CX
	// (cliente o monorepo), sin el segmento ebs/ del modo nuevo.
	const root = GRIDDO_RENDER_ROOT;
	const cx = root;
	const ssg = pkgDirSync({ cwd: __dirname }) || root;
	const cxCache = path.resolve(root, ".griddo/cache");
	const dbFilePath = path.join(cxCache, "db.json");
	const components = resolveComponentsPath();
	const exportsDir = path.join(root, "exports/sites");

	// Igual que prepare-render: conservar el estado previo de dominios para
	// que resolveDomainRenderMode vea renderMode/isRendering anteriores.
	let prevDomains: RenderDB["domains"] = {};
	if (await pathExists(dbFilePath)) {
		const prev = await readDB();
		prevDomains = prev.domains ?? {};
	}

	const data: RenderDB = {
		griddoVersion,
		buildReportFileName: "build-report.json",
		domains: prevDomains,
		currentRenderingDomain: null,
		commitHash: process.env.COMMIT_HASH || execSync("git rev-parse HEAD").toString().trim(),
		commitMessage:
			process.env.COMMIT_MESSAGE || execSync("git log -1 --pretty=%B").toString().trim(),
		paths: {
			components,
			cx,
			cxCache,
			exportsDir,
			root,
			ssg,
		},
	};

	// create the main cache folder for cx if it doesn't exist.
	if (!(await pathExists(cxCache))) {
		await fsp.mkdir(cxCache, { recursive: true });
	}

	await writeDB(data);
}

async function prepareDomainsLegacy() {
	// develop aceptaba un flag posicional para forzar dry-render global.
	const [dryRenderArg] = process.argv.slice(2);

	await AuthService.login();

	const db = await readDB();

	const domains = (await getInstanceDomains()) as LegacyDomain[];

	// Secuencial (igual que prepare-render) para no saturar la API.
	const domainsWithPendingPages: { domain: LegacyDomain; totalPendingPages: number }[] = [];
	for (const domain of domains) {
		domainsWithPendingPages.push({
			domain,
			totalPendingPages: await countPendingPages(domain.slug),
		});
	}

	domainsWithPendingPages.sort((a, b) => a.totalPendingPages - b.totalPendingPages);
	const sortedSlugs = domainsWithPendingPages.map(({ domain }) => domain.slug);

	// Contrato con la infra python: lee <cx-package>/domains.json para saber
	// qué dominios iterar y en qué orden (de menos a más páginas pendientes).
	await fsp.writeFile(path.join(db.paths.ssg, "domains.json"), JSON.stringify(sortedSlugs));

	db.domains = {};

	for (const { domain, totalPendingPages } of domainsWithPendingPages) {
		const domainSlug = domain.slug;
		const shouldBeRendered = totalPendingPages > 0;
		const { renderMode, reason } = await resolveDomainRenderMode({
			domain: domainSlug,
			shouldBeRendered,
		});

		GriddoLog.info(
			`(Pre-check) ${domainSlug} marked as <${renderMode}> with the reason <${reason}>`,
		);

		db.domains[domainSlug] = {
			id: domain.id,
			renderMode,
			shouldBeRendered,
			renderModeReason: reason,
			// GRIDDO_LEGACY_IGNORE_DRYRUN=1 (debug local): renderiza de verdad
			// dominios marcados dry-run en la API. En producción se respeta.
			dryRun: GRIDDO_LEGACY_IGNORE_DRYRUN ? false : domain.dryRun || !!dryRenderArg,
		};
	}

	await writeDB(db);
}

async function clean() {
	const db = await readDB();
	await rmDirs([path.join(db.paths.root, "apiCache")]);
}

async function main() {
	GRIDDO_SKIP_BUILD_CHECKS
		? GriddoLog.info("Build health check bypassed")
		: checkEnvironmentHealth();

	await initRenderLegacy();
	await prepareDomainsLegacy();
	await clean();
}

if (require.main === module) {
	main().catch((error) => {
		if (error instanceof Error) {
			GriddoLog.error(error.message);
		} else {
			GriddoLog.error(`An unexpected error occurred ${error}`);
		}
		process.exit(1);
	});
}

export { initRenderLegacy, prepareDomainsLegacy };
