import { ApiError, request } from './client';
import type { components } from './generated/v1';
import type { RemoteFamily } from '../mediaSources/familyMeta';

// --- Response DTOs (re-exported from the generated spec) ---
export type LocalLibrary = components['schemas']['LocalLibraryResponseModel'];
export type LocalLibraryPath = components['schemas']['LocalLibraryPathResponseModel'];
export type LocalLibraryDetail = components['schemas']['LocalLibraryDetailResponseModel'];
export type LocalPathCheckResult = components['schemas']['LocalPathCheckResponseModel'];
export type RemoteMediaSourceItem = components['schemas']['RemoteMediaSourceItemResponseModel'];
export type RemoteMediaSourceState = components['schemas']['RemoteMediaSourceStateResponseModel'];
export type RemoteLibrary = components['schemas']['RemoteLibraryResponseModel'];
export type PathReplacement = components['schemas']['PathReplacementResponseModel'];
export type RemoteConnection = components['schemas']['RemoteConnectionResponseModel'];
export type PlexPinFlow = components['schemas']['PlexPinFlowResponseModel'];

// --- Request DTOs (re-exported from the generated spec) ---
export type CreateLocalLibraryRequest = components['schemas']['CreateLocalLibraryRequest'];
export type UpdateLocalLibraryRequest = components['schemas']['UpdateLocalLibraryRequest'];
export type UpdateLocalLibraryPathRequest = components['schemas']['UpdateLocalLibraryPathRequest'];
export type MoveLocalLibraryPathRequest = components['schemas']['MoveLocalLibraryPathRequest'];
export type LocalPathCheckRequest = components['schemas']['LocalPathCheckRequest'];
export type ReplaceRemoteLibraryPreferencesRequest = components['schemas']['ReplaceRemoteLibraryPreferencesRequest'];
export type RemoteLibraryPreferenceRequest = components['schemas']['RemoteLibraryPreferenceRequest'];
export type ReplacePathReplacementsRequest = components['schemas']['ReplacePathReplacementsRequest'];
export type PathReplacementItemRequest = components['schemas']['PathReplacementItemRequest'];
export type SaveRemoteConnectionRequest = components['schemas']['SaveRemoteConnectionRequest'];

export type { RemoteFamily } from '../mediaSources/familyMeta';

// --- Local libraries (/api/v1/libraries/local) ---

export function getLocalLibraries(): Promise<LocalLibrary[]> {
  return request<LocalLibrary[]>('/api/v1/libraries/local');
}

export function getLocalLibrary(id: number): Promise<LocalLibraryDetail> {
  return request<LocalLibraryDetail>(`/api/v1/libraries/local/${id}`);
}

export function createLocalLibrary(body: CreateLocalLibraryRequest): Promise<LocalLibrary> {
  return request<LocalLibrary>('/api/v1/libraries/local', { body, method: 'POST' });
}

export function updateLocalLibrary(id: number, body: UpdateLocalLibraryRequest): Promise<LocalLibraryDetail> {
  return request<LocalLibraryDetail>(`/api/v1/libraries/local/${id}`, { body, method: 'PUT' });
}

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

export function moveLocalLibraryPath(pathId: number, body: MoveLocalLibraryPathRequest): Promise<void> {
  return request<void>(`/api/v1/libraries/local/paths/${pathId}/move`, { body, method: 'POST' });
}

export function checkLocalPathExists(body: LocalPathCheckRequest): Promise<LocalPathCheckResult> {
  return request<LocalPathCheckResult>('/api/v1/libraries/local/path-exists', { body, method: 'POST' });
}

// --- Plex-specific convenience over the shared remote surface (/api/v1/media-sources/plex) ---

export function getPlexState(): Promise<RemoteMediaSourceState> {
  return getRemoteState('plex');
}

export function startPlexPinFlow(): Promise<PlexPinFlow> {
  return request<PlexPinFlow>('/api/v1/media-sources/plex/pin-flow', { method: 'POST' });
}

export function signOutOfPlex(): Promise<void> {
  return request<void>('/api/v1/media-sources/plex/sign-out', { method: 'POST' });
}

// --- Shared remote surface (/api/v1/media-sources/{family}); family is the only URL variance ---

export function getRemoteState(family: RemoteFamily): Promise<RemoteMediaSourceState> {
  return request<RemoteMediaSourceState>(`/api/v1/media-sources/${family}`);
}

// Connection endpoints exist only for the api-key families (Jellyfin / Emby); Plex uses the pin flow.
export function getRemoteConnection(family: 'jellyfin' | 'emby'): Promise<RemoteConnection> {
  return request<RemoteConnection>(`/api/v1/media-sources/${family}/connection`);
}

export function saveRemoteConnection(
  family: 'jellyfin' | 'emby',
  body: SaveRemoteConnectionRequest
): Promise<RemoteConnection> {
  return request<RemoteConnection>(`/api/v1/media-sources/${family}/connection`, { body, method: 'PUT' });
}

export function disconnectRemote(family: 'jellyfin' | 'emby'): Promise<void> {
  return request<void>(`/api/v1/media-sources/${family}/disconnect`, { method: 'POST' });
}

export function getRemoteLibraries(family: RemoteFamily, sourceId: number): Promise<RemoteLibrary[]> {
  return request<RemoteLibrary[]>(`/api/v1/media-sources/${family}/${sourceId}/libraries`);
}

export function replaceRemoteLibraryPreferences(
  family: RemoteFamily,
  sourceId: number,
  body: ReplaceRemoteLibraryPreferencesRequest
): Promise<RemoteLibrary[]> {
  return request<RemoteLibrary[]>(`/api/v1/media-sources/${family}/${sourceId}/libraries`, { body, method: 'PUT' });
}

export function getPathReplacements(family: RemoteFamily, sourceId: number): Promise<PathReplacement[]> {
  return request<PathReplacement[]>(`/api/v1/media-sources/${family}/${sourceId}/path-replacements`);
}

export function replacePathReplacements(
  family: RemoteFamily,
  sourceId: number,
  body: ReplacePathReplacementsRequest
): Promise<PathReplacement[]> {
  return request<PathReplacement[]>(`/api/v1/media-sources/${family}/${sourceId}/path-replacements`, {
    body,
    method: 'PUT'
  });
}

export function refreshRemoteLibraries(family: RemoteFamily, sourceId: number): Promise<void> {
  return request<void>(`/api/v1/media-sources/${family}/${sourceId}/refresh-libraries`, { method: 'POST' });
}

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

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

  return fallback;
}
