import { existsSync, readFileSync } from 'node:fs';
import { spawn } from 'node:child_process';
import { basename } from 'node:path';

const [command, envFile] = process.argv.slice(2);

if (!['build', 'deploy'].includes(command) || !envFile) {
  console.error('Usage: node scripts/cloudflare-worker.mjs <build|deploy> <env-file>');
  process.exit(1);
}

if (!existsSync(envFile)) {
  console.error(`Missing ${envFile}. Copy the matching .example file and fill in the values first.`);
  process.exit(1);
}

function parseEnvFile(path) {
  const entries = {};
  const lines = readFileSync(path, 'utf8').split(/\r?\n/);

  for (const line of lines) {
    const trimmed = line.trim();
    if (!trimmed || trimmed.startsWith('#')) continue;

    const separator = trimmed.indexOf('=');
    if (separator === -1) continue;

    const key = trimmed.slice(0, separator).trim();
    let value = trimmed.slice(separator + 1).trim();

    if (
      (value.startsWith('"') && value.endsWith('"')) ||
      (value.startsWith("'") && value.endsWith("'"))
    ) {
      value = value.slice(1, -1);
    }

    entries[key] = value;
  }

  return entries;
}

function applyEnv(entries) {
  for (const [key, value] of Object.entries(entries)) {
    process.env[key] = value;
  }
}

function run(name, commandName, commandArgs) {
  return new Promise((resolve, reject) => {
    const child = spawn(commandName, commandArgs, {
      env: process.env,
      stdio: 'inherit',
      shell: process.platform === 'win32',
    });

    child.on('error', reject);
    child.on('exit', (code) => {
      if (code === 0) {
        resolve();
        return;
      }

      reject(new Error(`${name} exited with code ${code}`));
    });
  });
}

const envEntries = parseEnvFile(envFile);
applyEnv(envEntries);

const workerName = process.env.CF_WORKER_NAME;
const workerRoute = process.env.CF_WORKER_ROUTE;
const workerDomain = process.env.CF_WORKER_DOMAIN;
const compatibilityDate = process.env.CF_WORKER_COMPATIBILITY_DATE;

console.log(`Using ${basename(envFile)} for ${command}.`);
console.log(`PUBLIC_SITE_URL=${process.env.PUBLIC_SITE_URL ?? '<unset>'}`);
console.log(`DIRECTUS_URL=${process.env.DIRECTUS_URL ?? '<unset>'}`);

await run('Astro build', 'npm', ['run', 'build']);

if (command === 'deploy') {
  if (!workerName) {
    console.error('Missing CF_WORKER_NAME. Set it in the env file.');
    process.exit(1);
  }

  const wranglerArgs = ['wrangler', 'deploy', 'dist', '--name', workerName];

  if (compatibilityDate) {
    wranglerArgs.push('--compatibility-date', compatibilityDate);
  }

  if (workerRoute) {
    wranglerArgs.push('--route', workerRoute);
  }

  if (workerDomain) {
    wranglerArgs.push('--domain', workerDomain);
  }

  await run('Cloudflare Worker deploy', 'npx', wranglerArgs);
}
