//
//  RemoteImageService.swift
//  SportsTime
//
//  Downloads and caches remote images for PDF export (team logos, stadium photos).
//

import Foundation
import UIKit

actor RemoteImageService {

    // MARK: - Errors

    enum ImageFetchError: Error, LocalizedError {
        case invalidURL
        case downloadFailed(String)
        case invalidImageData

        var errorDescription: String? {
            switch self {
            case .invalidURL:
                return "Invalid image URL"
            case .downloadFailed(let reason):
                return "Image download failed: \(reason)"
            case .invalidImageData:
                return "Downloaded data is not a valid image"
            }
        }
    }

    // MARK: - Properties

    private let urlSession: URLSession
    private var imageCache: [URL: UIImage] = [:]

    // MARK: - Init

    init() {
        // Configure URLSession with caching
        let config = URLSessionConfiguration.default
        config.requestCachePolicy = .returnCacheDataElseLoad
        config.urlCache = URLCache(
            memoryCapacity: 50 * 1024 * 1024,  // 50 MB memory
            diskCapacity: 100 * 1024 * 1024,   // 100 MB disk
            diskPath: "ImageCache"
        )
        config.timeoutIntervalForRequest = 15
        config.timeoutIntervalForResource = 30

        self.urlSession = URLSession(configuration: config)
    }

    // MARK: - Public Methods

    /// Fetch a single image from URL
    func fetchImage(from url: URL) async throws -> UIImage {
        // Check cache first
        if let cached = imageCache[url] {
            return cached
        }

        // Download image
        let (data, response) = try await urlSession.data(from: url)

        // Validate response
        guard let httpResponse = response as? HTTPURLResponse,
              (200...299).contains(httpResponse.statusCode) else {
            let statusCode = (response as? HTTPURLResponse)?.statusCode ?? -1
            throw ImageFetchError.downloadFailed("HTTP \(statusCode)")
        }

        // Create image
        guard let image = UIImage(data: data) else {
            throw ImageFetchError.invalidImageData
        }

        // Scale image for PDF (max 400pt width to keep file size reasonable)
        let scaledImage = scaleImage(image, maxWidth: 400)

        // Cache it
        imageCache[url] = scaledImage

        return scaledImage
    }

    /// Batch fetch multiple images in parallel
    func fetchImages(from urls: [URL]) async -> [URL: UIImage] {
        var results: [URL: UIImage] = [:]

        await withTaskGroup(of: (URL, UIImage?).self) { group in
            for url in urls {
                group.addTask {
                    do {
                        let image = try await self.fetchImage(from: url)
                        return (url, image)
                    } catch {
                        return (url, nil)
                    }
                }
            }

            for await (url, image) in group {
                if let image = image {
                    results[url] = image
                }
            }
        }

        return results
    }

    /// Fetch team logos by team ID
    func fetchTeamLogos(teams: [Team]) async -> [UUID: UIImage] {
        let urlToTeam: [URL: UUID] = Dictionary(
            uniqueKeysWithValues: teams.compactMap { team in
                guard let logoURL = team.logoURL else { return nil }
                return (logoURL, team.id)
            }
        )

        let images = await fetchImages(from: Array(urlToTeam.keys))

        var result: [UUID: UIImage] = [:]
        for (url, image) in images {
            if let teamId = urlToTeam[url] {
                result[teamId] = image
            }
        }

        return result
    }

    /// Fetch stadium photos by stadium ID
    func fetchStadiumPhotos(stadiums: [Stadium]) async -> [UUID: UIImage] {
        let urlToStadium: [URL: UUID] = Dictionary(
            uniqueKeysWithValues: stadiums.compactMap { stadium in
                guard let imageURL = stadium.imageURL else { return nil }
                return (imageURL, stadium.id)
            }
        )

        let images = await fetchImages(from: Array(urlToStadium.keys))

        var result: [UUID: UIImage] = [:]
        for (url, image) in images {
            if let stadiumId = urlToStadium[url] {
                result[stadiumId] = image
            }
        }

        return result
    }

    /// Clear the in-memory cache
    func clearCache() {
        imageCache.removeAll()
    }

    // MARK: - Private Methods

    /// Scale image to max width while maintaining aspect ratio
    private func scaleImage(_ image: UIImage, maxWidth: CGFloat) -> UIImage {
        let currentWidth = image.size.width
        guard currentWidth > maxWidth else { return image }

        let scale = maxWidth / currentWidth
        let newSize = CGSize(
            width: image.size.width * scale,
            height: image.size.height * scale
        )

        let renderer = UIGraphicsImageRenderer(size: newSize)
        return renderer.image { _ in
            image.draw(in: CGRect(origin: .zero, size: newSize))
        }
    }
}
