// ─────────────────────────────────────────────────────────────────────────────
// `TQSignResultParser` XCTest 单测。
// ─────────────────────────────────────────────────────────────────────────────

#import <XCTest/XCTest.h>
#import "TQSignResultParser.h"
#import "TQSignResult.h"
#import "TQSignAction.h"
#import "TQSignResultStatus.h"

@interface TQSignResultParserTests : XCTestCase
@end

@implementation TQSignResultParserTests

#pragma mark - 1. 标准签署成功

- (void)test_parses_standard_sign_success {
    NSString *url = @"qianapp://callback/sign?flowId=abc-123&action=sign&result=success&from=tencent_ess";
    TQSignResult *r = [TQSignResultParser parse:url];

    XCTAssertEqualObjects(r.rawUrl, url);
    XCTAssertEqualObjects(r.customPath, @"callback/sign");
    XCTAssertEqualObjects(r.flowId, @"abc-123");
    XCTAssertEqualObjects(r.action, TQSignActionSign);
    XCTAssertEqualObjects(r.result, TQSignResultStatusSuccess);
    XCTAssertEqualObjects(r.from, @"tencent_ess");
    XCTAssertEqual(r.extras.count, 0u);
}

#pragma mark - 2. 空字段保留为空字符串

- (void)test_preserves_empty_value_as_empty_string {
    TQSignResult *r = [TQSignResultParser parse:@"qianapp://x?flowId=&action=&result=&from="];
    XCTAssertEqualObjects(r.flowId, @"");
    XCTAssertEqualObjects(r.action, @"");
    XCTAssertEqualObjects(r.result, @"");
    XCTAssertEqualObjects(r.from, @"");
}

#pragma mark - 3. 未知 action 原样透出

- (void)test_preserves_unknown_action_value_verbatim {
    TQSignResult *r = [TQSignResultParser parse:@"qianapp://x?action=futureBrandNewAction&result=mystery"];
    XCTAssertEqualObjects(r.action, @"futureBrandNewAction");
    XCTAssertEqualObjects(r.result, @"mystery");
    XCTAssertNotEqualObjects(r.action, TQSignActionSign);
}

#pragma mark - 4. 重复 key 取首个

- (void)test_keeps_first_value_when_query_key_duplicates {
    TQSignResult *r = [TQSignResultParser parse:@"qianapp://x?flowId=first&flowId=second&action=sign"];
    XCTAssertEqualObjects(r.flowId, @"first");
    XCTAssertEqualObjects(r.action, TQSignActionSign);
}

#pragma mark - 5. 非法 URL → empty

- (void)test_returns_empty_for_nil_or_empty_or_wrong_scheme {
    XCTAssertEqualObjects([TQSignResultParser parse:nil],                       [TQSignResult empty]);
    XCTAssertEqualObjects([TQSignResultParser parse:@""],                       [TQSignResult empty]);
    XCTAssertEqualObjects([TQSignResultParser parse:@"https://example.com/x"], [TQSignResult empty]);
    XCTAssertEqualObjects([TQSignResultParser parse:@"weixin://wap/pay"],      [TQSignResult empty]);
}

#pragma mark - 6. extras 透传

- (void)test_transfers_unknown_query_keys_to_extras {
    NSString *url = @"qianapp://done?flowId=f1&action=sign&result=success&customer_id=u-42&channel=ad-banner";
    TQSignResult *r = [TQSignResultParser parse:url];

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

#pragma mark - 7. errorCode / errorMsg 落 extras

- (void)test_keeps_errorCode_and_errorMsg_in_extras {
    NSString *url = @"qianapp://x?action=sign&result=fail&errorCode=10086&errorMsg=user_canceled";
    TQSignResult *r = [TQSignResultParser parse:url];

    XCTAssertEqualObjects(r.result, TQSignResultStatusFail);
    XCTAssertEqualObjects(r.extras[@"errorCode"], @"10086");
    XCTAssertEqualObjects(r.extras[@"errorMsg"],  @"user_canceled");
}

#pragma mark - 8. 中文 percent-decode

- (void)test_decodes_utf8_percent_encoded_chinese {
    // "签署成功" UTF-8 percent-encoded
    NSString *url = @"qianapp://x?action=sign&note=%E7%AD%BE%E7%BD%B2%E6%88%90%E5%8A%9F";
    TQSignResult *r = [TQSignResultParser parse:url];
    XCTAssertEqualObjects(r.extras[@"note"], @"签署成功");
}

#pragma mark - 9. customPath = host + path

- (void)test_customPath_combines_host_and_path {
    XCTAssertEqualObjects([TQSignResultParser parse:@"qianapp://callback/sign?flowId=1"].customPath, @"callback/sign");
    XCTAssertEqualObjects([TQSignResultParser parse:@"qianapp://result?flowId=1"].customPath,        @"result");
    XCTAssertEqualObjects([TQSignResultParser parse:@"qianapp://done/"].customPath,                  @"done");
}

#pragma mark - 10. 无 query

- (void)test_parses_url_without_query {
    TQSignResult *r = [TQSignResultParser parse:@"qianapp://done"];
    XCTAssertEqualObjects(r.customPath, @"done");
    XCTAssertEqualObjects(r.flowId, @"");
    XCTAssertEqual(r.extras.count, 0u);
}

#pragma mark - 11. 等号 in value

- (void)test_preserves_equal_sign_inside_value {
    TQSignResult *r = [TQSignResultParser parse:@"qianapp://x?token=abc==&action=sign"];
    XCTAssertEqualObjects(r.extras[@"token"], @"abc==");
    XCTAssertEqualObjects(r.action, TQSignActionSign);
}

#pragma mark - 12. 大小写 scheme

- (void)test_accepts_uppercase_scheme {
    TQSignResult *r = [TQSignResultParser parse:@"QIANAPP://x?action=sign"];
    XCTAssertEqualObjects(r.action, TQSignActionSign);
}

#pragma mark - 13. 常量值校验

- (void)test_constants_match_protocol_wire_values {
    XCTAssertEqualObjects(TQSignActionFill,       @"fill");
    XCTAssertEqualObjects(TQSignActionSign,       @"sign");
    XCTAssertEqualObjects(TQSignActionRejectFill, @"reject_fill");
    XCTAssertEqualObjects(TQSignActionRejectSign, @"reject_sign");
    XCTAssertEqualObjects(TQSignActionView,       @"view");

    XCTAssertEqualObjects(TQSignResultStatusSuccess, @"success");
    XCTAssertEqualObjects(TQSignResultStatusFail,    @"fail");
}

@end
