import { readFile } from 'node:fs/promises';
import path from 'node:path';
import { dist, requireDist, resolveFile } from './lib/dist.mjs';
import { walk } from './lib/walk.mjs';

const allowedPreservedRoutes = new Set(['/fleeting/', '/reconcile/']);
const failures = [];

async function targetExists(pathname) {
  if (allowedPreservedRoutes.has(pathname)) return true;
  return (await resolveFile(pathname)) !== null;
}

await requireDist();

const files = await walk(dist);
const checkedFiles = files.filter((file) => /\.(html|xml|css|webmanifest)$/.test(file));

function pagePathname(file) {
  const rel = path.relative(dist, file).replaceAll(path.sep, '/');
  if (rel === 'index.html') return '/';
  if (rel.endsWith('/index.html')) return `/${rel.slice(0, -'index.html'.length)}`;
  return `/${rel}`;
}

function collectUrlReferences(body, rel) {
  const urls = [];

  for (const match of body.matchAll(/\b(?:href|src|poster)=["']([^"']+)["']/g)) {
    urls.push(match[1]);
  }

  for (const match of body.matchAll(/\bsrcset=["']([^"']+)["']/g)) {
    for (const candidate of match[1].split(',')) {
      const url = candidate.trim().split(/\s+/)[0];
      if (url) urls.push(url);
    }
  }

  if (rel.endsWith('.css')) {
    for (const match of body.matchAll(/url\(\s*['"]?([^'")]+)['"]?\s*\)/g)) {
      urls.push(match[1]);
    }
  }

  if (rel.endsWith('.webmanifest')) {
    try {
      const manifest = JSON.parse(body);
      for (const key of ['start_url', 'scope']) {
        if (typeof manifest[key] === 'string') urls.push(manifest[key]);
      }
      for (const icon of manifest.icons ?? []) {
        if (typeof icon?.src === 'string') urls.push(icon.src);
      }
      for (const screenshot of manifest.screenshots ?? []) {
        if (typeof screenshot?.src === 'string') urls.push(screenshot.src);
      }
    } catch {
      failures.push(`${rel}: invalid web manifest JSON`);
    }
  }

  return urls;
}

for (const file of checkedFiles) {
  const body = await readFile(file, 'utf8');
  const rel = path.relative(dist, file);
  const baseUrl = new URL(pagePathname(file), 'https://schmelczer.dev');

  for (const raw of collectUrlReferences(body, rel)) {
    if (/^(mailto:|tel:|data:)/i.test(raw)) continue;

    let parsed;
    try {
      parsed = new URL(raw, baseUrl);
    } catch {
      failures.push(`${rel}: invalid URL ${raw}`);
      continue;
    }

    if (parsed.origin !== 'https://schmelczer.dev') continue;
    if (!(await targetExists(parsed.pathname))) {
      failures.push(`${rel}: missing local target ${parsed.pathname}`);
    }
  }
}

if (failures.length > 0) {
  console.error(failures.join('\n'));
  process.exit(1);
}

console.log('No missing local href/src targets found in dist/.');
