#!/usr/bin/env node

const fs = require('fs');
const path = require('path');

const rootDir = path.resolve(__dirname, '..');

function isSemverLike(version) {
  return /^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$/.test(String(version || '').trim());
}

function readJson(filePath) {
  return JSON.parse(fs.readFileSync(filePath, 'utf8'));
}

function writeJson(filePath, value) {
  fs.writeFileSync(filePath, `${JSON.stringify(value, null, 2)}\n`, 'utf8');
}

function getAppPackageDirs() {
  const dirs = [rootDir];
  const entries = fs.readdirSync(rootDir, { withFileTypes: true });

  for (const entry of entries) {
    if (!entry.isDirectory()) {
      continue;
    }

    if (entry.name === 'node_modules' || entry.name === 'tmp' || entry.name.startsWith('.')) {
      continue;
    }

    const dir = path.join(rootDir, entry.name);
    if (
      fs.existsSync(path.join(dir, 'package.json')) &&
      fs.existsSync(path.join(dir, 'src', 'config.ts'))
    ) {
      dirs.push(dir);
    }
  }

  return dirs;
}

function syncVersions(version, options = {}) {
  const targetVersion = String(version || '').trim();
  if (!isSemverLike(targetVersion)) {
    throw new Error(`Invalid version "${version}". Expected x.y.z, for example 4.5.34.`);
  }

  const packageDirs = getAppPackageDirs();
  const changed = [];

  for (const dir of packageDirs) {
    const packagePath = path.join(dir, 'package.json');
    const pkg = readJson(packagePath);
    const before = pkg.version;

    if (before !== targetVersion) {
      pkg.version = targetVersion;
      writeJson(packagePath, pkg);
      changed.push(path.relative(rootDir, packagePath) || 'package.json');
    }

    const configPath = path.join(dir, 'src', 'config.ts');
    if (fs.existsSync(configPath)) {
      let content = fs.readFileSync(configPath, 'utf8');
      const nextContent = content.replace(
        /version:\s*(?:packageJson\.version|["'][^"']*["'])/,
        'version: packageJson.version'
      );
      if (nextContent !== content) {
        fs.writeFileSync(configPath, nextContent, 'utf8');
        changed.push(path.relative(rootDir, configPath));
      }
    }
  }

  if (!options.silent) {
    console.log(`[sync-version] version=${targetVersion}`);
    console.log(`[sync-version] app packages=${packageDirs.length}`);
    if (changed.length === 0) {
      console.log('[sync-version] no changes');
    } else {
      changed.forEach((file) => console.log(`[sync-version] updated ${file}`));
    }
  }

  return { version: targetVersion, packageCount: packageDirs.length, changed };
}

if (require.main === module) {
  const argVersion = process.argv[2] || process.env.APP_VERSION || process.env.OEM_VERSION;
  try {
    syncVersions(argVersion);
  } catch (error) {
    console.error(`[sync-version] ${error.message}`);
    process.exit(1);
  }
}

module.exports = {
  syncVersions,
  getAppPackageDirs
};
