import Foundation

/// Configuración centralizada de la API del backend VPS.
///
/// `APIConfig` proporciona todos los endpoints y parámetros de configuración
/// necesarios para comunicarse con el backend VPS que gestiona el almacenamiento
/// y serving de capítulos de manga.
///
/// # Example
/// ```swift
/// let baseURL = APIConfig.baseURL
/// let downloadEndpoint = APIConfig.Endpoints.download(mangaSlug: "one-piece", chapterNumber: 1)
/// print(downloadEndpoint) // "https://api.example.com/api/v1/download/one-piece/1"
/// ```
enum APIConfig {
    // MARK: - Base Configuration

    /// URL base del backend VPS
    ///
    /// Esta URL se usa para construir todos los endpoints de la API.
    /// Configurar según el entorno (desarrollo, staging, producción).
    ///
    /// # Configuración Actual
    /// - Producción: `https://gitea.cbcren.online`
    /// - Puerto: `3001` (se añade automáticamente)
    ///
    /// # Notas Importantes
    /// - Incluir el protocolo (`https://` o `http://`)
    /// - NO incluir el número de puerto aquí (usar la propiedad `port`)
    /// - NO incluir slash al final
    /// - Asegurarse de que el servidor sea accesible desde el dispositivo iOS
    ///
    /// # Ejemplos
    /// - `https://manga.cbcren.online` (VPS de producción)
    /// - `http://192.168.1.100` (desarrollo local)
    /// - `http://localhost` (simulador con servidor local)
    static let serverURL = "https://manga.cbcren.online"

    /// Puerto donde corre el backend API
    ///
    /// # Valor por Defecto
    /// - `nil` - Usa el puerto estándar HTTPS (443)
    ///
    /// # Notas
    /// - Con HTTPS, se usa el puerto estándar 443
    /// - Solo especificar un puerto si es diferente al estándar
    static let port: Int? = nil

    /// URL base completa para requests a la API
    ///
    /// Construye automáticamente la URL base combinando la URL del servidor y el puerto.
    /// Esta es la propiedad recomendada para usar al hacer requests a la API.
    ///
    /// # Ejemplo
    /// ```swift
    /// let endpoint = "/api/v1/manga"
    /// let url = URL(string: APIConfig.baseURL + endpoint)
    /// ```
    static var baseURL: String {
        // Si no hay puerto específico o es el puerto estándar HTTPS, usar solo la URL
        if port == nil || port == 443 {
            return serverURL
        }
        return "\(serverURL):\(port!)"
    }

    /// Versión de la API
    static var apiVersion: String {
        return "v1"
    }

    /// Path base de la API
    static var basePath: String {
        return "\(baseURL)/api/\(apiVersion)"
    }

    /// Timeout por defecto para requests (en segundos)
    static var defaultTimeout: TimeInterval {
        return 30.0
    }

    /// Timeout para requests de descarga (en segundos)
    static var downloadTimeout: TimeInterval {
        return 300.0 // 5 minutos
    }

    // MARK: - HTTP Headers

    /// Headers HTTP comunes para todas las requests
    static var commonHeaders: [String: String] {
        return [
            "Content-Type": "application/json",
            "Accept": "application/json"
        ]
    }

    /// Header de autenticación (si se requiere API key o token)
    ///
    /// - Parameter token: Token de autenticación (API key, JWT, etc.)
    /// - Returns: Dictionary con el header de autorización
    static func authHeader(token: String) -> [String: String] {
        return [
            "Authorization": "Bearer \(token)"
        ]
    }

    // MARK: - Retry Configuration

    /// Número máximo de intentos de retry para requests fallidas
    ///
    /// # Valor por Defecto
    /// - `3` intentos de retry
    ///
    /// # Comportamiento
    /// - Un valor de `0` significa sin reintentos
    /// - Los reintentos usan backoff exponencial
    /// - Solo se reintentan errores recuperables (fallos de red, timeouts, etc.)
    /// - Errores de cliente (4xx) típicamente no se reintentan
    static let maxRetries: Int = 3

    /// Delay base entre intentos de retry en segundos
    ///
    /// # Valor por Defecto
    /// - `1.0` segundo
    ///
    /// # Fórmula
    /// El delay real usa backoff exponencial:
    /// ```
    /// delay = baseRetryDelay * (2 ^ numeroDeIntento)
    /// ```
    /// - Intento 1: 1 segundo de delay
    /// - Intento 2: 2 segundos de delay
    /// - Intento 3: 4 segundos de delay
    static let baseRetryDelay: TimeInterval = 1.0

    // MARK: - Cache Configuration

    /// Número máximo de respuestas de API a cachear en memoria
    ///
    /// # Valor por Defecto
    /// - `100` respuestas cacheadas
    ///
    /// # Notas
    /// - Cachear ayuda a reducir requests de red y mejorar performance
    /// - La caché se limpia automáticamente cuando se detecta presión de memoria
    /// - Valores más grandes pueden aumentar el uso de memoria
    static let cacheMaxMemoryUsage = 100

