import { mediaCatalog } from '@/services/mock-data'
import { apiGet, isMockApiEnabled, mockResponse, type ServiceRequestOptions } from '@/services/api-client'
import type { SearchFilters, SearchResult } from '@/types/domain'

const normalize = (value: string): string => value.trim().toLowerCase()

const calculateScore = (title: string, query: string, rating: number): number => {
  const cleanTitle = normalize(title)
  const cleanQuery = normalize(query)

  if (cleanTitle === cleanQuery) {
    return Math.min(100, 70 + rating * 3)
  }

  if (cleanTitle.startsWith(cleanQuery)) {
    return Math.min(98, 60 + rating * 3)
  }

  return Math.min(95, 45 + rating * 4)
}

export const searchService = {
  search: async (
    query: string,
    filters: SearchFilters,
    options: ServiceRequestOptions = {},
  ): Promise<SearchResult[]> => {
    const term = normalize(query)

    if (!term) {
      return []
    }

    if (isMockApiEnabled()) {
      return mockResponse(
        '/api/v1/search',
        () =>
          mediaCatalog
            .filter((item) => {
              if (filters.mediaType && filters.mediaType !== 'all' && item.type !== filters.mediaType) {
                return false
              }

              if (filters.genre && !item.genres.includes(filters.genre)) {
                return false
              }

              return (
                normalize(item.title).includes(term) ||
                normalize(item.overview).includes(term) ||
                item.genres.some((genre) => normalize(genre).includes(term))
              )
            })
            .map((item) => ({
              id: item.id,
              mediaType: item.type,
              title: item.title,
              subtitle:
                item.type === 'game' && item.platforms.length > 0
                  ? `${item.genres.join(' • ')} · ${item.platforms.join(' • ')} · ${new Date(item.releaseDate).getFullYear()}`
                  : `${item.genres.join(' • ')} · ${new Date(item.releaseDate).getFullYear()}`,
              genres: item.genres,
              score: calculateScore(item.title, term, item.rating),
            }))
            .sort((left, right) => right.score - left.score)
            .slice(0, 12),
        options,
      )
    }

    return apiGet<SearchResult[]>('/api/v1/search', {
      query: term,
      genre: filters.genre,
      mediaType: filters.mediaType,
    })
  },
}
