import Foundation

public struct RadioStation: Codable, Hashable, Identifiable, Sendable {
    public var uuid: String
    public var name: String
    public var url: String
    public var resolvedURL: String
    public var homepage: String
    public var favicon: String
    public var country: String
    public var tags: String
    public var codec: String
    public var bitrate: Int
    public var votes: Int
    public var isOnline: Bool
    public var isFavorite: Bool
    public var isManual: Bool

    public var id: String {
        if !uuid.isEmpty { return uuid }
        if !resolvedURL.isEmpty { return resolvedURL }
        if !url.isEmpty { return url }
        return name
    }

    public var playbackURLString: String {
        resolvedURL.isEmpty ? url : resolvedURL
    }

    public var searchableText: String {
        [name, tags, country, codec].joined(separator: " ").lowercased()
    }

    public init(
        uuid: String = "",
        name: String,
        url: String = "",
        resolvedURL: String = "",
        homepage: String = "",
        favicon: String = "",
        country: String = "",
        tags: String = "",
        codec: String = "",
        bitrate: Int = 0,
        votes: Int = 0,
        isOnline: Bool = true,
        isFavorite: Bool = false,
        isManual: Bool = false
    ) {
        self.uuid = uuid
        self.name = name
        self.url = url
        self.resolvedURL = resolvedURL
        self.homepage = homepage
        self.favicon = favicon
        self.country = country
        self.tags = tags
        self.codec = codec
        self.bitrate = bitrate
        self.votes = votes
        self.isOnline = isOnline
        self.isFavorite = isFavorite
        self.isManual = isManual
    }

    enum CodingKeys: String, CodingKey {
        case uuid = "stationuuid"
        case legacyUUID = "uuid"
        case name
        case url
        case resolvedURL = "url_resolved"
        case legacyResolvedURL = "urlResolved"
        case homepage
        case favicon
        case country
        case tags
        case codec
        case bitrate
        case votes
        case lastCheckOK = "lastcheckok"
        case isFavorite
        case isManual
    }

    public init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        uuid = try container.decodeIfPresent(String.self, forKey: .uuid)
            ?? container.decodeIfPresent(String.self, forKey: .legacyUUID)
            ?? ""
        name = try container.decodeIfPresent(String.self, forKey: .name) ?? ""
        url = try container.decodeIfPresent(String.self, forKey: .url) ?? ""
        resolvedURL = try container.decodeIfPresent(String.self, forKey: .resolvedURL)
            ?? container.decodeIfPresent(String.self, forKey: .legacyResolvedURL)
            ?? ""
        homepage = try container.decodeIfPresent(String.self, forKey: .homepage) ?? ""
        favicon = try container.decodeIfPresent(String.self, forKey: .favicon) ?? ""
        country = try container.decodeIfPresent(String.self, forKey: .country) ?? ""
        tags = try container.decodeIfPresent(String.self, forKey: .tags) ?? ""
        codec = try container.decodeIfPresent(String.self, forKey: .codec) ?? ""
        bitrate = try container.decodeFlexibleInt(forKey: .bitrate) ?? 0
        votes = try container.decodeFlexibleInt(forKey: .votes) ?? 0
        let lastCheckOK = try container.decodeFlexibleInt(forKey: .lastCheckOK)
        isOnline = lastCheckOK.map { $0 > 0 } ?? true
        isFavorite = try container.decodeIfPresent(Bool.self, forKey: .isFavorite) ?? false
        isManual = try container.decodeIfPresent(Bool.self, forKey: .isManual) ?? false
    }

    public func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(uuid, forKey: .legacyUUID)
        try container.encode(name, forKey: .name)
        try container.encode(url, forKey: .url)
        try container.encode(resolvedURL, forKey: .legacyResolvedURL)
        try container.encode(homepage, forKey: .homepage)
        try container.encode(favicon, forKey: .favicon)
        try container.encode(country, forKey: .country)
        try container.encode(tags, forKey: .tags)
        try container.encode(codec, forKey: .codec)
        try container.encode(bitrate, forKey: .bitrate)
        try container.encode(votes, forKey: .votes)
        try container.encode(isFavorite, forKey: .isFavorite)
        try container.encode(isManual, forKey: .isManual)
    }
}

extension KeyedDecodingContainer {
    func decodeFlexibleInt(forKey key: Key) throws -> Int? {
        if let intValue = try? decodeIfPresent(Int.self, forKey: key) {
            return intValue
        }
        if let stringValue = try? decodeIfPresent(String.self, forKey: key) {
            return Int(stringValue)
        }
        return nil
    }
}
