package com.radiola.data.repository

import android.util.Log
import com.radiola.data.remote.RadiolaApi
import com.radiola.data.remote.dto.ChartEntryDto
import com.radiola.data.remote.dto.PointDto
import com.radiola.data.remote.dto.StationPlaysDto
import com.radiola.data.remote.dto.TrackStatsDto
import com.radiola.domain.model.ChartEntry
import com.radiola.domain.model.ChartPeriod
import com.radiola.domain.model.ChartTrend
import com.radiola.domain.model.StatPoint
import com.radiola.domain.model.StationPlays
import com.radiola.domain.model.TrackStats
import com.radiola.domain.repository.ChartsRepository
import java.time.Instant
import java.time.LocalDate
import java.time.ZoneOffset
import java.time.format.DateTimeFormatter
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class ChartsRepositoryImpl @Inject constructor(
    private val api: RadiolaApi
) : ChartsRepository {

    override suspend fun getCharts(period: ChartPeriod, genre: String?): List<ChartEntry> {
        return try {
            val response = api.getCharts(period.apiValue, genre = genre)
            response.items.map { it.toDomain() }
        } catch (e: Exception) {
            Log.w("ChartsRepository", "Ошибка загрузки чартов: ${e.message}")
            emptyList()
        }
    }

    override suspend fun getGenres(): List<String> {
        return try {
            api.getGenres().genres
        } catch (e: Exception) {
            Log.w("ChartsRepository", "Ошибка загрузки жанров: ${e.message}")
            emptyList()
        }
    }

    override suspend fun getTrackStats(trackId: String): TrackStats {
        return api.getTrackStats(trackId).toDomain()
    }

    override suspend fun setLiked(trackId: String, liked: Boolean) {
        try {
            if (liked) api.likeTrack(trackId) else api.unlikeTrack(trackId)
        } catch (e: Exception) {
            Log.w("ChartsRepository", "Ошибка лайка трека $trackId: ${e.message}")
        }
    }

    // ---- Маппинг DTO → Domain ----

    private fun ChartEntryDto.toDomain() = ChartEntry(
        rank = rank,
        trackId = trackId,
        artist = artist,
        song = song,
        coverUrl = coverUrl,
        genre = genre,
        styles = styles,
        label = label,
        year = year,
        plays = plays,
        stationsCount = stationsCount,
        likes = likes,
        prevRank = prevRank,
        trend = when (trend) {
            "up" -> ChartTrend.UP
            "down" -> ChartTrend.DOWN
            "new" -> ChartTrend.NEW
            else -> ChartTrend.SAME
        }
    )

    private fun TrackStatsDto.toDomain() = TrackStats(
        trackId = trackId,
        artist = artist,
        song = song,
        album = album,
        coverUrl = coverUrl,
        genre = genre,
        styles = styles,
        label = label,
        year = year,
        releaseDate = releaseDate,
        firstSeen = firstSeen,
        totalPlays = totalPlays,
        totalLikes = totalLikes,
        isLiked = isLiked,
        currentRank = currentRank,
        peakRank = peakRank,
        stations = stations.map { it.toDomain() },
        playsTimeline = playsTimeline.map { it.toDomain() },
        likesTimeline = likesTimeline.map { it.toDomain() }
    )

    private fun StationPlaysDto.toDomain() = StationPlays(stationId, name, plays)

    private fun PointDto.toDomain(): StatPoint {
        val epochMs = try {
            Instant.parse(date).toEpochMilli()
        } catch (e: Exception) {
            // Попробуем как yyyy-MM-dd
            try {
                LocalDate.parse(date, DateTimeFormatter.ISO_LOCAL_DATE)
                    .atStartOfDay(ZoneOffset.UTC)
                    .toInstant()
                    .toEpochMilli()
            } catch (e2: Exception) {
                System.currentTimeMillis()
            }
        }
        return StatPoint(epochMs, value)
    }
}
