//
//  UITestLaunchConfiguration.swift
//  suixinkanUITests
//
//  Created by Codex on 2026/6/26.
//

import XCTest

/// UI Test 启动参数与环境变量，需与 App 侧 `AppUITestLaunchState` 保持同名。
enum UITestLaunchConfiguration {
    static let uiTestsArgument = "-suixinkan-ui-tests"
    static let resetArgument = "-suixinkan-ui-tests-reset-state"
    static let openMenuArgument = "-suixinkan-ui-tests-open-menu"
    static let openProfileArgument = "-suixinkan-ui-tests-open-profile"

    /// 生成 UI Test 启动参数；可用 openMenu / openProfile 直达目标页。
    static func launchArguments(
        resetState: Bool = false,
        openMenu: String? = nil,
        openProfile: String? = nil
    ) -> [String] {
        var arguments = [uiTestsArgument]
        if resetState {
            arguments.append(resetArgument)
        }
        if let openMenu, !openMenu.isEmpty {
            arguments.append(contentsOf: [openMenuArgument, openMenu])
        } else if let openProfile, !openProfile.isEmpty {
            arguments.append(contentsOf: [openProfileArgument, openProfile])
        }
        return arguments
    }

    /// 为 XCUIApplication 注入 UI Test 启动参数；仅在需要冷启动空白态时传入 resetState。
    static func apply(
        to app: XCUIApplication,
        resetState: Bool = false,
        openMenu: String? = nil,
        openProfile: String? = nil
    ) {
        app.launchArguments = launchArguments(
            resetState: resetState,
            openMenu: openMenu,
            openProfile: openProfile
        )
    }

    static let phoneEnvironmentKey = "SUI_TEST_PHONE"
    static let passwordEnvironmentKey = "SUI_TEST_PASSWORD"
    static let accountNameEnvironmentKey = "SUI_TEST_ACCOUNT_NAME"

    /// 从 Scheme / xcodebuild 环境变量或本地 plist 读取测试账号。
    static var credentials: UITestCredentials? {
        if let environmentCredentials = credentialsFromEnvironment() {
            return environmentCredentials
        }
        return credentialsFromLocalPlist()
    }

    /// 缺少测试账号时跳过需要真实登录的用例。
    static func requireCredentials(file: StaticString = #filePath, line: UInt = #line) throws -> UITestCredentials {
        guard let credentials else {
            throw XCTSkip(
                "缺少 UI Test 账号。请配置环境变量 \(phoneEnvironmentKey) / \(passwordEnvironmentKey)，或在本机创建 UITestCredentials.local.plist。"
            )
        }
        return credentials
    }

    /// 从 Scheme / xcodebuild 环境变量读取测试账号。
    private static func credentialsFromEnvironment() -> UITestCredentials? {
        let environment = ProcessInfo.processInfo.environment
        guard
            let phone = environment[phoneEnvironmentKey]?.trimmingCharacters(in: .whitespacesAndNewlines),
            !phone.isEmpty,
            let password = environment[passwordEnvironmentKey]?.trimmingCharacters(in: .whitespacesAndNewlines),
            !password.isEmpty
        else {
            return nil
        }

        let accountName = environment[accountNameEnvironmentKey]?
            .trimmingCharacters(in: .whitespacesAndNewlines)
        return UITestCredentials(
            phone: phone,
            password: password,
            accountName: accountName?.isEmpty == false ? accountName : nil
        )
    }

    /// 从 gitignore 的本地 plist 读取测试账号，便于本机开发配置。
    private static func credentialsFromLocalPlist() -> UITestCredentials? {
        let plistURL = localCredentialsURL
        guard
            FileManager.default.fileExists(atPath: plistURL.path),
            let dictionary = NSDictionary(contentsOf: plistURL) as? [String: String]
        else {
            return nil
        }

        guard
            let phone = dictionary[phoneEnvironmentKey]?.trimmingCharacters(in: .whitespacesAndNewlines),
            !phone.isEmpty,
            let password = dictionary[passwordEnvironmentKey]?.trimmingCharacters(in: .whitespacesAndNewlines),
            !password.isEmpty
        else {
            return nil
        }

        let accountName = dictionary[accountNameEnvironmentKey]?
            .trimmingCharacters(in: .whitespacesAndNewlines)
        return UITestCredentials(
            phone: phone,
            password: password,
            accountName: accountName?.isEmpty == false ? accountName : nil
        )
    }

    /// 本地测试账号 plist 路径。
    private static var localCredentialsURL: URL {
        URL(fileURLWithPath: #filePath)
            .deletingLastPathComponent()
            .deletingLastPathComponent()
            .appendingPathComponent("UITestCredentials.local.plist")
    }
}

/// UI Test 登录账号实体。
struct UITestCredentials: Equatable {
    let phone: String
    let password: String
    let accountName: String?
}
