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

const PACKAGE_SCOPE = '@bytelyst/';
const requestedPackageSource = process.env.BYTELYST_PACKAGE_SOURCE || 'common-plat';
const PACKAGE_SOURCE = requestedPackageSource === 'vendor' ? 'vendor' : 'common-plat';
const DEFAULT_COMMON_PLAT_ROOTS = [
  path.resolve(__dirname, '..', 'learning_ai_common_plat'),
  '/opt/bytelyst/learning_ai_common_plat',
];
const COMMON_PLAT_ROOT =
  process.env.BYTELYST_COMMON_PLAT_ROOT ||
  DEFAULT_COMMON_PLAT_ROOTS.find((candidate) => fs.existsSync(path.join(candidate, 'packages'))) ||
  DEFAULT_COMMON_PLAT_ROOTS[0];
const COMMON_PLAT_PACKAGES_ROOT = path.join(COMMON_PLAT_ROOT, 'packages');
const VENDOR_PACKAGES_ROOT = path.join(__dirname, 'vendor', 'bytelyst');
const VERSION_CACHE = new Map();
let loggedSource = false;

function packageDirFor(name) {
  return name.startsWith(PACKAGE_SCOPE) ? name.slice(PACKAGE_SCOPE.length) : null;
}

function pathIfPackageExists(rootDir, name) {
  const packageDir = packageDirFor(name);
  if (!packageDir) return null;

  const candidate = path.join(rootDir, packageDir);
  return fs.existsSync(path.join(candidate, 'package.json')) ? candidate : null;
}

function readPackageVersion(packagePath) {
  if (VERSION_CACHE.has(packagePath)) {
    return VERSION_CACHE.get(packagePath);
  }

  try {
    const packageJson = JSON.parse(fs.readFileSync(path.join(packagePath, 'package.json'), 'utf8'));
    const version = packageJson.version || null;
    VERSION_CACHE.set(packagePath, version);
    return version;
  } catch {
    VERSION_CACHE.set(packagePath, null);
    return null;
  }
}

function resolveRegistryVersion(name) {
  const commonPlatPath = pathIfPackageExists(COMMON_PLAT_PACKAGES_ROOT, name);
  if (commonPlatPath) {
    const version = readPackageVersion(commonPlatPath);
    if (version) return version;
  }

  const vendorPath = pathIfPackageExists(VENDOR_PACKAGES_ROOT, name);
  if (vendorPath) {
    const version = readPackageVersion(vendorPath);
    if (version) return version;
  }

  return null;
}

function resolveSpecifier(name) {
  if (!name.startsWith(PACKAGE_SCOPE)) {
    return null;
  }

  if (PACKAGE_SOURCE === 'common-plat') {
    const packagePath = pathIfPackageExists(COMMON_PLAT_PACKAGES_ROOT, name);
    return packagePath ? `file:${packagePath}` : null;
  }

  const vendorPath = pathIfPackageExists(VENDOR_PACKAGES_ROOT, name);
  if (vendorPath) {
    return `file:${vendorPath}`;
  }

  const commonPlatPath = pathIfPackageExists(COMMON_PLAT_PACKAGES_ROOT, name);
  if (commonPlatPath) {
    return `file:${commonPlatPath}`;
  }

  const version = resolveRegistryVersion(name);
  return version ?? null;
}

function rewriteDependencySet(dependencies = {}) {
  for (const dependencyName of Object.keys(dependencies)) {
    const rewrittenSpecifier = resolveSpecifier(dependencyName);
    if (rewrittenSpecifier) {
      dependencies[dependencyName] = rewrittenSpecifier;
    }
  }
}

function logSourceOnce() {
  if (loggedSource) {
    return;
  }

  loggedSource = true;
  process.stderr.write(
    `[bytelyst] pnpm package source=${PACKAGE_SOURCE} commonPlatRoot=${COMMON_PLAT_ROOT}\n`,
  );
}

module.exports = {
  hooks: {
    readPackage(packageJson) {
      logSourceOnce();
      rewriteDependencySet(packageJson.dependencies);
      rewriteDependencySet(packageJson.devDependencies);
      rewriteDependencySet(packageJson.optionalDependencies);
      rewriteDependencySet(packageJson.peerDependencies);
      return packageJson;
    },
  },
};
