//
//  ScenicQueueAPI.swift
//  suixinkan
//
//  Created by Codex on 2026/6/25.
//

import Foundation
import Combine

/// 排队管理服务协议，定义列表、动作、设置、二维码和实时 token 能力。
@MainActor
protocol ScenicQueueServing: AnyObject {
    func scenicQueueStats(scenicId: Int, scenicSpotId: Int) async throws -> ScenicQueueStatsData
    func scenicQueueHome(scenicId: Int, scenicSpotId: Int, type: Int, page: Int, pageSize: Int) async throws -> ScenicQueueHomeData
    func socketToken() async throws -> SocketTokenResponse
    func scenicQueueCall(id: Int64) async throws -> ScenicQueueCallData
    func scenicQueuePass(id: Int64) async throws -> ScenicQueuePassData
    func scenicQueueFinish(id: Int64) async throws -> ScenicQueueFinishData
    func scenicQueueRequeueInsertBefore(recordId: Int64, operatorId: Int) async throws
    func scenicQueueUserMark(_ request: ScenicQueueUserMarkRequest) async throws
    func scenicQueueSetting(scenicId: Int, scenicSpotId: Int?) async throws -> ScenicQueueSettingData
    func scenicQueueSaveSetting(_ request: ScenicQueueSaveSettingRequest) async throws
    func scenicQueueShootQueueQRCode(scenicId: Int, scenicSpotId: Int) async throws -> ScenicQueueShootQueueQRCodeData
    func scenicQueueSettingChangeLog(scenicId: Int, scenicSpotId: Int?, page: Int, pageSize: Int) async throws -> ScenicQueueSettingChangeLogData
}

@MainActor
/// 排队管理 API，封装 `/api/app/scenic-queue` 下的排队接口。
final class ScenicQueueAPI {
    private let client: APIClient

    /// 初始化排队管理 API，并注入共享网络客户端。
    init(client: APIClient) {
        self.client = client
    }

    /// 获取当前打卡点排队统计。
    func scenicQueueStats(scenicId: Int, scenicSpotId: Int) async throws -> ScenicQueueStatsData {
        do {
            return try await client.send(
                APIRequest(
                    method: .get,
                    path: "/api/app/scenic-queue/queue-stats",
                    queryItems: [
                        URLQueryItem(name: "scenic_id", value: String(scenicId)),
                        URLQueryItem(name: "scenic_spot_id", value: String(scenicSpotId))
                    ]
                )
            )
        } catch APIError.emptyData {
            return ScenicQueueStatsData()
        }
    }

    /// 获取当前打卡点排队列表。
    func scenicQueueHome(
        scenicId: Int,
        scenicSpotId: Int,
        type: Int,
        page: Int = 1,
        pageSize: Int = 20
    ) async throws -> ScenicQueueHomeData {
        do {
            return try await client.send(
                APIRequest(
                    method: .get,
                    path: "/api/app/scenic-queue/home",
                    queryItems: [
                        URLQueryItem(name: "scenic_id", value: String(scenicId)),
                        URLQueryItem(name: "scenic_spot_id", value: String(scenicSpotId)),
                        URLQueryItem(name: "type", value: String(type)),
                        URLQueryItem(name: "page", value: String(max(page, 1))),
                        URLQueryItem(name: "page_size", value: String(max(pageSize, 1)))
                    ]
                )
            )
        } catch APIError.emptyData {
            return ScenicQueueHomeData()
        }
    }

    /// 获取 WebSocket 订阅 token。
    func socketToken() async throws -> SocketTokenResponse {
        try await client.send(APIRequest(method: .get, path: "/api/app/socket-token"))
    }

    /// 叫号。
    func scenicQueueCall(id: Int64) async throws -> ScenicQueueCallData {
        do {
            return try await client.send(
                APIRequest(method: .post, path: "/api/app/scenic-queue/call", body: ScenicQueueActionRequest(id: id))
            )
        } catch APIError.emptyData {
            return ScenicQueueCallData(id: id)
        }
    }

