#!/usr/bin/env node

import { mkdir, writeFile } from 'node:fs/promises';
import path from 'node:path';
import { fileURLToPath } from 'node:url';

import { radioCountries } from '../src/radio/radioCountries.js';
import { normalizeRadioBrowserStation } from '../src/radio/radioStationNormalizer.js';
import type { RadioBrowserStation, RadioStation } from '../src/radio/radioTypes.js';

const API_ENDPOINT = 'https://de1.api.radio-browser.info/json/stations/search';

const scriptDir = path.dirname(fileURLToPath(import.meta.url));
const repoRoot = path.resolve(scriptDir, '..');
const outputPath = path.join(repoRoot, 'public', 'data', 'radio-stations.json');
const syncOutputPath = path.join(repoRoot, 'public', 'data', 'radio-stations-sync.json');

const collectedStations: RadioStation[] = [];
const seenStationIds = new Set<string>();
const seenStreamUrls = new Set<string>();
const failedCountries: string[] = [];
let successfulCountries = 0;

for (const country of radioCountries) {
  try {
    const fetchedStations = await fetchCountryStations(country.code);
    const normalizedStations = fetchedStations
      .map((station) => normalizeRadioBrowserStation(station, country.name))
      .filter((station): station is RadioStation => station !== null);

    for (const station of normalizedStations) {
      if (seenStationIds.has(station.id)) continue;
      if (seenStreamUrls.has(station.streamUrl)) continue;

      seenStationIds.add(station.id);
      seenStreamUrls.add(station.streamUrl);
      collectedStations.push(station);
    }

    successfulCountries += 1;
  } catch (error) {
    failedCountries.push(country.code);
    const message = error instanceof Error ? error.message : String(error);
    console.error(`[radio-import] Failed to import ${country.name} (${country.code}): ${message}`);
  }
}

collectedStations.sort((left, right) => {
  const countryOrder = left.country.localeCompare(right.country, undefined, { sensitivity: 'base' });
  if (countryOrder !== 0) return countryOrder;
  if (right.clickcount !== left.clickcount) return right.clickcount - left.clickcount;
  return left.name.localeCompare(right.name, undefined, { sensitivity: 'base' });
});

await mkdir(path.dirname(outputPath), { recursive: true });
const serializedStations = `${JSON.stringify(collectedStations, null, 2)}\n`;
await Promise.all([
  writeFile(outputPath, serializedStations, 'utf8'),
  writeFile(syncOutputPath, serializedStations, 'utf8'),
]);

console.log(`[radio-import] Imported ${collectedStations.length} stations from ${successfulCountries}/${radioCountries.length} countries.`);
console.log(`[radio-import] Failed countries: ${failedCountries.length > 0 ? failedCountries.join(', ') : 'None'}`);
console.log('[radio-import] Output: public/data/radio-stations.json');
console.log('[radio-import] Sync output: public/data/radio-stations-sync.json');

async function fetchCountryStations(countryCode: string): Promise<RadioBrowserStation[]> {
  const url = new URL(API_ENDPOINT);
  url.search = new URLSearchParams({
    countrycode: countryCode,
    hidebroken: 'true',
    is_https: 'true',
    order: 'clickcount',
    reverse: 'true',
    limit: '100',
  }).toString();

  const response = await fetch(url, {
    headers: {
      'user-agent': 'RadioPlayerImporter/1.0',
    },
  });

  if (!response.ok) {
    throw new Error(`${response.status} ${response.statusText}`);
  }

  const payload = (await response.json()) as unknown;
  if (!Array.isArray(payload)) {
    throw new Error('Expected an array response from Radio Browser.');
  }

  return payload as RadioBrowserStation[];
}