//
//  LiveAPITests.swift
//  suixinkanTests
//

import XCTest
@testable import suixinkan

@MainActor
/// 直播 API 测试。
final class LiveAPITests: XCTestCase {
    func testManualLiveListAndDetailBuildAndroidQueries() async throws {
        let session = MockURLSession(responses: [
            envelopeJSON(#"{"page":1,"page_size":10,"total":0,"total_pages":0,"items":[]}"#),
            envelopeJSON(#"{"id":7,"title":"直播"}"#),
        ])
        let api = LiveAPI(client: APIClient(environment: .testing, session: session))

        _ = try await api.liveList(scenicId: "12", page: 2, pageSize: 10)
        _ = try await api.liveDetail(liveId: 7)

        XCTAssertEqual(session.requests[0].httpMethod, "GET")
        XCTAssertEqual(session.requests[0].url?.path, "/api/app/manual-live/list")
        let listQuery = URLComponents(url: session.requests[0].url!, resolvingAgainstBaseURL: false)?.queryItems
        XCTAssertEqual(listQuery?.first { $0.name == "scenic_id" }?.value, "12")
        XCTAssertEqual(listQuery?.first { $0.name == "page" }?.value, "2")
        XCTAssertEqual(listQuery?.first { $0.name == "page_size" }?.value, "10")

        XCTAssertEqual(session.requests[1].httpMethod, "GET")
        XCTAssertEqual(session.requests[1].url?.path, "/api/app/manual-live/detail")
        let detailQuery = URLComponents(url: session.requests[1].url!, resolvingAgainstBaseURL: false)?.queryItems
        XCTAssertEqual(detailQuery?.first { $0.name == "live_id" }?.value, "7")
    }

    func testManualLiveControlBodies() async throws {
        let session = MockURLSession(responses: [envelopeJSON("{}"), envelopeJSON("{}"), envelopeJSON("{}"), envelopeJSON("{}")])
        let api = LiveAPI(client: APIClient(environment: .testing, session: session))

        try await api.createLive(scenicId: "3", title: "直播A", coverImg: "https://cdn/c.jpg")
        try await api.startLive(liveId: 8)
        try await api.finishLive(liveId: 8)
        try await api.setPushMode(liveId: 8, mode: 2)

        XCTAssertEqual(session.requests[0].url?.path, "/api/app/manual-live/create")
        let createBody = try JSONSerialization.jsonObject(with: XCTUnwrap(session.requests[0].httpBody)) as? [String: Any]
        XCTAssertEqual(createBody?["scenic_id"] as? String, "3")
        XCTAssertEqual(createBody?["title"] as? String, "直播A")
        XCTAssertEqual(createBody?["cover_img"] as? String, "https://cdn/c.jpg")

        XCTAssertEqual(session.requests[1].url?.path, "/api/app/manual-live/start")
        let startBody = try JSONSerialization.jsonObject(with: XCTUnwrap(session.requests[1].httpBody)) as? [String: Any]
        XCTAssertEqual(startBody?["live_id"] as? Int, 8)

        XCTAssertEqual(session.requests[2].url?.path, "/api/app/manual-live/finish")
        XCTAssertEqual(session.requests[3].url?.path, "/api/app/manual-live/set-push-mode")
        let modeBody = try JSONSerialization.jsonObject(with: XCTUnwrap(session.requests[3].httpBody)) as? [String: Any]
        XCTAssertEqual(modeBody?["live_id"] as? Int, 8)
        XCTAssertEqual(modeBody?["manual_push_mode"] as? Int, 2)
    }

    func testAlbumRequestsMatchAndroidPaths() async throws {
        let session = MockURLSession(responses: [
            envelopeJSON(#"{"items":[],"page":1,"page_size":10,"total":0,"total_pages":0}"#),
            envelopeJSON("{}"),
            envelopeJSON(#"{"id":4,"items":[]}"#),
            envelopeJSON("{}"),
        ])
        let api = LiveAPI(client: APIClient(environment: .testing, session: session))

        _ = try await api.albumList(scenicId: "9", startTime: "2026-07-01", endTime: "2026-07-08", page: 3, pageSize: 10)
        try await api.createAlbumFolder(scenicId: "9", name: "作品", items: [LiveAlbumFile(url: "https://cdn/a.jpg", type: 2, size: 10)])
        _ = try await api.albumFolderDetail(folderId: 4)
        try await api.deleteAlbumFile(folderId: 4, fileId: 11)

        XCTAssertEqual(session.requests[0].url?.path, "/api/app/view-album/folders")
        let query = URLComponents(url: session.requests[0].url!, resolvingAgainstBaseURL: false)?.queryItems
        XCTAssertEqual(query?.first { $0.name == "scenic_id" }?.value, "9")
        XCTAssertEqual(query?.first { $0.name == "start_time" }?.value, "2026-07-01")
        XCTAssertEqual(query?.first { $0.name == "end_time" }?.value, "2026-07-08")
        XCTAssertEqual(query?.first { $0.name == "page" }?.value, "3")
        XCTAssertEqual(query?.first { $0.name == "page_size" }?.value, "10")

        XCTAssertEqual(session.requests[1].url?.path, "/api/app/view-album/create-folder")
        let createBody = try JSONSerialization.jsonObject(with: XCTUnwrap(session.requests[1].httpBody)) as? [String: Any]
        XCTAssertEqual(createBody?["scenic_id"] as? String, "9")
        XCTAssertEqual(createBody?["name"] as? String, "作品")
        XCTAssertEqual((createBody?["items"] as? [[String: Any]])?.first?["url"] as? String, "https://cdn/a.jpg")

        XCTAssertEqual(session.requests[2].url?.path, "/api/app/view-album/folder-detail")
        XCTAssertEqual(session.requests[3].url?.path, "/api/app/view-album/delete-files")
        let deleteBody = try JSONSerialization.jsonObject(with: XCTUnwrap(session.requests[3].httpBody)) as? [String: Any]
        XCTAssertEqual(deleteBody?["folder_id"] as? Int, 4)
        XCTAssertEqual(deleteBody?["file_ids"] as? [Int], [11])
    }

    private func envelopeJSON(_ dataJSON: String) -> Data {
        """
        {"code":100000,"msg":"success","data":\(dataJSON)}
        """.data(using: .utf8)!
    }
}
