import { createQuery } from '@tanstack/svelte-query';
import { api, apiFetch } from './client';
import { qk } from './queries';
import type { LidarrRequest, LidarrRequestKind } from './types';

/** Cadence for in-flight request polling. Tuned to match the operator's
    "fast enough to feel live, slow enough to not hammer the server"
    threshold from #369. */
const POLL_INTERVAL_MS = 12_000;

/** True if any row is mid-ingest (status === 'approved'). The status flips
    to 'completed' / 'rejected' when Lidarr finishes, so this predicate
    lets the page poll exactly while there's something interesting to watch. */
export function hasInFlightRequest(rows: readonly LidarrRequest[] | undefined): boolean {
  return rows?.some((r) => r.status === 'approved') ?? false;
}

// CreateRequestParams is the shape callers pass; unused MBID fields are
// optional, and we omit them from the wire body rather than sending empty
// strings (the backend tolerates either, but this keeps test expectations
// crisp and matches the spec §5 wire shape).
export type CreateRequestParams = {
  kind: LidarrRequestKind;
  lidarr_artist_mbid: string;
  lidarr_album_mbid?: string;
  lidarr_track_mbid?: string;
  artist_name: string;
  album_title?: string;
  track_title?: string;
};

type CreateRequestBody = {
  kind: LidarrRequestKind;
  lidarr_artist_mbid: string;
  artist_name: string;
  lidarr_album_mbid?: string;
  lidarr_track_mbid?: string;
  album_title?: string;
  track_title?: string;
};

function buildCreateBody(params: CreateRequestParams): CreateRequestBody {
  const body: CreateRequestBody = {
    kind: params.kind,
    lidarr_artist_mbid: params.lidarr_artist_mbid,
    artist_name: params.artist_name
  };
  if (params.lidarr_album_mbid)  body.lidarr_album_mbid  = params.lidarr_album_mbid;
  if (params.lidarr_track_mbid)  body.lidarr_track_mbid  = params.lidarr_track_mbid;
  if (params.album_title)        body.album_title        = params.album_title;
  if (params.track_title)        body.track_title        = params.track_title;
  return body;
}

export async function createRequest(params: CreateRequestParams): Promise<LidarrRequest> {
  return api.post<LidarrRequest>('/api/requests', buildCreateBody(params));
}

export async function listMyRequests(): Promise<LidarrRequest[]> {
  return api.get<LidarrRequest[]>('/api/requests');
}

export async function getRequest(id: string): Promise<LidarrRequest> {
  return api.get<LidarrRequest>(`/api/requests/${id}`);
}

// Server returns the cancelled row body (not 204) so callers can patch the
// cache without a refetch. api.del's return type is fixed to null, so we
// drop down to apiFetch here to keep typing honest.
export async function cancelRequest(id: string): Promise<LidarrRequest> {
  return apiFetch(`/api/requests/${id}`, { method: 'DELETE' }) as Promise<LidarrRequest>;
}

export function createMyRequestsQuery() {
  return createQuery({
    queryKey: qk.myRequests(),
    queryFn: listMyRequests,
    staleTime: 60_000,
    // Auto-poll while at least one user request is mid-ingest. Stops
    // automatically when all rows are pending/completed/rejected.
    // refetchIntervalInBackground defaults to false → polling pauses
    // while the tab is hidden and resumes on focus.
    refetchInterval: (query) =>
      hasInFlightRequest(query.state.data as LidarrRequest[] | undefined)
        ? POLL_INTERVAL_MS
        : false
  });
}
