import Foundation
@testable import BearWaveCore

try checkRadioBrowserDecoding()
checkPercentEncoding()
checkNormalizedSearch()
await checkStationLibrary()
print("BearWave checks passed")

private func checkRadioBrowserDecoding() throws {
    let url = Bundle.module.url(forResource: "stations", withExtension: "json")!
    let stations = try RadioBrowserClient.decodeStations(from: Data(contentsOf: url))
    expect(stations.count == 2, "decode should filter invalid stations")
    expect(stations[0].id == "alpha", "station id should prefer UUID")
    expect(stations[0].playbackURLString == "https://example.test/alpha-resolved", "resolved URL should be playback URL")
    expect(stations[1].bitrate == 96, "bitrate should decode from string")
    expect(stations[1].votes == 50, "votes should decode from string")
}

private func checkPercentEncoding() {
    expect(RadioBrowserClient.percentEncodePathComponent("classic rock") == "classic%20rock", "path values should be percent encoded")
}

private func checkNormalizedSearch() {
    expect(RadioBrowserClient.normalizedSearchText("SLAM!") == "slam", "normalization should ignore punctuation")
    expect(RadioBrowserClient.normalizedSearchText("SLÁM Radio") == "slamradio", "normalization should fold accents and separators")
    expect(RadioBrowserClient.normalizedSearchTokens("Radio Islamabad").contains("slam") == false, "tokens should not match inside another word")
    expect(RadioBrowserClient.normalizedSearchTokens("SLAM! Radio").contains("slam"), "tokens should match punctuation-separated station names")
}

@MainActor
private func checkStationLibrary() {
    let library = makeLibrary()
    let favorite = RadioStation(uuid: "one", name: "One", resolvedURL: "https://example.test/one")
    library.toggleFavorite(favorite)
    library.toggleFavorite(favorite)
    expect(library.favorites.isEmpty, "favorites should deduplicate by UUID")

    for index in 0..<25 {
        library.recordPlayback(RadioStation(uuid: "\(index)", name: "Station \(index)", resolvedURL: "https://example.test/\(index)"))
    }
    library.recordPlayback(RadioStation(uuid: "24", name: "Station 24", resolvedURL: "https://example.test/24"))
    expect(library.recentStations.count == 20, "recent stations should be limited to 20")
    expect(library.recentStations.first?.uuid == "24", "recent stations should move duplicates to the front")
    expect(Set(library.recentStations.map(\.uuid)).count == 20, "recent stations should stay unique")

    library.stations = [
        RadioStation(name: "Zoo News", resolvedURL: "https://example.test/zoo", tags: "news", bitrate: 96, votes: 3),
        RadioStation(name: "Alpha Rock", resolvedURL: "https://example.test/alpha", tags: "rock", bitrate: 192, votes: 1)
    ]
    library.filterQuery = "rock"
    expect(library.visibleStations.map(\.name) == ["Alpha Rock"], "filter should match tags")
    library.filterQuery = ""
    library.sortMode = .bitrate
    expect(library.visibleStations.map(\.name) == ["Alpha Rock", "Zoo News"], "bitrate sort should be descending")
}

@MainActor
private func makeLibrary() -> StationLibrary {
    let root = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString)
    let persistence = PersistenceStore(
        applicationSupportDirectory: root.appendingPathComponent("ApplicationSupport"),
        cacheDirectory: root.appendingPathComponent("Caches"),
        linuxConfigDirectory: root.appendingPathComponent("Linux")
    )
    let client = RadioBrowserClient(cacheDirectory: persistence.apiCacheDirectory, session: MockSession())
    return StationLibrary(client: client, persistence: persistence)
}

private func expect(_ condition: @autoclosure () -> Bool, _ message: String) {
    if !condition() {
        fatalError(message)
    }
}

struct MockSession: URLSessionProtocol {
    func data(for request: URLRequest) async throws -> (Data, URLResponse) {
        let data = "[]".data(using: .utf8)!
        let response = HTTPURLResponse(url: request.url!, statusCode: 200, httpVersion: nil, headerFields: nil)!
        return (data, response)
    }
}
