import { continueWatchingItems } from '@/services/mock-data'
import {
  apiGet,
  apiPost,
  isMockApiEnabled,
  mockResponse,
  type ServiceRequestOptions,
} from '@/services/api-client'
import type { ContinueWatchingItem, ProgressUpdateInput } from '@/types/domain'

const cloneContinueWatchingItem = (entry: ContinueWatchingItem): ContinueWatchingItem => ({
  item: {
    id: entry.item.id,
    provider: entry.item.provider,
    providerId: entry.item.providerId,
    title: entry.item.title,
    overview: entry.item.overview,
    type: entry.item.type,
    releaseDate: entry.item.releaseDate,
    genres: [...entry.item.genres],
    platforms: [...entry.item.platforms],
    rating: entry.item.rating,
    runtimeMinutes: entry.item.runtimeMinutes,
    artworkKey: entry.item.artworkKey,
  },
  progress: {
    itemId: entry.progress.itemId,
    seasonNumber: entry.progress.seasonNumber,
    episodeNumber: entry.progress.episodeNumber,
    progressPercent: entry.progress.progressPercent,
    lastWatchedAt: entry.progress.lastWatchedAt,
  },
})

let mockContinueWatching = continueWatchingItems.map(cloneContinueWatchingItem)

const authHeaders = (accessToken: string): Record<string, string> => ({
  Authorization: `Bearer ${accessToken}`,
})

export const progressService = {
  getContinueWatching: async (
    accessToken: string,
    options: ServiceRequestOptions = {},
  ): Promise<ContinueWatchingItem[]> => {
    if (isMockApiEnabled()) {
      return mockResponse(
        '/api/v1/progress/continue-watching',
        () => mockContinueWatching.map(cloneContinueWatchingItem),
        options,
      )
    }

    return apiGet<ContinueWatchingItem[]>(
      '/api/v1/progress/continue-watching',
      {},
      authHeaders(accessToken),
    )
  },

  updateProgress: async (
    accessToken: string,
    input: ProgressUpdateInput,
    options: ServiceRequestOptions = {},
  ): Promise<ContinueWatchingItem[]> => {
    if (isMockApiEnabled()) {
      return mockResponse(
        '/api/v1/progress',
        () => {
          const next = mockContinueWatching.filter(
            (entry) =>
              !(
                entry.item.id === input.mediaId &&
                entry.progress.seasonNumber === input.seasonNumber &&
                entry.progress.episodeNumber === input.episodeNumber
              ),
          )

          if (input.progressPercent > 0 && input.progressPercent < 100) {
            const current = continueWatchingItems
              .map(cloneContinueWatchingItem)
              .find((entry) => entry.item.id === input.mediaId)

            if (!current) {
              throw new Error('media not found')
            }

            next.unshift({
              item: current.item,
              progress: {
                itemId: input.mediaId,
                seasonNumber: Math.max(1, input.seasonNumber),
                episodeNumber: Math.max(1, input.episodeNumber),
                progressPercent: input.progressPercent,
                lastWatchedAt: new Date().toISOString(),
              },
            })
          }

          mockContinueWatching = next.slice(0, 12)
          return mockContinueWatching.map(cloneContinueWatchingItem)
        },
        options,
      )
    }

    return apiPost<ContinueWatchingItem[]>(
      '/api/v1/progress',
      {
        mediaId: input.mediaId,
        seasonNumber: input.seasonNumber,
        episodeNumber: input.episodeNumber,
        progressPercent: input.progressPercent,
      },
      authHeaders(accessToken),
    )
  },
}
