/**
 * Thin Radarr v3 API client. Used to add new movies, list quality
 * profiles and root folders, and reconcile our TMDB-keyed view of the
 * library against what Radarr already has or is downloading.
 *
 * All endpoints expect an `X-Api-Key` header. Calls return null on
 * network or HTTP failure so callers can fall through gracefully.
 */

import type { ArrInstance } from '../stores/arr-instances-store'

export interface RadarrRootFolder {
  id: number
  path: string
  freeSpace?: number
  unmappedFolders?: { name: string; path: string }[]
}

export interface RadarrQualityProfile {
  id: number
  name: string
  cutoff: number
}

export interface RadarrTag {
  id: number
  label: string
}

export interface RadarrMovie {
  id?: number
  title: string
  originalTitle?: string
  year?: number
  tmdbId: number
  imdbId?: string | null
  hasFile?: boolean
  monitored?: boolean
  status?: 'announced' | 'inCinemas' | 'released' | 'deleted'
  qualityProfileId?: number
  rootFolderPath?: string
  tags?: number[]
  added?: string
  sizeOnDisk?: number
  isAvailable?: boolean
  /** Posters / fanart attached. */
  images?: { coverType: string; remoteUrl?: string; url?: string }[]
}

export interface RadarrLookupResult extends RadarrMovie {
  /** Returned by /lookup with no `id` until added. */
  folder?: string
}

export interface RadarrQueueItem {
  id: number
  movieId?: number
  title: string
  status: string
  trackedDownloadStatus?: string
  size?: number
  sizeleft?: number
  timeleft?: string
  estimatedCompletionTime?: string
}

export interface RadarrSystemStatus {
  version: string
  startTime?: string
  branch?: string
  appData?: string
  isProduction?: boolean
}

export interface AddRadarrMoviePayload {
  tmdbId: number
  qualityProfileId: number
  rootFolderPath: string
  monitored?: boolean
  searchOnAdd?: boolean
  tags?: number[]
  /** Required by Radarr but the lookup payload supplies it; we pass it back unchanged. */
  title: string
  titleSlug: string
  year: number
  images?: { coverType: string; remoteUrl?: string; url?: string }[]
  minimumAvailability?: 'announced' | 'inCinemas' | 'released' | 'preDB'
}

export function buildAddRadarrMovieBody(payload: AddRadarrMoviePayload) {
  return {
    tmdbId: payload.tmdbId,
    qualityProfileId: payload.qualityProfileId,
    rootFolderPath: payload.rootFolderPath,
    monitored: payload.monitored ?? true,
    title: payload.title,
    titleSlug: payload.titleSlug,
    year: payload.year,
    images: payload.images || [],
    tags: payload.tags || [],
    minimumAvailability: payload.minimumAvailability || 'released',
    addOptions: {
      searchForMovie: payload.searchOnAdd ?? true,
      monitor: 'movieOnly',
    },
  }
}

class RadarrClient {
  instance: ArrInstance
  constructor(instance: ArrInstance) {
    this.instance = instance
  }

  private url(path: string): string {
    const base = this.instance.baseUrl.replace(/\/+$/, '')
    return `${base}/api/v3${path}`
  }

  private async req<T>(path: string, init: RequestInit = {}): Promise<T | null> {
    try {
      const res = await fetch(this.url(path), {
        ...init,
        headers: {
          'X-Api-Key': this.instance.apiKey,
          'Content-Type': 'application/json',
          ...(init.headers || {}),
        },
      })
      if (!res.ok) return null
      const text = await res.text()
      return text ? (JSON.parse(text) as T) : (null as unknown as T)
    } catch {
      return null
    }
  }

  systemStatus() { return this.req<RadarrSystemStatus>('/system/status') }
  qualityProfiles() { return this.req<RadarrQualityProfile[]>('/qualityprofile') }
  rootFolders() { return this.req<RadarrRootFolder[]>('/rootfolder') }
  tags() { return this.req<RadarrTag[]>('/tag') }
  movies() { return this.req<RadarrMovie[]>('/movie') }
  queue() { return this.req<{ records: RadarrQueueItem[] }>('/queue') }

  /**
   * Look up a movie by TMDB id. Returns the metadata Radarr needs to add
   * it; `id` is undefined until the movie has been added.
   */
  lookupByTmdbId(tmdbId: number) {
    return this.req<RadarrLookupResult[]>(
      `/movie/lookup/tmdb?tmdbId=${encodeURIComponent(tmdbId)}`,
    )
  }

  async addMovie(payload: AddRadarrMoviePayload): Promise<RadarrMovie | null> {
    const body = buildAddRadarrMovieBody(payload)
    return this.req<RadarrMovie>('/movie', {
      method: 'POST',
      body: JSON.stringify(body),
    })
  }

  removeMovie(id: number, deleteFiles = false) {
    return this.req<void>(
      `/movie/${id}?deleteFiles=${deleteFiles ? 'true' : 'false'}&addImportExclusion=false`,
      { method: 'DELETE' },
    )
  }

  searchMovie(id: number) {
    return this.req<void>('/command', {
      method: 'POST',
      body: JSON.stringify({ name: 'MoviesSearch', movieIds: [id] }),
    })
  }
}

export function radarrClient(instance: ArrInstance) {
  return new RadarrClient(instance)
}
