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

import XCTest
@testable import suixinkan

@MainActor
/// 景区选择 ViewModel 测试，覆盖搜索、定位和切换持久化。
final class ScenicSelectionViewModelTests: XCTestCase {
    /// 测试当前景区会优先展示并标记选中。
    func testCurrentScenicMovesToFirstItem() {
        let context = AccountContext()
        context.replaceScopes(
            scenic: [
                BusinessScope(id: 1, name: "西湖景区", kind: .scenic),
                BusinessScope(id: 2, name: "东湖景区", kind: .scenic)
            ],
            stores: [],
            currentScenicId: 2
        )
        let viewModel = ScenicSelectionViewModel()

        viewModel.reload(from: context)

        XCTAssertEqual(viewModel.items.map(\.id), [2, 1])
        XCTAssertTrue(viewModel.items[0].isClosest)
    }

    /// 测试搜索会按景区名称和地址过滤。
    func testSearchFiltersByNameAndAddress() {
        let viewModel = ScenicSelectionViewModel()
        let context = AccountContext()
        context.replaceScopes(
            scenic: [
                BusinessScope(id: 1, name: "西湖景区", kind: .scenic, address: "杭州"),
                BusinessScope(id: 2, name: "东湖景区", kind: .scenic, address: "武汉")
            ],
            stores: []
        )
        viewModel.reload(from: context)

        viewModel.searchQuery = "武汉"

        XCTAssertEqual(viewModel.filteredItems.map(\.id), [2])
    }

    /// 测试定位成功后会计算距离并标记最近景区。
    func testLocationSuccessMarksClosestScenic() {
        let context = AccountContext()
        context.replaceScopes(
            scenic: [
                BusinessScope(id: 1, name: "远景区", kind: .scenic, address: "远处", latitude: 31.0, longitude: 121.0),
                BusinessScope(id: 2, name: "近景区", kind: .scenic, address: "附近", latitude: 30.0001, longitude: 120.0001)
            ],
            stores: []
        )
        let viewModel = ScenicSelectionViewModel()
        viewModel.reload(from: context)

        viewModel.applyCurrentLocation(latitude: 30.0, longitude: 120.0)

        XCTAssertEqual(viewModel.items.first(where: \.isClosest)?.id, 2)
        XCTAssertEqual(viewModel.currentLocationText, "附近")
        XCTAssertNotNil(viewModel.items.first(where: { $0.id == 2 })?.distanceMeters)
    }

    /// 测试定位失败时保留列表并展示提示。
    func testLocationFailureKeepsItemsAndWarning() {
        let context = AccountContext()
        context.replaceScopes(scenic: [BusinessScope(id: 1, name: "西湖景区", kind: .scenic, address: "杭州")], stores: [])
        let viewModel = ScenicSelectionViewModel()
        viewModel.reload(from: context)

        viewModel.applyLocationFailure("定位权限未开启")

        XCTAssertEqual(viewModel.items.map(\.id), [1])
        XCTAssertEqual(viewModel.locationWarning, "定位权限未开启")
    }

    /// 测试切换景区会联动门店并保存账号快照。
    func testSelectScenicUpdatesStoreAndPersistsSnapshot() {
        let suiteName = "ScenicSelectionViewModelTests.\(UUID().uuidString)"
        let defaults = UserDefaults(suiteName: suiteName)!
        defer { defaults.removePersistentDomain(forName: suiteName) }
        let snapshotStore = AccountSnapshotStore(defaults: defaults)
        let accountContext = AccountContext()
        let permissionContext = PermissionContext()
        accountContext.replaceScopes(
            scenic: [
                BusinessScope(id: 1, name: "西湖景区", kind: .scenic),
                BusinessScope(id: 2, name: "东湖景区", kind: .scenic)
            ],
            stores: [
                BusinessScope(id: 10, name: "西湖门店", kind: .store, parentScenicId: 1),
                BusinessScope(id: 20, name: "东湖门店", kind: .store, parentScenicId: 2)
            ],
            currentScenicId: 1,
            currentStoreId: 10
        )
        permissionContext.replaceRolePermissions([RolePermissionResponse(role: RoleInfo(id: 7, name: "运营"), scenic: [])])

        ScenicSelectionViewModel().select(
            scenicId: 2,
            accountContext: accountContext,
            permissionContext: permissionContext,
            snapshotStore: snapshotStore
        )

        XCTAssertEqual(accountContext.currentScenic?.id, 2)
        XCTAssertEqual(accountContext.currentStore?.id, 20)
        XCTAssertEqual(snapshotStore.load()?.currentScenicId, 2)
        XCTAssertEqual(snapshotStore.load()?.currentStoreId, 20)
        XCTAssertEqual(snapshotStore.load()?.currentRoleId, 7)
    }
}
