import Combine
import Foundation

@MainActor
final class RecentSearchesRepository: ObservableObject {
    static let shared = RecentSearchesRepository()

    @Published private(set) var recentSearches: [RecentSearch] = []

    private static let maxRecent = 15
    private static let legacyKey = "rosetta_recent_searches"
    private var currentAccount: String = ""

    private init() {}

    func setAccount(_ accountPublicKey: String) {
        let account = accountPublicKey.trimmingCharacters(in: .whitespacesAndNewlines)
        guard account != currentAccount else { return }
        currentAccount = account
        load()
    }

    func clearSession() {
        currentAccount = ""
        recentSearches = []
    }

    func add(_ user: SearchUser) {
        let recent = RecentSearch(
            publicKey: user.publicKey,
            title: user.title,
            username: user.username,
            verified: Int(user.verified)
        )
        add(recent)
    }

    func add(_ recent: RecentSearch) {
        guard !currentAccount.isEmpty else { return }
        recentSearches.removeAll { $0.publicKey == recent.publicKey }
        recentSearches.insert(recent, at: 0)
        if recentSearches.count > Self.maxRecent {
            recentSearches = Array(recentSearches.prefix(Self.maxRecent))
        }
        persist()
    }

    func remove(publicKey: String) {
        guard !currentAccount.isEmpty else { return }
        recentSearches.removeAll { $0.publicKey == publicKey }
        persist()
    }

    func clearAll() {
        guard !currentAccount.isEmpty else {
            recentSearches = []
            return
        }
        recentSearches = []
        UserDefaults.standard.removeObject(forKey: scopedKey)
    }

    private var scopedKey: String {
        "rosetta_recent_searches_\(currentAccount)"
    }

    private func load() {
        guard !currentAccount.isEmpty else {
            recentSearches = []
            return
        }

        if let data = UserDefaults.standard.data(forKey: scopedKey),
           let list = try? JSONDecoder().decode([RecentSearch].self, from: data)
        {
            recentSearches = Array(list.prefix(Self.maxRecent))
            return
        }

        if let data = UserDefaults.standard.data(forKey: Self.legacyKey),
           let list = try? JSONDecoder().decode([RecentSearch].self, from: data)
        {
            recentSearches = Array(list.prefix(Self.maxRecent))
            persist()
            UserDefaults.standard.removeObject(forKey: Self.legacyKey)
            return
        }

        recentSearches = []
    }

    private func persist() {
        guard !currentAccount.isEmpty else { return }
        guard let data = try? JSONEncoder().encode(recentSearches) else { return }
        UserDefaults.standard.set(data, forKey: scopedKey)
    }
}
