//
//  MainTabBadgeViewModelTests.swift
//  suixinkanTests
//
//  Created by Codex on 2026/6/23.
//

import XCTest
@testable import suixinkan

@MainActor
/// 主 Tab 角标测试，覆盖待核销数量加载、封顶和失败清理。
final class MainTabBadgeViewModelTests: XCTestCase {
    /// 测试无景区时清空角标且不请求接口。
    func testMissingScenicClearsBadgeWithoutRequestingAPI() async {
        let api = MockMainTabOrderService()
        let viewModel = MainTabBadgeViewModel()

        await viewModel.refreshPendingWriteOffCount(api: api, scenicId: nil, storeId: 66)

        XCTAssertNil(viewModel.pendingWriteOffCount)
        XCTAssertTrue(api.writeOffListCalls.isEmpty)
    }

    /// 测试接口成功时展示待核销总数。
    func testSuccessfulRefreshStoresPendingWriteOffCount() async {
        let api = MockMainTabOrderService()
        api.writeOffResponse = ListPayload<WriteOffOrderItem>(total: 8, list: [])
        let viewModel = MainTabBadgeViewModel()

        await viewModel.refreshPendingWriteOffCount(api: api, scenicId: 88, storeId: 66)

        XCTAssertEqual(viewModel.pendingWriteOffCount, 8)
        XCTAssertEqual(api.writeOffListCalls, [.init(scenicId: 88, storeId: 66, page: 1, pageSize: 1)])
    }

    /// 测试待核销数量超过 99 时角标封顶。
    func testSuccessfulRefreshCapsPendingWriteOffCountAtNinetyNine() async {
        let api = MockMainTabOrderService()
        api.writeOffResponse = ListPayload<WriteOffOrderItem>(total: 120, list: [])
        let viewModel = MainTabBadgeViewModel()

        await viewModel.refreshPendingWriteOffCount(api: api, scenicId: 88, storeId: nil)

        XCTAssertEqual(viewModel.pendingWriteOffCount, 99)
    }

    /// 测试接口失败时清空角标。
    func testRefreshFailureClearsBadge() async {
        let api = MockMainTabOrderService()
        api.writeOffError = APIError.httpStatus(500, "server error")
        let viewModel = MainTabBadgeViewModel()

        await viewModel.refreshPendingWriteOffCount(api: api, scenicId: 88, storeId: 66)

        XCTAssertNil(viewModel.pendingWriteOffCount)
        XCTAssertEqual(api.writeOffListCalls.count, 1)
    }
}

@MainActor
/// 主 Tab 角标测试用订单服务，只实现角标依赖的核销列表记录。
private final class MockMainTabOrderService: OrderServing {
    struct WriteOffListCall: Equatable {
        let scenicId: Int
        let storeId: Int?
        let page: Int
        let pageSize: Int
    }

    var writeOffResponse = ListPayload<WriteOffOrderItem>(total: 0, list: [])
    var writeOffError: Error?
    private(set) var writeOffListCalls: [WriteOffListCall] = []

    /// 返回空订单管理列表，角标测试不会使用该方法。
    func orderList(
        scenicId: Int,
        page: Int,
        pageSize: Int,
        orderStatus: Int?,
        userPhone: String?,
        startTime: String?,
        endTime: String?,
        isRefined: Int?,
        isScenicAdmin: Bool
    ) async throws -> ListPayload<OrderEntity> {
        ListPayload(total: 0, list: [])
    }

    /// 记录核销列表请求并返回预设响应。
    func writeOffList(scenicId: Int, storeId: Int?, page: Int, pageSize: Int) async throws -> ListPayload<WriteOffOrderItem> {
        writeOffListCalls.append(.init(scenicId: scenicId, storeId: storeId, page: page, pageSize: pageSize))
        if let writeOffError {
            throw writeOffError
        }
        return writeOffResponse
    }

    /// 角标测试不会触发核销操作。
    func writeOff(orderNumber: String) async throws {}

    /// 角标测试不会请求订单详情。
    func storeOrderDetail(storeId: Int, orderNumber: String) async throws -> StoreOrderDetailResponse {
        try TestFixture.payload(StoreOrderDetailResponse.self, named: "store_order_detail_success")
    }
}
