import XCTest
@testable import TencentQianWebViewSDK

/// `SignResultParser` XCTest,与 Android `SignResultParserTest` 同一组用例。
final class SignResultParserTests: XCTestCase {

    // MARK: - 1. 标准签署成功

    func test_parses_standard_sign_success() {
        let url = "qianapp://callback/sign?flowId=abc-123&action=sign&result=success&from=tencent_ess"
        let r = SignResultParser.parse(url)

        XCTAssertEqual(r.rawUrl, url)
        XCTAssertEqual(r.customPath, "callback/sign")
        XCTAssertEqual(r.flowId, "abc-123")
        XCTAssertEqual(r.action, SignAction.sign)
        XCTAssertEqual(r.result, SignResultStatus.success)
        XCTAssertEqual(r.from, "tencent_ess")
        XCTAssertTrue(r.extras.isEmpty)
    }

    // MARK: - 2. 空字段保留为空字符串

    func test_preserves_empty_value_as_empty_string() {
        let r = SignResultParser.parse("qianapp://x?flowId=&action=&result=&from=")
        XCTAssertEqual(r.flowId, "")
        XCTAssertEqual(r.action, "")
        XCTAssertEqual(r.result, "")
        XCTAssertEqual(r.from, "")
    }

    // MARK: - 3. 未知 action 原样透出

    func test_preserves_unknown_action_value_verbatim() {
        let r = SignResultParser.parse("qianapp://x?action=futureBrandNewAction&result=mystery")
        XCTAssertEqual(r.action, "futureBrandNewAction")
        XCTAssertEqual(r.result, "mystery")
        XCTAssertNotEqual(r.action, SignAction.sign)
    }

    // MARK: - 4. 重复 key 取首个

    func test_keeps_first_value_when_query_key_duplicates() {
        let r = SignResultParser.parse("qianapp://x?flowId=first&flowId=second&action=sign")
        XCTAssertEqual(r.flowId, "first")
        XCTAssertEqual(r.action, SignAction.sign)
    }

    // MARK: - 5. 非法 URL → empty

    func test_returns_empty_for_nil_or_empty_or_wrong_scheme() {
        XCTAssertEqual(SignResultParser.parse(nil), .empty)
        XCTAssertEqual(SignResultParser.parse(""), .empty)
        XCTAssertEqual(SignResultParser.parse("https://example.com/x"), .empty)
        XCTAssertEqual(SignResultParser.parse("weixin://wap/pay"), .empty)
    }

    // MARK: - 6. extras 透传

    func test_transfers_unknown_query_keys_to_extras() {
        let url = "qianapp://done?flowId=f1&action=sign&result=success&customer_id=u-42&channel=ad-banner"
        let r = SignResultParser.parse(url)

        XCTAssertEqual(r.extras["customer_id"], "u-42")
        XCTAssertEqual(r.extras["channel"], "ad-banner")
        XCTAssertEqual(r.flowId, "f1")
        XCTAssertNil(r.extras["flowId"])
    }

    // MARK: - 7. errorCode / errorMsg 落 extras

    func test_keeps_errorCode_and_errorMsg_in_extras() {
        let url = "qianapp://x?action=sign&result=fail&errorCode=10086&errorMsg=user_canceled"
        let r = SignResultParser.parse(url)

        XCTAssertEqual(r.result, SignResultStatus.fail)
        XCTAssertEqual(r.extras["errorCode"], "10086")
        XCTAssertEqual(r.extras["errorMsg"], "user_canceled")
    }

    // MARK: - 8. 中文 percent-decode

    func test_decodes_utf8_percent_encoded_chinese() {
        // "签署成功" UTF-8 percent-encoded
        let url = "qianapp://x?action=sign&note=%E7%AD%BE%E7%BD%B2%E6%88%90%E5%8A%9F"
        let r = SignResultParser.parse(url)
        XCTAssertEqual(r.extras["note"], "签署成功")
    }

    // MARK: - 9. customPath = host + path

    func test_customPath_combines_host_and_path() {
        XCTAssertEqual(SignResultParser.parse("qianapp://callback/sign?flowId=1").customPath, "callback/sign")
        XCTAssertEqual(SignResultParser.parse("qianapp://result?flowId=1").customPath, "result")
        XCTAssertEqual(SignResultParser.parse("qianapp://done/").customPath, "done")
    }

    // MARK: - 10. 无 query

    func test_parses_url_without_query() {
        let r = SignResultParser.parse("qianapp://done")
        XCTAssertEqual(r.customPath, "done")
        XCTAssertEqual(r.flowId, "")
        XCTAssertTrue(r.extras.isEmpty)
    }

    // MARK: - 11. 等号 in value

    func test_preserves_equal_sign_inside_value() {
        let r = SignResultParser.parse("qianapp://x?token=abc==&action=sign")
        XCTAssertEqual(r.extras["token"], "abc==")
        XCTAssertEqual(r.action, SignAction.sign)
    }

    // MARK: - 12. 大小写 scheme

    func test_accepts_uppercase_scheme() {
        let r = SignResultParser.parse("QIANAPP://x?action=sign")
        XCTAssertEqual(r.action, SignAction.sign)
    }

    // MARK: - 13. 常量值校验

    func test_constants_match_protocol_wire_values() {
        XCTAssertEqual(SignAction.fill, "fill")
        XCTAssertEqual(SignAction.sign, "sign")
        XCTAssertEqual(SignAction.rejectFill, "reject_fill")
        XCTAssertEqual(SignAction.rejectSign, "reject_sign")
        XCTAssertEqual(SignAction.view, "view")

        XCTAssertEqual(SignResultStatus.success, "success")
        XCTAssertEqual(SignResultStatus.fail, "fail")
    }
}