    /// Tiempo de expiración de caché para respuestas de API en segundos
    ///
    /// # Valor por Defecto
    /// - `300.0` segundos (5 minutos)
    ///
    /// # Uso
    /// - Datos cacheados más viejos que esto se refrescarán del servidor
    /// - Configurar en `0` para deshabilitar caché
    /// - Aumentar para datos que cambian infrecuentemente
    static let cacheExpiryTime: TimeInterval = 300.0

    // MARK: - Logging Configuration

    /// Habilitar logging de requests para debugging
    ///
    /// # Valor por Defecto
    /// - `false` (deshabilitado en producción)
    ///
    /// # Comportamiento
    /// - Cuando es `true`, todas las requests y respuestas se loguean a consola
    /// - Útil para desarrollo y debugging
    /// - Debe ser `false` en builds de producción por seguridad
    ///
    /// # Recomendación
    /// Usar configuraciones de build para habilitar solo en debug:
    /// ```swift
    /// #if DEBUG
    /// static let loggingEnabled = true
    /// #else
    /// static let loggingEnabled = false
    /// #endif
    /// ```
    static let loggingEnabled = false

    // MARK: - Helper Methods

    /// Construye una URL completa para un endpoint dado
    ///
    /// - Parameter endpoint: El path del endpoint de la API (ej: "/manga/popular")
    /// - Returns: Una URL completa combinando la base URL y el endpoint
    ///
    /// # Ejemplo
    /// ```swift
    /// let url = APIConfig.url(for: "/manga/popular")
    /// // Retorna: "https://gitea.cbcren.online:3001/api/v1/manga/popular"
    /// ```
    static func url(for endpoint: String) -> String {
        // Remover slash inicial si está presente para evitar dobles slashes
        let cleanEndpoint = endpoint.hasPrefix("/") ? String(endpoint.dropFirst()) : endpoint

        // Añadir prefix de API si no está ya incluido
        if cleanEndpoint.hasPrefix("api/") {
            return baseURL + "/" + cleanEndpoint
        } else {
            return baseURL + "/" + cleanEndpoint
        }
    }

    /// Crea un objeto URL para un endpoint dado
    ///
    /// - Parameter endpoint: El path del endpoint de la API
    /// - Returns: Un objeto URL, o nil si el string es inválido
    ///
    /// # Ejemplo
    /// ```swift
    /// if let url = APIConfig.urlObject(for: "/manga/popular") {
    ///     var request = URLRequest(url: url)
    ///     // Hacer request...
    /// }
    /// ```
    static func urlObject(for endpoint: String) -> URL? {
        return URL(string: url(for: endpoint))
    }

    /// Retorna el timeout a usar para un tipo específico de request
    ///
    /// - Parameter isResourceRequest: Si esta es una request intensiva de recursos (ej: descargar imágenes)
    /// - Returns: El valor de timeout apropiado
    ///
    /// # Ejemplo
    /// ```swift
    /// let timeout = APIConfig.timeoutFor(isResourceRequest: true)
    /// // Retorna: 300.0 (downloadTimeout)
    /// ```
    static func timeoutFor(isResourceRequest: Bool = false) -> TimeInterval {
        return isResourceRequest ? downloadTimeout : defaultTimeout
    }

    // MARK: - Validation

    /// Valida que la configuración actual esté correctamente configurada
    ///
    /// - Returns: `true` si la configuración parece válida, `false` en caso contrario
    ///
    /// # Verificaciones Realizadas
    /// - URL del servidor no está vacía
    /// - Puerto está en rango válido (1-65535)
    /// - Valores de timeout son positivos
    /// - Cantidad de reintentos es no-negativa
    ///
    /// # Uso
    /// Llamar durante el inicio de la app para asegurar configuración válida:
    /// ```swift
    /// assert(APIConfig.isValid, "Configuración de API inválida")
    /// ```
    static var isValid: Bool {
        // Verificar URL del servidor
        guard !serverURL.isEmpty else { return false }

        // Verificar rango de puerto
        guard (1...65535).contains(port) else { return false }

        // Verificar timeouts
        guard defaultTimeout > 0 && downloadTimeout > 0 else { return false }

        // Verificar cantidad de reintentos
        guard maxRetries >= 0 else { return false }

        return true
    }

    // MARK: - Endpoints

    /// Estructura que contiene todos los endpoints de la API
    enum Endpoints {
        /// Endpoint para solicitar la descarga de un capítulo al VPS
        ///
        /// El backend iniciará el proceso de descarga de las imágenes
        /// y las almacenará en el VPS.
        ///
        /// - Parameters:
        ///   - mangaSlug: Slug del manga a descargar
        ///   - chapterNumber: Número del capítulo
        /// - Returns: URL completa del endpoint
        static func download(mangaSlug: String, chapterNumber: Int) -> String {
            return "\(basePath)/download/\(mangaSlug)/\(chapterNumber)"
        }

