package com.horrortv.app.util

import android.util.Log
import com.horrortv.app.domain.model.AppError
import retrofit2.HttpException
import java.io.IOException
import java.net.ConnectException
import java.net.SocketTimeoutException
import java.net.UnknownHostException

sealed class ApiException : Exception() {
    
    abstract fun toAppError(): AppError
    
    data class NetworkUnavailable(
        override val message: String = "No hay conexión a internet",
        override val cause: Throwable? = null
    ) : ApiException() {
        override fun toAppError(): AppError = AppError.NetworkError(
            userMessage = message,
            debugMessage = "Network unavailable: ${cause?.message}",
            cause = cause
        )
    }
    
    data class Timeout(
        override val message: String = "Tiempo de espera agotado",
        override val cause: Throwable? = null
    ) : ApiException() {
        override fun toAppError(): AppError = AppError.NetworkError(
            userMessage = message,
            debugMessage = "Request timeout",
            cause = cause
        )
    }
    
    data class ServerError(
        val code: Int,
        override val message: String = "Error del servidor",
        override val cause: Throwable? = null
    ) : ApiException() {
        override fun toAppError(): AppError = AppError.ApiError(
            userMessage = message,
            debugMessage = "Server error: $code",
            code = code,
            cause = cause
        )
    }
    
    data class RateLimited(
        override val message: String = "Demasiadas solicitudes. Intenta más tarde.",
        override val cause: Throwable? = null
    ) : ApiException() {
        override fun toAppError(): AppError = AppError.ApiError(
            userMessage = message,
            debugMessage = "Rate limited (429)",
            code = 429,
            cause = cause
        )
    }
    
    data class Unknown(
        override val message: String = "Error inesperado",
        override val cause: Throwable? = null
    ) : ApiException() {
        override fun toAppError(): AppError = AppError.UnknownError(
            userMessage = message,
            debugMessage = cause?.message ?: "Unknown error",
            cause = cause
        )
    }
    
    companion object {
        private val retryableCodes = setOf(429, 500, 502, 503, 504)
        
        fun isRetryable(error: ApiException): Boolean {
            return error is Timeout || 
                   error is RateLimited || 
                   (error is ServerError && error.code in retryableCodes)
        }
        
        fun fromThrowable(throwable: Throwable): ApiException {
            return when (throwable) {
                is ApiException -> throwable
                is SocketTimeoutException -> Timeout(cause = throwable)
                is ConnectException -> NetworkUnavailable(cause = throwable)
                is UnknownHostException -> NetworkUnavailable(cause = throwable)
                is IOException -> NetworkUnavailable(cause = throwable)
                is HttpException -> {
                    val code = throwable.code()
                    if (code == 429) RateLimited(cause = throwable)
                    else if (code in retryableCodes) ServerError(code, cause = throwable)
                    else ServerError(code, cause = throwable)
                }
                else -> Unknown(cause = throwable)
            }
        }
    }
}