#!/usr/bin/env node

import { readFileSync, writeFileSync } from 'node:fs';
import { resolve } from 'node:path';
import { parse, stringify } from 'yaml';

const root = resolve(import.meta.dirname, '..');
const basePath = resolve(root, 'config/default.yaml');

const profiles = [
  {
    name: 'paas',
    overlayPath: resolve(root, 'config/profiles/paas.overlay.yaml'),
    outputPath: resolve(root, 'config/paas.yaml'),
  },
];

const checkOnly = process.argv.includes('--check');

function isObject(value) {
  return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
}

function deepMerge(base, overlay) {
  if (!isObject(base) || !isObject(overlay)) {
    return overlay;
  }

  const result = { ...base };
  for (const [key, value] of Object.entries(overlay)) {
    if (isObject(value) && isObject(result[key])) {
      result[key] = deepMerge(result[key], value);
      continue;
    }
    result[key] = value;
  }
  return result;
}

function sortObjectKeys(value) {
  if (Array.isArray(value)) {
    return value.map(sortObjectKeys);
  }
  if (!isObject(value)) {
    return value;
  }
  const sorted = {};
  for (const key of Object.keys(value).sort()) {
    sorted[key] = sortObjectKeys(value[key]);
  }
  return sorted;
}

function stableStringify(value) {
  return JSON.stringify(sortObjectKeys(value));
}

function buildHeader(profile) {
  return [
    '# Flynn generated profile',
    `# Profile: ${profile.name}`,
    '#',
    '# This file is auto-generated from:',
    '# - config/default.yaml',
    `# - config/profiles/${profile.name}.overlay.yaml`,
    '#',
    '# Do not edit this file directly.',
    '# Regenerate with: pnpm config:profiles:generate',
    '',
  ].join('\n');
}

const baseConfig = parse(readFileSync(basePath, 'utf-8'));

let hasDrift = false;
for (const profile of profiles) {
  const overlayConfig = parse(readFileSync(profile.overlayPath, 'utf-8'));
  const merged = deepMerge(baseConfig, overlayConfig);
  const nextContent = buildHeader(profile) + stringify(merged, {
    lineWidth: 0,
  });

  if (checkOnly) {
    const existing = parse(readFileSync(profile.outputPath, 'utf-8'));
    if (stableStringify(existing) !== stableStringify(merged)) {
      console.error(`[drift] config/${profile.name}.yaml is out of date`);
      hasDrift = true;
    }
    continue;
  }

  writeFileSync(profile.outputPath, nextContent, 'utf-8');
  console.log(`[ok] generated config/${profile.name}.yaml`);
}

if (checkOnly && hasDrift) {
  process.exit(1);
}