        /// Endpoint para verificar si un capítulo está descargado en el VPS
        ///
        /// - Parameters:
        ///   - mangaSlug: Slug del manga
        ///   - chapterNumber: Número del capítulo
        /// - Returns: URL completa del endpoint
        static func checkDownloaded(mangaSlug: String, chapterNumber: Int) -> String {
            return "\(basePath)/chapters/\(mangaSlug)/\(chapterNumber)"
        }

        /// Endpoint para listar todos los capítulos descargados de un manga
        ///
        /// - Parameter mangaSlug: Slug del manga
        /// - Returns: URL completa del endpoint
        static func listChapters(mangaSlug: String) -> String {
            return "\(basePath)/chapters/\(mangaSlug)"
        }

        /// Endpoint para obtener la URL de una imagen específica de un capítulo
        ///
        /// - Parameters:
        ///   - mangaSlug: Slug del manga
        ///   - chapterNumber: Número del capítulo
        ///   - pageIndex: Índice de la página (0-based)
        /// - Returns: URL completa del endpoint
        static func getImage(mangaSlug: String, chapterNumber: Int, pageIndex: Int) -> String {
            return "\(basePath)/images/\(mangaSlug)/\(chapterNumber)/\(pageIndex)"
        }

        /// Endpoint para eliminar un capítulo del VPS
        ///
        /// - Parameters:
        ///   - mangaSlug: Slug del manga
        ///   - chapterNumber: Número del capítulo
        /// - Returns: URL completa del endpoint
        static func deleteChapter(mangaSlug: String, chapterNumber: Int) -> String {
            return "\(basePath)/chapters/\(mangaSlug)/\(chapterNumber)"
        }

        /// Endpoint para obtener estadísticas de almacenamiento del VPS
        ///
        /// - Returns: URL completa del endpoint
        static func storageStats() -> String {
            return "\(basePath)/storage/stats"
        }

        /// Endpoint para hacer ping al servidor (health check)
        ///
        /// - Returns: URL completa del endpoint
        static func health() -> String {
            return "\(basePath)/health"
        }
    }

    // MARK: - Error Codes

    /// Códigos de error específicos de la API
    enum ErrorCodes {
        static let chapterNotFound = 40401
        static let chapterAlreadyDownloaded = 40901
        static let storageLimitExceeded = 50701
        static let invalidImageFormat = 42201
        static let downloadFailed = 50001
    }

    // MARK: - Environment Configuration

    /// Configuración para entorno de desarrollo
    ///
    /// # Uso
    /// Para usar configuración de desarrollo, modificar en builds de desarrollo:
    /// ```swift
    /// #if DEBUG
    /// static let serverURL = "http://192.168.1.100"
    /// #else
    /// static let serverURL = "https://gitea.cbcren.online"
    /// #endif
    /// ```
    static var development: (serverURL: String, port: Int, timeout: TimeInterval, logging: Bool) {
        return (
            serverURL: "http://192.168.1.100",
            port: 3001,
            timeout: 60.0,
            logging: true
        )
    }

    /// Configuración para entorno de staging
    static var staging: (serverURL: String, port: Int, timeout: TimeInterval, logging: Bool) {
        return (
            serverURL: "https://staging.cbcren.online",
            port: 3001,
            timeout: 30.0,
            logging: true
        )
    }

    /// Configuración para entorno de producción
    static var production: (serverURL: String, port: Int, timeout: TimeInterval, logging: Bool) {
        return (
            serverURL: "https://gitea.cbcren.online",
            port: 3001,
            timeout: 30.0,
            logging: false
        )
    }
}

// MARK: - Debug Support

#if DEBUG
extension APIConfig {
    /// Configuración de test para unit testing
    ///
    /// # Uso
    /// Usar esta configuración en unit tests para evitar hacer llamadas reales a la API:
    /// ```swift
    /// func testAPICall() {
    ///     let testConfig = APIConfig.testing
    ///     // Usar URL de servidor mock
    /// }
    /// ```
    static var testing: (serverURL: String, port: Int, timeout: TimeInterval, logging: Bool) {
        return (
            serverURL: "http://localhost:3001",
            port: 3001,
            timeout: 5.0,
            logging: true
        )
    }

    /// Imprime la configuración actual a consola (solo debug)
    static func printConfiguration() {
        print("=== API Configuration ===")
        print("Server URL: \(serverURL)")
        print("Port: \(port)")
        print("Base URL: \(baseURL)")
        print("API Version: \(apiVersion)")
        print("Default Timeout: \(defaultTimeout)s")
        print("Download Timeout: \(downloadTimeout)s")
        print("Max Retries: \(maxRetries)")
        print("Logging Enabled: \(loggingEnabled)")
        print("Cache Enabled: \(cacheExpiryTime > 0)")
        print("=========================")
    }
}
#endif

