#!/usr/bin/env node

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

const DEFAULT_SOURCE_URL = 'https://data.radio.si/api/radiostations?857df78efd094abcb98c7bbb53303c3d';

const scriptDir = path.dirname(fileURLToPath(import.meta.url));
const repoRoot = path.resolve(scriptDir, '..');

const sourceUrlArg = process.argv[2];
const stationsPathArg = process.argv[3];

const sourceUrl = sourceUrlArg && !sourceUrlArg.startsWith('--') ? sourceUrlArg : DEFAULT_SOURCE_URL;
const stationsPath = stationsPathArg && !stationsPathArg.startsWith('--')
  ? path.resolve(process.cwd(), stationsPathArg)
  : path.join(repoRoot, 'public', 'stations.json');

const [remoteStations, existingStations] = await Promise.all([
  fetchJson(sourceUrl),
  readJsonFile(stationsPath).catch(() => []),
]);

if (!Array.isArray(remoteStations)) {
  throw new Error('Expected the radio stations API to return an array.');
}

const remoteStationsById = new Set(remoteStations.map((station) => station.id));
const existingStationsById = new Map(
  existingStations
    .filter((station) => station && typeof station === 'object' && typeof station.id === 'string')
    .map((station) => [station.id, station]),
);

const updatedStations = remoteStations.map((remoteStation) => {
  const existingStation = existingStationsById.get(remoteStation.id);
  return mergeStation(existingStation, remoteStation);
}).concat(
  existingStations
    .filter((station) => station && typeof station === 'object' && typeof station.id === 'string' && !remoteStationsById.has(station.id))
    .map(normalizeStation),
);

await writeFile(stationsPath, `${JSON.stringify(updatedStations, null, 2)}\n`, 'utf8');

console.log(`Updated ${updatedStations.length} stations in ${stationsPath}`);

async function fetchJson(url) {
  const response = await fetch(url);

  if (!response.ok) {
    throw new Error(`Failed to fetch ${url}: ${response.status} ${response.statusText}`);
  }

  return response.json();
}

async function readJsonFile(filePath) {
  const contents = await readFile(filePath, 'utf8');
  return JSON.parse(contents);
}

function mergeStation(existingStation = {}, remoteStation) {
  const assets = { ...(existingStation.assets ?? {}) };
  assets.logo = remoteStation.logo;

  if (remoteStation.poster) {
    assets.poster = remoteStation.poster;
  } else {
    delete assets.poster;
  }

  const streams = { ...(existingStation.streams ?? {}) };
  streams.audio = remoteStation.liveAudio;

  if (remoteStation.liveVideo) {
    streams.video = remoteStation.liveVideo;
  } else {
    delete streams.video;
  }

  const metadata = { ...(existingStation.metadata ?? {}) };
  if (remoteStation.lastSongs) {
    metadata.lastSongs = remoteStation.lastSongs;
  }

  return {
    id: remoteStation.id,
    name: remoteStation.title ?? existingStation.name ?? remoteStation.id,
    slogan: remoteStation.slogan ?? existingStation.slogan ?? '',
    category: existingStation.category ?? '',
    country: existingStation.country ?? 'SI',
    language: existingStation.language ?? 'sl',
    region: existingStation.region ?? 'National',
    tags: Array.isArray(existingStation.tags) ? existingStation.tags : [],
    website: remoteStation.www ?? existingStation.website ?? null,
    enabled: typeof remoteStation.enabled === 'boolean' ? remoteStation.enabled : Boolean(existingStation.enabled),
    assets,
    streams,
    metadata,
  };
}

function normalizeStation(station) {
  const assets = { ...(station.assets ?? {}) };
  const streams = { ...(station.streams ?? {}) };
  const metadata = { ...(station.metadata ?? {}) };

  if (!assets.logo) {
    assets.logo = station.logo ?? '';
  }

  if (station.poster && !assets.poster) {
    assets.poster = station.poster;
  }

  if (!streams.audio) {
    streams.audio = station.streams?.audio ?? station.url ?? station.liveAudio ?? station.streamUrl ?? '';
  }

  if (!streams.video && station.liveVideo) {
    streams.video = station.liveVideo;
  }

  return {
    id: station.id,
    name: station.name ?? station.title ?? station.id,
    slogan: station.slogan ?? '',
    category: station.category ?? '',
    country: station.country ?? '',
    language: station.language ?? '',
    region: station.region ?? '',
    tags: Array.isArray(station.tags) ? station.tags : [],
    website: station.website ?? station.homepage ?? station.www ?? null,
    enabled: typeof station.enabled === 'boolean' ? station.enabled : true,
    assets,
    streams,
    metadata,
  };
}
