// SomaFM source adapter — implements the RadioSource contract from
// base-source.js. SomaFM is a listener-supported indie radio network
// that publicly exposes a station catalogue (channels.json) and per-
// station playlist files (.pls) — no API key required.
//
// Reference: https://somafm.com/

import { parsePls } from '../lib/playlist-parser.js';

const CHANNELS_URL = 'https://somafm.com/channels.json';

/** @type {import('./base-source.js').RadioSource} */
export const somaFM = {
  id: 'somafm',
  displayName: 'SomaFM',

  async listStations() {
    const res = await fetch(CHANNELS_URL, { cache: 'no-store' });
    if (!res.ok) throw new Error(`SomaFM channels.json HTTP ${res.status}`);
    const data = await res.json();
    const channels = Array.isArray(data?.channels) ? data.channels : [];

    return channels.map(ch => ({
      id:          `somafm:${ch.id}`,
      sourceId:    'somafm',
      name:        ch.title || ch.id,
      description: ch.description || '',
      genre:       ch.genre || '',
      artworkUrl:  ch.image || '',
      // We don't resolve the stream here — that happens lazily on play
      // (one extra HTTP fetch per station change, beats ~150 upfront).
      streamUrls:  [],
      // Keep the raw playlists list around so resolveStreamUrl can pick
      // the best one without re-fetching the catalogue.
      _playlists:  Array.isArray(ch.playlists) ? ch.playlists : [],
    }));
  },

  async resolveStreamUrl(station) {
    // Prefer mp3 + highest available quality. SomaFM offers aac too,
    // but mp3 has the broadest browser support.
    const playlists = station._playlists || [];
    const preferred =
      playlists.find(p => p.format === 'mp3' && p.quality === 'highest') ||
      playlists.find(p => p.format === 'mp3') ||
      playlists[0];

    if (!preferred?.url) {
      throw new Error(`No playable playlist for ${station.name}`);
    }

    const res = await fetch(preferred.url, { cache: 'no-store' });
    if (!res.ok) throw new Error(`SomaFM .pls HTTP ${res.status}`);
    const text = await res.text();
    const streams = parsePls(text);

    if (!streams.length) {
      throw new Error(`Empty playlist for ${station.name}`);
    }
    return streams[0];
  },

  async getNowPlaying(station) {
    // SomaFM publishes per-channel song history at
    //   https://somafm.com/songs/{shortId}.json
    // The first entry is the current track.
    const shortId = station.id.split(':')[1];
    if (!shortId) return null;
    try {
      const res = await fetch(`https://somafm.com/songs/${shortId}.json`, { cache: 'no-store' });
      if (!res.ok) return null;
      const data = await res.json();
      const songs = Array.isArray(data?.songs) ? data.songs : [];
      const cur = songs[0];
      if (!cur) return null;
      return {
        title:  cur.title  || '',
        artist: cur.artist || '',
        album:  cur.album  || '',
      };
    } catch {
      return null;
    }
  },
};
