// LRCLib client (lyrics lookup).
//
// No API key is required, so the client is always enabled. A polite per-host
// rate limit (~250ms) is enforced via the http base.
//
// LRCLib's /get endpoint matches on track/artist/album/duration and returns 404
// when nothing matches; that 404 is treated as "no lyrics" (null), not an error.
// Any other failure also degrades to null so enrichment never breaks the worker.

import { integrationsConfig, LrcLibConfig } from './config.js';
import { buildUserAgent, requestJson, HttpError } from './http.js';

export interface LyricsResult {
  /** Plain-text lyrics, if available. */
  plainLyrics: string | null;
  /** Time-synced lyrics as an LRC string, if available. */
  syncedLyrics: string | null;
  provider: 'lrclib';
}

// --- Raw LRCLib response shape (only the fields we read) -------------------

interface LrcLibGetResponse {
  plainLyrics?: string | null;
  syncedLyrics?: string | null;
}

export class LrcLibClient {
  private readonly cfg: LrcLibConfig;
  private readonly userAgent: string;

  constructor(cfg: LrcLibConfig = integrationsConfig.lrclib) {
    this.cfg = cfg;
    this.userAgent = buildUserAgent(integrationsConfig.musicbrainz.contact);
  }

  private async get<T>(path: string): Promise<T> {
    return requestJson<T>(`${this.cfg.baseUrl}${path}`, {
      userAgent: this.userAgent,
      minIntervalMs: this.cfg.minIntervalMs,
    });
  }

  /**
   * Look up lyrics for a track. Returns plain + synced lyrics, or null when no
   * match (404) or on any error.
   */
  async getLyrics(
    artist: string,
    title: string,
    album?: string,
    durationSec?: number
  ): Promise<LyricsResult | null> {
    if (artist.trim() === '' || title.trim() === '') return null;

    const qs = new URLSearchParams({ track_name: title, artist_name: artist });
    if (album && album.trim() !== '') qs.set('album_name', album);
    if (durationSec !== undefined && Number.isFinite(durationSec)) {
      qs.set('duration', String(Math.round(durationSec)));
    }
    const path = `/get?${qs.toString()}`;

    try {
      const data = await this.get<LrcLibGetResponse>(path);
      const plainLyrics = data.plainLyrics ?? null;
      const syncedLyrics = data.syncedLyrics ?? null;
      if (plainLyrics === null && syncedLyrics === null) return null;
      return { plainLyrics, syncedLyrics, provider: 'lrclib' };
    } catch (err) {
      // 404 simply means no lyrics matched; treat as a clean miss.
      if (err instanceof HttpError && err.status === 404) return null;
      console.warn('[LRCLib] getLyrics failed:', (err as Error).message);
      return null;
    }
  }
}
