#!/usr/bin/env node
/**
 * set-brand.mjs - prepara il progetto per un brand (vedi cartella brands/).
 *
 *   node scripts/set-brand.mjs <edil|mytown>
 *
 * Operazioni (idempotenti):
 *  1. brands/<brand>/brand.ts        -> src/brand/active-brand.ts
 *  2. brands/<brand>/logo.(jpeg|png) -> src/assets/icons/app/logo/logo.jpeg
 *  3. capacitor.config.ts            : appId, appName, EdgeToEdge.backgroundColor
 *  4. android/app/build.gradle       : namespace, applicationId
 *  5. android/.../values/strings.xml : app_name, title_activity_main, package_name, custom_url_scheme
 *  6. ios (se presente)              : PRODUCT_BUNDLE_IDENTIFIER, CFBundleDisplayName
 *  7. icone/splash (se sorgenti presenti): @capacitor/assets generate
 *
 * I replace sono fatti su pattern di campo (non sul valore corrente): rieseguire
 * lo script o cambiare brand è sempre sicuro. Se un pattern obbligatorio non viene
 * trovato lo script termina con errore (niente patch silenziose).
 */
import { readFileSync, writeFileSync, existsSync, copyFileSync } from 'node:fs';
import { join, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
import { execSync } from 'node:child_process';

const ROOT = join(dirname(fileURLToPath(import.meta.url)), '..');
const BRANDS = ['edil', 'mytown'];

const brand = process.argv[2];
if (!BRANDS.includes(brand)) {
	console.error(`\n✗ Brand non valido: "${brand ?? ''}". Usare: node scripts/set-brand.mjs <${BRANDS.join('|')}>\n`);
	process.exit(1);
}

const brandDir = join(ROOT, 'brands', brand);
if (!existsSync(brandDir)) fail(`Cartella brand mancante: ${rel(brandDir)}`);

// --- Estrae i valori dal descrittore brand.ts (single source of truth) -----
const brandTsPath = join(brandDir, 'brand.ts');
if (!existsSync(brandTsPath)) fail(`Descrittore mancante: ${rel(brandTsPath)}`);
const brandTs = readFileSync(brandTsPath, 'utf8');
const appName = field(brandTs, 'appName');
const bundleId = field(brandTs, 'bundleId');
const edgeColor = field(brandTs, 'edgeColor');

console.log(`\n▶ Brand: ${brand}  (appName="${appName}", bundleId="${bundleId}", edge="${edgeColor}")\n`);

// --- 1. active-brand.ts -----------------------------------------------------
const activeBrandPath = join(ROOT, 'src', 'brand', 'active-brand.ts');
const banner = `// FILE GENERATO da scripts/set-brand.mjs (brand: ${brand}). Non modificare a mano.\n`;
writeFileSync(activeBrandPath, banner + stripLeadingComments(brandTs), 'utf8');
console.log(`  ✓ ${rel(activeBrandPath)}`);

// --- 2. logo ----------------------------------------------------------------
const logoSrc = ['logo.jpeg', 'logo.jpg', 'logo.png'].map((f) => join(brandDir, f)).find(existsSync);
if (!logoSrc) fail(`Logo mancante in ${rel(brandDir)} (atteso logo.jpeg|jpg|png)`);
const logoDest = join(ROOT, 'src', 'assets', 'icons', 'app', 'logo', 'logo.jpeg');
copyFileSync(logoSrc, logoDest);
console.log(`  ✓ ${rel(logoDest)}  (da ${rel(logoSrc)})`);

// --- 3. capacitor.config.ts -------------------------------------------------
patch(join(ROOT, 'capacitor.config.ts'), [
	[/(appId:\s*')[^']*(')/, `$1${bundleId}$2`, 'appId'],
	[/(appName:\s*')[^']*(')/, `$1${appName}$2`, 'appName'],
	[/(EdgeToEdge:\s*\{\s*backgroundColor:\s*')[^']*(')/, `$1${edgeColor}$2`, 'EdgeToEdge.backgroundColor'],
]);

// --- 4. android build.gradle ------------------------------------------------
patch(join(ROOT, 'android', 'app', 'build.gradle'), [
	[/(namespace\s+")[^"]*(")/, `$1${bundleId}$2`, 'namespace'],
	[/(applicationId\s+")[^"]*(")/, `$1${bundleId}$2`, 'applicationId'],
]);

// --- 5. android strings.xml -------------------------------------------------
patch(join(ROOT, 'android', 'app', 'src', 'main', 'res', 'values', 'strings.xml'), [
	[/(<string name="app_name">)[^<]*(<\/string>)/, `$1${appName}$2`, 'app_name'],
	[/(<string name="title_activity_main">)[^<]*(<\/string>)/, `$1${appName}$2`, 'title_activity_main'],
	[/(<string name="package_name">)[^<]*(<\/string>)/, `$1${bundleId}$2`, 'package_name'],
	[/(<string name="custom_url_scheme">)[^<]*(<\/string>)/, `$1${bundleId}$2`, 'custom_url_scheme'],
]);

// --- 6. iOS (opzionale: solo se la piattaforma è stata aggiunta) ------------
const iosProj = join(ROOT, 'ios', 'App', 'App.xcodeproj', 'project.pbxproj');
const iosPlist = join(ROOT, 'ios', 'App', 'App', 'Info.plist');
if (existsSync(iosProj)) {
	patch(iosProj, [[/(PRODUCT_BUNDLE_IDENTIFIER = )[^;]*(;)/g, `$1${bundleId}$2`, 'PRODUCT_BUNDLE_IDENTIFIER']]);
	if (existsSync(iosPlist)) {
		patch(
			iosPlist,
			[[/(<key>CFBundleDisplayName<\/key>\s*<string>)[^<]*(<\/string>)/, `$1${appName}$2`, 'CFBundleDisplayName']],
			{ optional: true },
		);
	}
} else {
	console.log('  • iOS non presente (cartella ios/ assente) — salto. Eseguire `npx cap add ios` e poi rilanciare lo script.');
}

// --- 7. icone & splash (opzionale: richiede sorgenti + @capacitor/assets) ---
const assetsDir = join(brandDir, 'assets');
if (existsSync(assetsDir)) {
	console.log('  • Genero icone/splash con @capacitor/assets...');
	try {
		execSync(`npx @capacitor/assets generate --assetPath "${assetsDir}" --iconBackgroundColor "${edgeColor}" --iconBackgroundColorDark "${edgeColor}" --splashBackgroundColor "#ffffff"`, {
			cwd: ROOT,
			stdio: 'inherit',
		});
	} catch {
		console.warn('  ! Generazione icone/splash fallita (controlla i sorgenti in brands/<brand>/assets e che @capacitor/assets sia installato).');
	}
} else {
	console.log(`  • Nessun sorgente icone in ${rel(assetsDir)} — salto generazione icone/splash.`);
}

console.log(`\n✓ Brand "${brand}" applicato. Ora: ng build && npx cap sync\n`);

// ---------------------------------------------------------------------------
// helpers
function field(src, key) {
	const m = src.match(new RegExp(`${key}:\\s*'([^']*)'`));
	if (!m) fail(`Campo "${key}" non trovato in brands/${brand}/brand.ts`);
	return m[1];
}

function stripLeadingComments(src) {
	// rimuove le righe di commento iniziali del descrittore (manteniamo solo il banner generato)
	return src.replace(/^(\s*\/\/[^\n]*\n)+/, '');
}

function patch(file, rules, opts = {}) {
	if (!existsSync(file)) {
		if (opts.optional) {
			console.log(`  • ${rel(file)} assente — salto.`);
			return;
		}
		fail(`File richiesto mancante: ${rel(file)}`);
	}
	let content = readFileSync(file, 'utf8');
	for (const [regex, replacement, label] of rules) {
		if (!regex.test(content)) fail(`Pattern "${label}" non trovato in ${rel(file)} — verifica il file (replace annullato).`);
		content = content.replace(regex, replacement);
	}
	writeFileSync(file, content, 'utf8');
	console.log(`  ✓ ${rel(file)}  [${rules.map((r) => r[2]).join(', ')}]`);
}

function rel(p) {
	return p.replace(ROOT + '\\', '').replace(ROOT + '/', '').replace(/\\/g, '/');
}

function fail(msg) {
	console.error(`\n✗ ${msg}\n`);
	process.exit(1);
}
