// Cover Art Archive client.
//
// No API key is required, so the client is always enabled. A polite per-host
// rate limit (~250ms) is enforced via the http base.
//
// /release/{mbid} returns JSON listing images[]; we pick the front image. CAA
// then redirects the image URL to archive.org, but we return the URL string
// directly (callers can fetch it; the http base follows redirects by default).
// A 404 (no cover art for that release) is treated as a clean miss (null).
//
// /artist/{mbid} returns artist images (same structure).

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

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

interface CaaImage {
  image?: string;
  front?: boolean;
  thumbnails?: { '500'?: string; large?: string; small?: string };
}

interface CaaReleaseResponse {
  images?: CaaImage[];
}

export class CoverArtClient {
  private readonly cfg: CoverArtConfig;
  private readonly userAgent: string;

  constructor(cfg: CoverArtConfig = integrationsConfig.coverart) {
    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,
    });
  }

  /**
   * Return the front cover URL for a release MBID (preferring the 500px
   * thumbnail, falling back to the full image), or null on no art (404) / error.
   */
  async getReleaseCoverUrl(releaseMbid: string): Promise<string | null> {
    if (releaseMbid.trim() === '') return null;

    const path = `/release/${encodeURIComponent(releaseMbid)}`;

    try {
      const data = await this.get<CaaReleaseResponse>(path);
      const images = data.images ?? [];
      const front = images.find((img) => img.front) ?? images[0];
      if (!front) return null;
      return front.thumbnails?.['500'] ?? front.image ?? null;
    } catch (err) {
      // 404 means no cover art for this release; treat as a clean miss.
      if (err instanceof HttpError && err.status === 404) return null;
      console.warn('[CoverArt] getReleaseCoverUrl failed:', (err as Error).message);
      return null;
    }
  }

  /**
   * Return the front cover URL for a release-group MBID (preferring the 500px
   * thumbnail, falling back to the full image), or null on no art (404) / error.
   *
   * This is the preferred CAA endpoint when a release-group MBID is available:
   * it aggregates cover art across all releases in the group, so it hits more
   * often than the per-release endpoint. Now that `albums.mbid` stores
   * release-group MBIDs (from the MusicBrainz release-group search), this is a
   * direct, exact lookup — no search step required.
   */
  async getReleaseGroupCoverUrl(releaseGroupMbid: string): Promise<string | null> {
    if (releaseGroupMbid.trim() === '') return null;

    const path = `/release-group/${encodeURIComponent(releaseGroupMbid)}`;

    try {
      const data = await this.get<CaaReleaseResponse>(path);
      const images = data.images ?? [];
      const front = images.find((img) => img.front) ?? images[0];
      if (!front) return null;
      return front.thumbnails?.['500'] ?? front.image ?? null;
    } catch (err) {
      if (err instanceof HttpError && err.status === 404) return null;
      console.warn('[CoverArt] getReleaseGroupCoverUrl failed:', (err as Error).message);
      return null;
    }
  }

  /**
   * Cover Art Archive does NOT provide artist images, only release images.
   * This method always returns null — kept for interface compatibility.
   */
  async getArtistImageUrl(_artistMbid: string): Promise<string | null> {
    return null;
  }
}
