import { ApiError, request, requestWithMeta, type ResponseWithMeta } from './client';
import type { components } from './generated/v1';

export type BlockGroup = components['schemas']['BlockGroupResponseModel'];
export type Block = components['schemas']['BlockResponseModel'];
export type BlockItem = components['schemas']['BlockItemResponseModel'];
export type BlockWithItems = components['schemas']['BlockWithItemsResponseModel'];
export type BlockPreviewItem = components['schemas']['BlockPreviewItemResponseModel'];
export type CreateBlockGroupRequest = components['schemas']['CreateBlockGroupRequest'];
export type CreateBlockRequest = components['schemas']['CreateBlockRequest'];
export type ReplaceBlockRequest = components['schemas']['ReplaceBlockRequest'];
export type BlockItemRequest = components['schemas']['BlockItemRequest'];
export type CopyBlockRequest = components['schemas']['CopyBlockRequest'];
export type SchedulingPickerOption = components['schemas']['SchedulingPickerOptionResponseModel'];

// Block groups

export function getBlockGroups(): Promise<BlockGroup[]> {
  return request<BlockGroup[]>('/api/v1/blocks/groups');
}

export function createBlockGroup(body: CreateBlockGroupRequest): Promise<BlockGroup> {
  return request<BlockGroup>('/api/v1/blocks/groups', { body, method: 'POST' });
}

export function deleteBlockGroup(id: number): Promise<void> {
  return request<void>(`/api/v1/blocks/groups/${id}`, { method: 'DELETE' });
}

// Blocks

export function getBlocks(): Promise<Block[]> {
  return request<Block[]>('/api/v1/blocks');
}

export function getBlock(id: number): Promise<Block> {
  return request<Block>(`/api/v1/blocks/${id}`);
}

export function createBlock(body: CreateBlockRequest): Promise<Block> {
  return request<Block>('/api/v1/blocks', { body, method: 'POST' });
}

export function deleteBlock(id: number): Promise<void> {
  return request<void>(`/api/v1/blocks/${id}`, { method: 'DELETE' });
}

export function getBlockItems(id: number): Promise<BlockItem[]> {
  return request<BlockItem[]>(`/api/v1/blocks/${id}/items`);
}

/** Load block items together with the block's concurrency ETag (issue #253). */
export function getBlockItemsWithMeta(id: number): Promise<ResponseWithMeta<BlockItem[]>> {
  return requestWithMeta<BlockItem[]>(`/api/v1/blocks/${id}/items`);
}

/**
 * Replace a block. Pass the last-seen ETag as `If-Match` to reject a stale overwrite with 412;
 * the resolved value carries the new ETag for a subsequent save (issue #253).
 */
export function replaceBlock(
  id: number,
  body: ReplaceBlockRequest,
  ifMatch?: string | null
): Promise<ResponseWithMeta<BlockWithItems>> {
  return requestWithMeta<BlockWithItems>(`/api/v1/blocks/${id}`, {
    body,
    method: 'PUT',
    headers: ifMatch ? { 'If-Match': ifMatch } : undefined
  });
}

export function previewBlock(id: number, body: ReplaceBlockRequest): Promise<BlockPreviewItem[]> {
  return request<BlockPreviewItem[]>(`/api/v1/blocks/${id}/preview`, { body, method: 'POST' });
}

export function copyBlock(id: number, body: CopyBlockRequest): Promise<Block> {
  return request<Block>(`/api/v1/blocks/${id}/copy`, { body, method: 'POST' });
}

// Scheduling search pickers

function searchOptions(path: string, query: string): Promise<SchedulingPickerOption[]> {
  return request<SchedulingPickerOption[]>(`${path}?query=${encodeURIComponent(query)}`);
}

export function searchCollections(query: string): Promise<SchedulingPickerOption[]> {
  return searchOptions('/api/v1/search/collections', query);
}

export function searchTelevisionShows(query: string): Promise<SchedulingPickerOption[]> {
  return searchOptions('/api/v1/search/television-shows', query);
}

export function searchTelevisionSeasons(query: string): Promise<SchedulingPickerOption[]> {
  return searchOptions('/api/v1/search/television-seasons', query);
}

export function searchSmartCollections(query: string): Promise<SchedulingPickerOption[]> {
  return searchOptions('/api/v1/search/smart-collections', query);
}

export function searchArtists(query: string): Promise<SchedulingPickerOption[]> {
  return searchOptions('/api/v1/search/artists', query);
}

export function searchMultiCollections(query: string): Promise<SchedulingPickerOption[]> {
  return searchOptions('/api/v1/search/multi-collections', query);
}

export function messageFromBlockError(error: unknown, fallback = 'Unable to load blocks'): string {
  if (error instanceof ApiError) {
    return error.detail ?? error.message;
  }

  if (error instanceof Error) {
    return error.message;
  }

  return fallback;
}