    /// 标记过号。
    func scenicQueuePass(id: Int64) async throws -> ScenicQueuePassData {
        do {
            return try await client.send(
                APIRequest(method: .post, path: "/api/app/scenic-queue/pass", body: ScenicQueueActionRequest(id: id))
            )
        } catch APIError.emptyData {
            return ScenicQueuePassData(id: id)
        }
    }

    /// 标记完成。
    func scenicQueueFinish(id: Int64) async throws -> ScenicQueueFinishData {
        do {
            return try await client.send(
                APIRequest(method: .post, path: "/api/app/scenic-queue/finish", body: ScenicQueueActionRequest(id: id))
            )
        } catch APIError.emptyData {
            return ScenicQueueFinishData(id: id)
        }
    }

    /// 将过号记录重新插回当前排队队列。
    func scenicQueueRequeueInsertBefore(recordId: Int64, operatorId: Int) async throws {
        let _: EmptyPayload = try await client.send(
            APIRequest(
                method: .post,
                path: "/api/app/scenic-queue/requeue-insert-before",
                body: ScenicQueueRequeueInsertBeforeRequest(recordId: recordId, operatorId: operatorId)
            )
        )
    }

    /// 标记用户身份/限制排队。
    func scenicQueueUserMark(_ request: ScenicQueueUserMarkRequest) async throws {
        let _: EmptyPayload = try await client.send(
            APIRequest(method: .post, path: "/api/app/scenic-queue/user-mark", body: request)
        )
    }

    /// 获取排队设置。
    func scenicQueueSetting(scenicId: Int, scenicSpotId: Int?) async throws -> ScenicQueueSettingData {
        var query = [URLQueryItem(name: "scenic_id", value: String(scenicId))]
        if let scenicSpotId {
            query.append(URLQueryItem(name: "scenic_spot_id", value: String(scenicSpotId)))
        }
        do {
            return try await client.send(
                APIRequest(method: .get, path: "/api/app/scenic-queue/setting", queryItems: query)
            )
        } catch APIError.emptyData {
            return ScenicQueueSettingData()
        }
    }

    /// 保存排队设置。
    func scenicQueueSaveSetting(_ request: ScenicQueueSaveSettingRequest) async throws {
        let _: EmptyPayload = try await client.send(
            APIRequest(method: .post, path: "/api/app/scenic-queue/save-setting", body: request)
        )
    }

    /// 获取取号二维码。
    func scenicQueueShootQueueQRCode(scenicId: Int, scenicSpotId: Int) async throws -> ScenicQueueShootQueueQRCodeData {
        try await client.send(
            APIRequest(
                method: .get,
                path: "/api/app/scenic-queue/shoot-queue-qrcode",
                queryItems: [
                    URLQueryItem(name: "scenic_id", value: String(scenicId)),
                    URLQueryItem(name: "scenic_spot_id", value: String(scenicSpotId))
                ]
            )
        )
    }

    /// 获取排队设置变更日志。
    func scenicQueueSettingChangeLog(
        scenicId: Int,
        scenicSpotId: Int?,
        page: Int = 1,
        pageSize: Int = 20
    ) async throws -> ScenicQueueSettingChangeLogData {
        var query = [
            URLQueryItem(name: "scenic_id", value: String(scenicId)),
            URLQueryItem(name: "page", value: String(max(page, 1))),
            URLQueryItem(name: "page_size", value: String(max(pageSize, 1)))
        ]
        if let scenicSpotId {
            query.append(URLQueryItem(name: "scenic_spot_id", value: String(scenicSpotId)))
        }
        do {
            return try await client.send(
                APIRequest(method: .get, path: "/api/app/scenic-queue/setting-change-log", queryItems: query)
            )
        } catch APIError.emptyData {
            return ScenicQueueSettingChangeLogData()
        }
    }
}

extension ScenicQueueAPI: ScenicQueueServing {}
