//
//  LiveModels.swift
//  suixinkan
//

import Foundation

/// 直播状态，对齐 Android `AliveEntity.status`。
enum LiveStatus: Int, Sendable, Equatable {
    case pending = 1
    case living = 2
    case paused = 3
    case finished = 4
    case unknown = 0

    /// 是否允许开始、暂停或结束。
    var isOperable: Bool { self != .finished }
}

/// 直播推流模式，对齐 Android `manualPushMode`。
enum LivePushMode: Int, CaseIterable, Sendable, Equatable {
    case clarityFirst = 1
    case smoothFirst = 2

    /// 展示文案。
    var title: String {
        switch self {
        case .clarityFirst: "清晰度优先"
        case .smoothFirst: "流畅度优先"
        }
    }
}

/// 直播列表与详情实体，对齐 Android `AliveEntity`。
struct LiveItem: Decodable, Sendable, Equatable, Hashable, Identifiable {
    let id: Int
    let title: String
    let coverImg: String
    let pushUrl: String
    let startTime: Int64
    let endTime: Int64
    let duration: Int64
    let status: Int
    let statusLabel: String
    let manualPushMode: Int
    let manualPushState: Int
    let viewsCount: Int

    enum CodingKeys: String, CodingKey {
        case id
        case title
        case coverImg = "cover_img"
        case pushUrl = "push_url"
        case startTime = "start_time"
        case endTime = "end_time"
        case duration
        case status
        case statusLabel = "status_label"
        case manualPushMode = "manual_push_mode"
        case manualPushState = "manual_push_state"
        case legacyManualPushMode = "manaul_push_mode"
        case legacyManualPushState = "manaul_push_state"
        case viewsCount = "views_count"
    }

    init(
        id: Int = 0,
        title: String = "",
        coverImg: String = "",
        pushUrl: String = "",
        startTime: Int64 = 0,
        endTime: Int64 = 0,
        duration: Int64 = 0,
        status: Int = 0,
        statusLabel: String = "",
        manualPushMode: Int = 1,
        manualPushState: Int = 0,
        viewsCount: Int = 0
    ) {
        self.id = id
        self.title = title
        self.coverImg = coverImg
        self.pushUrl = pushUrl
        self.startTime = startTime
        self.endTime = endTime
        self.duration = duration
        self.status = status
        self.statusLabel = statusLabel
        self.manualPushMode = manualPushMode
        self.manualPushState = manualPushState
        self.viewsCount = viewsCount
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        id = try container.decodeLossyInt(forKey: .id) ?? 0
        title = try container.decodeLossyString(forKey: .title)
        coverImg = try container.decodeLossyString(forKey: .coverImg).unescapedSlashes
        pushUrl = try container.decodeLossyString(forKey: .pushUrl).unescapedSlashes
        startTime = try container.decodeLossyInt64(forKey: .startTime) ?? 0
        endTime = try container.decodeLossyInt64(forKey: .endTime) ?? 0
        duration = try container.decodeLossyInt64(forKey: .duration) ?? 0
        status = try container.decodeLossyInt(forKey: .status) ?? 0
        statusLabel = try container.decodeLossyString(forKey: .statusLabel)
        manualPushMode = try container.decodeLossyInt(forKey: .manualPushMode)
            ?? container.decodeLossyInt(forKey: .legacyManualPushMode)
            ?? 1
        manualPushState = try container.decodeLossyInt(forKey: .manualPushState)
            ?? container.decodeLossyInt(forKey: .legacyManualPushState)
            ?? 0
        viewsCount = try container.decodeLossyInt(forKey: .viewsCount) ?? 0
    }

    /// 类型化直播状态。
    var liveStatus: LiveStatus { LiveStatus(rawValue: status) ?? .unknown }

    /// 标题兜底。
    var displayTitle: String { title.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty ? "暂无标题" : title }

    /// 当前操作按钮标题。
    var controlTitle: String { liveStatus == .living ? "暂停" : "开始" }
}

/// 直播分页响应，对齐 Android `ItemListResponse<AliveEntity>`。
struct LiveListResponse: Decodable, Sendable, Equatable {
    let page: Int
    let pageSize: Int
    let total: Int
    let totalPages: Int
    let items: [LiveItem]

    enum CodingKeys: String, CodingKey {
        case page
        case pageSize = "page_size"
        case total
        case totalPages = "total_pages"
        case items
    }

    init(page: Int = 1, pageSize: Int = 10, total: Int = 0, totalPages: Int = 0, items: [LiveItem] = []) {
        self.page = page
        self.pageSize = pageSize
        self.total = total
        self.totalPages = totalPages
        self.items = items
    }
}

/// 新增直播请求。
struct LiveCreateRequest: Encodable, Sendable, Equatable {
    let scenicId: String
    let title: String
    let coverImg: String

    enum CodingKeys: String, CodingKey {
        case scenicId = "scenic_id"
        case title
        case coverImg = "cover_img"
    }
}

/// 直播控制请求。
struct LiveControlRequest: Encodable, Sendable, Equatable {
    let liveId: Int

    enum CodingKeys: String, CodingKey {
        case liveId = "live_id"
    }
}

/// 直播推流模式请求。
struct LivePushModeRequest: Encodable, Sendable, Equatable {
    let liveId: Int
    let manualPushMode: Int

    enum CodingKeys: String, CodingKey {
        case liveId = "live_id"
        case manualPushMode = "manual_push_mode"
    }
}

