//
//  TravelAlbumAPITests.swift
//  suixinkanTests
//

import XCTest
@testable import suixinkan

@MainActor
/// 旅拍相册 API 测试。
final class TravelAlbumAPITests: XCTestCase {
    func testListBuildsPathAndQuery() async throws {
        let data = envelopeJSON(#"{"total":1,"list":[]}"#)
        let session = MockURLSession(responses: [data])
        let api = TravelAlbumAPI(client: APIClient(environment: .testing, session: session))

        _ = try await api.list(page: 2, pageSize: 30)

        let request = try XCTUnwrap(session.requests.first)
        XCTAssertEqual(request.url?.path, "/api/yf-handset-app/photog/travel-album/list")
        let query = try XCTUnwrap(URLComponents(url: try XCTUnwrap(request.url), resolvingAgainstBaseURL: false)?.queryItems)
        XCTAssertEqual(query.first { $0.name == "page" }?.value, "2")
        XCTAssertEqual(query.first { $0.name == "page_size" }?.value, "30")
    }

    func testCreateEncodesBody() async throws {
        let data = envelopeJSON(#"{"id":8}"#)
        let session = MockURLSession(responses: [data])
        let api = TravelAlbumAPI(client: APIClient(environment: .testing, session: session))

        _ = try await api.create(
            TravelAlbumCreateRequest(
                name: "2026-07-07-001",
                type: 1,
                orderNumber: nil,
                materialNum: 2,
                materialPrice: 10.5,
                materialPackagePrice: 88,
                photoPrice: 0
            )
        )

        let request = try XCTUnwrap(session.requests.first)
        XCTAssertEqual(request.httpMethod, "POST")
        XCTAssertEqual(request.url?.path, "/api/yf-handset-app/photog/travel-album/create")
        let body = try JSONSerialization.jsonObject(with: try XCTUnwrap(request.httpBody)) as? [String: Any]
        XCTAssertEqual(body?["name"] as? String, "2026-07-07-001")
        XCTAssertEqual(body?["type"] as? Int, 1)
        XCTAssertEqual(body?["material_num"] as? Int, 2)
        XCTAssertEqual(body?["material_price"] as? Double, 10.5)
    }

    func testMaterialListAndDeleteAndMpCode() async throws {
        let materialList = envelopeJSON(#"{"total":0,"list":[]}"#)
        let empty = envelopeJSON("{}")
        let code = envelopeJSON(#"{"mp_code_oss_url":"https://cdn/qr.png"}"#)
        let session = MockURLSession(responses: [materialList, empty, code])
        let api = TravelAlbumAPI(client: APIClient(environment: .testing, session: session))

        _ = try await api.materialList(userEquityTravelId: 3, page: 1, pageSize: 30, orderBy: 4, isPurchased: 1)
        try await api.deleteAlbum(id: 3)
        let response = try await api.mpCode(id: 3)

        XCTAssertEqual(response.mpCodeOssUrl, "https://cdn/qr.png")
        XCTAssertEqual(session.requests[0].url?.path, "/api/yf-handset-app/photog/travel-album/material-list")
        let query = URLComponents(url: session.requests[0].url!, resolvingAgainstBaseURL: false)?.queryItems
        XCTAssertEqual(query?.first { $0.name == "user_equity_travel_id" }?.value, "3")
        XCTAssertEqual(query?.first { $0.name == "order_by" }?.value, "4")
        XCTAssertEqual(query?.first { $0.name == "is_purchased" }?.value, "1")
        XCTAssertEqual(session.requests[1].url?.path, "/api/yf-handset-app/photog/travel-album/delete")
        let body = try JSONSerialization.jsonObject(with: session.requests[1].httpBody!) as? [String: Any]
        XCTAssertEqual(body?["id"] as? Int, 3)
        XCTAssertEqual(session.requests[2].url?.path, "/api/yf-handset-app/photog/travel-album/mp-code")
    }

    func testUploadMaterialBuildsPathAndBody() async throws {
        let material = envelopeJSON(#"{"id":6,"user_equity_travel_id":3,"status":1,"order_number":"","user_id":9,"file_name":"A.JPG","file_type":1,"file_url":"https://cdn/a.jpg","file_size":1024,"cover_url":"","is_purchased":false,"created_at":"2026-07-08 10:00:00","updated_at":"2026-07-08 10:00:00"}"#)
        let session = MockURLSession(responses: [material])
        let api = TravelAlbumAPI(client: APIClient(environment: .testing, session: session))

        let response = try await api.uploadMaterial(
            TravelAlbumUploadMaterialRequest(
                userEquityTravelId: 3,
                fileName: "A.JPG",
                fileUrl: "https://cdn/a.jpg",
                clientPhotoId: "2a1d96b1-c0cc-489f-9f42-419ff1439a62"
            )
        )

        XCTAssertEqual(response.id, 6)
        let request = try XCTUnwrap(session.requests.first)
        XCTAssertEqual(request.httpMethod, "POST")
        XCTAssertEqual(request.url?.path, "/api/yf-handset-app/photog/travel-album/upload-material")
        let body = try JSONSerialization.jsonObject(with: try XCTUnwrap(request.httpBody)) as? [String: Any]
        XCTAssertEqual(body?["user_equity_travel_id"] as? Int, 3)
        XCTAssertEqual(body?["file_name"] as? String, "A.JPG")
        XCTAssertEqual(body?["file_url"] as? String, "https://cdn/a.jpg")
        XCTAssertEqual(body?["client_photo_id"] as? String, "2a1d96b1-c0cc-489f-9f42-419ff1439a62")
    }

    func testMaterialClientPhotoIdsBuildsPathQueryAndDecodesResponse() async throws {
        let data = envelopeJSON(#"{"client_photo_ids":["one","two"]}"#)
        let session = MockURLSession(responses: [data])
        let api = TravelAlbumAPI(client: APIClient(environment: .testing, session: session))

        let response = try await api.materialClientPhotoIds(userEquityTravelId: 3)

        XCTAssertEqual(response.clientPhotoIds, ["one", "two"])
        let request = try XCTUnwrap(session.requests.first)
        XCTAssertEqual(request.httpMethod, "GET")
        XCTAssertEqual(request.url?.path, "/api/yf-handset-app/photog/travel-album/material-client-photo-ids")
        let query = URLComponents(url: request.url!, resolvingAgainstBaseURL: false)?.queryItems
        XCTAssertEqual(query?.first { $0.name == "user_equity_travel_id" }?.value, "3")
    }

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