import APIClient
import Combine
import ComposableArchitecture
import Foundation

/*
 Simple reaction status cache that keeps up to 500 hooks in memory.
 - Hooks are evicted in LRU order.
 - Handles like status/count and dislike status per hookId.
 */
final actor SimpleReactionCache: Sendable {
    private var likeStatus: [String: Bool] = [:]
    private var likeCount: [String: Int] = [:]
    private var dislikeStatus: [String: Bool] = [:]
    private var accessOrder: [String] = [] // LRU tracking
    private let maxCacheSize = 500

    func getLikeStatus(for hookId: String) -> Bool? {
        // Update access order for LRU
        if likeStatus[hookId] != nil {
            updateAccessOrder(for: hookId)
        }
        return likeStatus[hookId]
    }

    func getLikeCount(for hookId: String) -> Int? {
        // Update access order for LRU
        if likeCount[hookId] != nil {
            updateAccessOrder(for: hookId)
        }
        return likeCount[hookId]
    }

    func getDislikeStatus(for hookId: String) -> Bool? {
        // Update access order for LRU
        if dislikeStatus[hookId] != nil {
            updateAccessOrder(for: hookId)
        }
        return dislikeStatus[hookId]
    }

    func setLikeStatus(_ isLiked: Bool, for hookId: String) {
        likeStatus[hookId] = isLiked
        updateAccessOrder(for: hookId)
        evictIfNeeded()
    }

    func setLikeCount(_ count: Int, for hookId: String) {
        likeCount[hookId] = count
        updateAccessOrder(for: hookId)
        evictIfNeeded()
    }

    func setDislikeStatus(_ isDisliked: Bool, for hookId: String) {
        dislikeStatus[hookId] = isDisliked
        updateAccessOrder(for: hookId)
        evictIfNeeded()
    }

    func updateLikeState(_ isLiked: Bool, for hookId: String) {
        let currentCount = likeCount[hookId] ?? 0
        likeStatus[hookId] = isLiked

        if isLiked {
            likeCount[hookId] = currentCount + 1
        } else {
            likeCount[hookId] = max(0, currentCount - 1)
        }
        updateAccessOrder(for: hookId)
        evictIfNeeded()
    }

    func updateDislikeState(_ isDisliked: Bool, for hookId: String) {
        dislikeStatus[hookId] = isDisliked
        updateAccessOrder(for: hookId)
        evictIfNeeded()
    }

    func hydrateFromHooks(_ hooks: [Hook]) {
        for hook in hooks {
            likeStatus[hook.id] = hook.isLiked
            likeCount[hook.id] = hook.likeCount
            dislikeStatus[hook.id] = hook.isDisliked
            updateAccessOrder(for: hook.id)
        }
        evictIfNeeded()
    }

    func removeHook(_ hookId: String) {
        likeStatus.removeValue(forKey: hookId)
        likeCount.removeValue(forKey: hookId)
        dislikeStatus.removeValue(forKey: hookId)
        accessOrder.removeAll { $0 == hookId }
    }

    private func updateAccessOrder(for hookId: String) {
        // Remove from current position
        accessOrder.removeAll { $0 == hookId }
        // Add to end (most recently used)
        accessOrder.append(hookId)
    }

    private func evictIfNeeded() {
        while likeStatus.count > maxCacheSize {
            guard let leastRecentlyUsed = accessOrder.first else { break }
            likeStatus.removeValue(forKey: leastRecentlyUsed)
            likeCount.removeValue(forKey: leastRecentlyUsed)
            dislikeStatus.removeValue(forKey: leastRecentlyUsed)
            accessOrder.removeFirst()
        }
    }
}