/// 直播相册文件实体，对齐 Android `AliveAlbumFileEntity`。
struct LiveAlbumFile: Codable, Sendable, Equatable, Hashable, Identifiable {
    let url: String
    let type: Int
    let size: Int64
    let coverImg: String?
    let id: Int

    enum CodingKeys: String, CodingKey {
        case url
        case type
        case size
        case coverImg = "cover_img"
        case id
    }

    init(url: String, type: Int, size: Int64, coverImg: String? = nil, id: Int = 0) {
        self.url = url.unescapedSlashes
        self.type = type
        self.size = size
        self.coverImg = coverImg?.unescapedSlashes
        self.id = id
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        url = try container.decodeLossyString(forKey: .url).unescapedSlashes
        type = try container.decodeLossyInt(forKey: .type) ?? 2
        size = try container.decodeLossyInt64(forKey: .size) ?? 0
        let cover = try container.decodeIfPresent(String.self, forKey: .coverImg)
        coverImg = cover?.unescapedSlashes
        id = try container.decodeLossyInt(forKey: .id) ?? 0
    }
}

/// 直播相册文件夹实体，对齐 Android `AliveAlbumFolderEntity`。
struct LiveAlbumFolder: Decodable, Sendable, Equatable, Hashable, Identifiable {
    let id: Int
    let albumId: Int
    let name: String
    let creator: String
    let items: [LiveAlbumFile]

    enum CodingKeys: String, CodingKey {
        case id
        case albumId = "album_id"
        case name
        case creator
        case items
    }

    init(id: Int = 0, albumId: Int = 0, name: String = "", creator: String = "", items: [LiveAlbumFile] = []) {
        self.id = id
        self.albumId = albumId
        self.name = name
        self.creator = creator
        self.items = items
    }

    /// 标题兜底。
    var displayName: String { name.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty ? "暂无标题" : name }
}

/// 直播相册列表响应。
struct LiveAlbumFolderListResponse: Decodable, Sendable, Equatable {
    let items: [LiveAlbumFolder]
    let page: Int
    let pageSize: Int
    let total: Int
    let totalPages: Int

    enum CodingKeys: String, CodingKey {
        case items
        case page
        case pageSize = "page_size"
        case total
        case totalPages = "total_pages"
    }

    init(items: [LiveAlbumFolder] = [], page: Int = 1, pageSize: Int = 10, total: Int = 0, totalPages: Int = 0) {
        self.items = items
        self.page = page
        self.pageSize = pageSize
        self.total = total
        self.totalPages = totalPages
    }
}

/// 创建直播相册文件夹请求。
struct LiveAlbumFolderCreateRequest: Encodable, Sendable, Equatable {
    let scenicId: String
    let name: String
    let items: [LiveAlbumFile]

    enum CodingKeys: String, CodingKey {
        case scenicId = "scenic_id"
        case name
        case items
    }
}

/// 删除直播相册文件夹请求。
struct LiveAlbumFolderDeleteRequest: Encodable, Sendable, Equatable {
    let folderId: Int

    enum CodingKeys: String, CodingKey {
        case folderId = "folder_id"
    }
}

/// 删除直播相册文件请求。
struct LiveAlbumFileDeleteRequest: Encodable, Sendable, Equatable {
    let folderId: Int
    let fileIds: [Int]

    enum CodingKeys: String, CodingKey {
        case folderId = "folder_id"
        case fileIds = "file_ids"
    }
}

/// 本地待上传直播相册素材。
struct LivePickedMedia: Sendable, Equatable {
    let data: Data
    let fileName: String
    let size: Int64
    let width: Int
    let height: Int
}

private extension KeyedDecodingContainer {
    func decodeLossyString(forKey key: Key) throws -> String {
        if let value = try? decodeIfPresent(String.self, forKey: key) {
            return value
        }
        if let value = try? decodeIfPresent(Int.self, forKey: key) {
            return String(value)
        }
        if let value = try? decodeIfPresent(Int64.self, forKey: key) {
            return String(value)
        }
        if let value = try? decodeIfPresent(Double.self, forKey: key) {
            return String(value)
        }
        return ""
    }

    func decodeLossyInt(forKey key: Key) throws -> Int? {
        if let value = try? decodeIfPresent(Int.self, forKey: key) {
            return value
        }
        if let value = try? decodeIfPresent(Int64.self, forKey: key) {
            return Int(value)
        }
        if let value = try? decodeIfPresent(String.self, forKey: key) {
            let text = value.trimmingCharacters(in: .whitespacesAndNewlines)
            if let intValue = Int(text) { return intValue }
            if let doubleValue = Double(text) { return Int(doubleValue) }
        }
        if let value = try? decodeIfPresent(Double.self, forKey: key) {
            return Int(value)
        }
        return nil
    }

    func decodeLossyInt64(forKey key: Key) throws -> Int64? {
        if let value = try? decodeIfPresent(Int64.self, forKey: key) {
            return value
        }
        if let value = try? decodeIfPresent(Int.self, forKey: key) {
            return Int64(value)
        }
        if let value = try? decodeIfPresent(String.self, forKey: key) {
            let text = value.trimmingCharacters(in: .whitespacesAndNewlines)
            if let intValue = Int64(text) { return intValue }
            if let doubleValue = Double(text) { return Int64(doubleValue) }
        }
        if let value = try? decodeIfPresent(Double.self, forKey: key) {
            return Int64(value)
        }
        return nil
    }
}

private extension String {
    var unescapedSlashes: String {
        replacingOccurrences(of: "\\/", with: "/")
    }
}
