import { apiClient } from '@/services/api/client';
import { Track, PaginatedResponse, TrackDTO } from '@/types/api';
import { trackSchema } from '@/schemas/apiSchemas';
import { uploadService, UploadMetadata } from './uploadService';

const env = {
  API_URL: import.meta.env.VITE_API_URL || '',
};

const mapTrackDTO = (dto: TrackDTO): Track =>
  ({
    id: dto.id,
    title: dto.title,
    artist:
      typeof dto.artist === 'object' ? (dto.artist as any).name : dto.artist,
    album: dto.album || 'Unknown',
    duration: dto.duration_formatted || '0:00',
    durationSec: dto.duration || 0,
    genre: dto.genre || 'None',
    year: dto.year || new Date().getFullYear(),
    coverUrl: dto.cover_art_path
      ? `${env.API_URL}${dto.cover_art_path}`
      : undefined,
    cover_art_path: dto.cover_art_path,
    filePath: dto.file_path,
    file_path: dto.file_path,
    file_size: dto.file_size || 0,
    format: dto.format || 'mp3',
    bitrate: dto.bitrate || 0,
    sample_rate: dto.sample_rate || 0,
    play_count: dto.play_count || 0,
    like_count: dto.like_count || 0,
    plays: dto.play_count || 0,
    likes: dto.like_count || 0,
    created_at: dto.created_at,
    updated_at: dto.updated_at,
    creator_id: dto.creator_id,
    is_public: dto.is_public ?? true,
    status: dto.status as any,
    stream_status: (dto.stream_status as any) || 'pending',
    stream_manifest_url: dto.stream_manifest_url,
  }) as Track;

export const trackService = {
  list: async (params?: {
    user_id?: string;
    artist?: string;
    genre?: string;
    page?: number;
    limit?: number;
    sort_by?: string;
    order?: 'asc' | 'desc';
    query?: string;
    search?: string;
  }) => {
    const response = await apiClient.get<PaginatedResponse<TrackDTO>>(
      '/tracks',
      {
        params: {
          ...params,
          query: params?.query || params?.search,
        },
      },
    );
    const data = response.data;
    const items = data.items || [];
    return {
      tracks: items.map(mapTrackDTO),
      pagination: {
        total: data.total,
        page: data.page,
        limit: data.limit,
        total_pages: data.total_pages,
        has_next: data.has_next,
        has_prev: data.has_prev,
      },
    };
  },

  search: async (query: string) => {
    const response = await apiClient.get<TrackDTO[]>('/tracks/search', {
      params: { query },
    });
    return { tracks: response.data.map(mapTrackDTO) };
  },

  get: async (id: string) => {
    const response = await apiClient.get<TrackDTO>(`/tracks/${id}`, {
      validateSchema: trackSchema,
    } as any);
    return { track: mapTrackDTO(response.data) };
  },

  update: async (id: string, data: Partial<Track>) => {
    const payload = {
      title: data.title,
      artist: data.artist,
      album: data.album,
      genre: data.genre,
      is_public: data.is_public,
    };
    const response = await apiClient.put<TrackDTO>(`/tracks/${id}`, payload, {
      validateSchema: trackSchema,
    } as any);
    return { track: mapTrackDTO(response.data) };
  },

  delete: async (id: string) => apiClient.delete(`/tracks/${id}`),

  like: async (id: string) => apiClient.post(`/tracks/${id}/like`),

  unlike: async (id: string) => apiClient.delete(`/tracks/${id}/like`),

  recordPlay: async (id: string) => apiClient.post(`/tracks/${id}/play`),

  download: async (id: string) => {
    const response = await apiClient.get(`/tracks/${id}/download`, {
      responseType: 'blob',
    });
    return response.data;
  },

  upload: async (
    file: File,
    metadata: UploadMetadata,
    onProgress?: (progress: number) => void,
  ) => {
    return await uploadService.uploadTrack(file, metadata, onProgress);
  },

  getStatus: async (trackId: string) => {
    return await uploadService.getTrackStatus(trackId);
  },
};
