#!/usr/bin/env node
import fs from 'node:fs';
import path from 'node:path';
import { pathToFileURL } from 'node:url';

const args = parseArgs(process.argv.slice(2));

try {
  if (!args.renderer) throw new Error('missing --renderer');
  await verifyRenderer(path.resolve(args.renderer));
  console.log(JSON.stringify({ success: true, errors: [] }, null, 2));
} catch (error) {
  console.error(JSON.stringify({ success: false, errors: [String(error?.message ?? error)] }, null, 2));
  process.exitCode = 1;
}

async function verifyRenderer(rendererPath) {
  try {
    const mod = await import(pathToFileURL(rendererPath).href);
    const renderer = mod.default ?? mod.renderer;
    if (!renderer || typeof renderer.renderPage !== 'function') {
      throw new Error('renderer must export a GradialRenderer with renderPage');
    }
    return;
  } catch (error) {
    if (!shouldUseStaticFallback(error)) {
      throw error;
    }
  }

  const source = fs.readFileSync(rendererPath, 'utf8');
  if (!staticallyExportsRenderPage(source)) {
    throw new Error('renderer must export a GradialRenderer with renderPage');
  }
}

function shouldUseStaticFallback(error) {
  const message = String(error?.message ?? error);
  return message.includes('Unknown file extension ".astro"');
}

function staticallyExportsRenderPage(source) {
  if (!/\brenderPage\s*[:=]\s*(async\s*)?(\([^)]*\)|[A-Za-z_$][\w$]*)?\s*=>|\brenderPage\s*[:=]\s*(async\s*)?function\b|\basync\s+renderPage\s*\(|\brenderPage\s*\(/m.test(source)) {
    return false;
  }
  if (/export\s+default\s+{[\s\S]*\brenderPage\b[\s\S]*}/m.test(source)) {
    return true;
  }
  const defaultName = source.match(/export\s+default\s+([A-Za-z_$][\w$]*)\s*;?/m)?.[1];
  const namedExport = source.match(/export\s*{\s*([A-Za-z_$][\w$]*)\s+as\s+renderer\s*}/m)?.[1] ?? source.match(/export\s*{\s*([A-Za-z_$][\w$]*)\s*}/m)?.[1];
  const rendererName = defaultName ?? namedExport;
  if (!rendererName) {
    return false;
  }
  const declaration = new RegExp(`(?:const|let|var)\\s+${rendererName}\\b[\\s\\S]*?\\{[\\s\\S]*?\\brenderPage\\b`, 'm');
  return declaration.test(source);
}

function parseArgs(argv) {
  const out = {};
  for (let i = 0; i < argv.length; i++) {
    const arg = argv[i];
    if (!arg.startsWith('--')) continue;
    const body = arg.slice(2);
    const equals = body.indexOf('=');
    if (equals >= 0) {
      out[body.slice(0, equals)] = body.slice(equals + 1);
      continue;
    }
    out[body] = argv[++i];
  }
  return out;
}
