# Windsurf 注册自动化配置
site:
  name: Windsurf
  url: https://windsurf.com/refer?referral_code=55424ec434

# 工作流定义
workflow:
  # ==================== 步骤 0: 处理邀请链接 ====================
  - action: navigate
    name: "打开邀请链接"
    url: "https://windsurf.com/refer?referral_code=55424ec434"
    options:
      waitUntil: 'networkidle2'
      timeout: 30000
  
  - action: click
    name: "点击接受邀请"
    selector:
      - text: 'Sign up to accept referral'
        selector: 'button'
      - css: 'button.bg-sk-aqua'
      - css: 'button:has-text("Sign up to accept referral")'
    timeout: 30000
    waitForNavigation: true
  
  # 验证跳转到注册页面（带referral_code）
  - action: verify
    name: "验证跳转到注册页面"
    conditions:
      success:
        - urlContains: "/account/register"
        - urlContains: "referral_code=55424ec434"
    timeout: 10000

  # ==================== 步骤 1: 打开注册页面并填写信息（带重试） ====================
  - action: retryBlock
    name: "打开注册页面并填写基本信息"
    maxRetries: 3
    retryDelay: 3000
    
    steps:
      # 1.1 验证注册页面元素已加载
      - action: wait
        name: "等待注册表单加载"
        type: element
        selector: '#firstName'
        timeout: 15000
      
      # 1.2 填写基本信息
      - action: fillForm
        name: "填写基本信息"
        fields:
          firstName: "{{account.firstName}}"
          lastName: "{{account.lastName}}"
          email: "{{account.email}}"
      
      # 1.3 勾选同意条款
      - action: click
        name: "勾选同意条款"
        selector:
          - css: 'input[type="checkbox"]'
        optional: true
      
      # 1.4 点击 Continue
      - action: click
        name: "点击 Continue (基本信息)"
        selector:
          - text: 'Continue'
            selector: 'button, a'  # 明确指定查找范围：按钮或链接
        timeout: 30000
        # 验证点击后密码页面出现
        verifyAfter:
          appears:
            - '#password'
            - 'input[type="password"]'

  # ==================== 步骤 2: 设置密码 ====================
  - action: fillForm
    name: "设置密码"
    fields:
      password: "{{account.password}}"
      passwordConfirmation: "{{account.password}}"
  
  - action: click
    name: "提交密码"
    selector:
      - text: 'Continue'
        selector: 'button, a'
    timeout: 30000

  # ==================== 步骤 2.5: Cloudflare Turnstile 验证 ====================
  - action: custom
    name: "Cloudflare Turnstile 验证"
    handler: "handleTurnstile"
    params:
      timeout: 30000
      maxRetries: 3
      # 重试策略：
      # - 'refresh': 刷新页面（适用于保持状态的网站）
      # - 'restart': 刷新后重新填写（适用于刷新=重置的网站，如 Windsurf）
      # - 'wait': 只等待不刷新
      retryStrategy: 'restart'  # Windsurf 刷新会回到第一步
    optional: true

  # ==================== 步骤 3: 邮箱验证 ====================
  # 需要自定义处理：获取邮件验证码 + 填写6个输入框
  - action: custom
    name: "邮箱验证"
    handler: "handleEmailVerification"
    params:
      timeout: 120000

  # ==================== 步骤 4: 跳过问卷调查 ====================
  - action: click
    name: "跳过问卷"
    selector:
      - text: 'Skip this step'
        selector: 'button, a'
      - text: 'skip'
        selector: 'button, a'
        exact: false

  # ==================== 步骤 5: 选择计划 ====================
  - action: click
    name: "选择计划"
    selector:
      - text: 'Select plan'
        selector: 'button, a'
    timeout: 30000
  
  # 等待跳转到 Stripe 支付页面（通用 URL 等待）
  - action: wait
    name: "等待跳转到 Stripe"
    type: url
    urlContains: "stripe.com"
    timeout: 20000

  # ==================== 步骤 6: 填写支付信息（带重试） ====================
  - action: retryBlock
    name: "提交支付并验证"
    maxRetries: 9999  # 无限重试，直到成功
    retryDelay: 15000  # 增加到15秒，避免触发Stripe风控
    onRetryBefore:
      # 生成银行卡（第一次或重试都生成新卡）
      - action: custom
        handler: "generateCard"
    
    steps:
      # 6.1 选择银行卡支付方式（每次重试都重新选择）
      - action: click
        name: "选择银行卡支付"
        selector:
          - css: 'input[type="radio"][value="card"]'
        verifyAfter:
          checked: true  # 验证 radio button 是否选中
      
      # 填写支付信息（银行卡+国家+地址）
      - action: fillForm
        name: "填写支付信息"
        fields:
          cardNumber: "{{card.number}}"
          cardExpiry: "{{card.month}}{{card.year}}"
          cardCvc: "{{card.cvv}}"
          billingName: "{{account.firstName}} {{account.lastName}}"
          billingCountry:
            find:
              - css: '#billingCountry'
            value: "MO"
            type: "select"
          addressLine1:
            find:
              - css: '#billingAddressLine1'  # 使用 id 选择器，兼容所有语言
              - css: 'input[name="billingAddressLine1"]'
              - css: 'input[placeholder*="地址"]'
              - css: 'input[placeholder*="Address"]'
              - css: 'input[placeholder*="Alamat"]'  # 印尼语
            value: "kowloon"
      
      # 滚动到页面底部（确保订阅按钮可见）
      - action: scroll
        name: "滚动到订阅按钮"
        type: bottom
      
      # 提交支付（内部会等待按钮变为可点击状态）
      - action: click
        name: "点击提交支付"
        selector:
          - css: 'button[data-testid="hosted-payment-submit-button"]'  # Stripe 官方 testid
          - css: 'button.SubmitButton'  # Stripe 按钮类名
          - css: 'button[type="submit"]'  # 通用 submit 按钮
          - css: 'button:has(.SubmitButton-IconContainer)'  # 包含 icon 容器的按钮
        timeout: 30000  # 给足够时间等待按钮从 disabled 变为可点击
        waitForEnabled: true  # 循环等待按钮激活（不是等待出现，而是等待可点击）
      
      # 验证点击是否生效（检查按钮状态变化）
      - action: custom
        name: "验证订阅按钮点击生效"
        handler: "verifySubmitClick"
      
      # 处理 hCaptcha（等待60秒让用户手动完成）
      - action: custom
        name: "hCaptcha 验证"
        handler: "handleHCaptcha"
      
      # 验证支付结果（轮询检测成功或失败）
      - action: verify
        name: "验证支付结果"
        conditions:
          success:
            - urlNotContains: "stripe.com"
            - urlNotContains: "checkout.stripe.com"
          failure:
            # 英文
            - textContains: "card was declined"
            - textContains: "Your card was declined"
            - textContains: "declined"
            - textContains: "We are unable to authenticate your payment method"
            # 中文
            - textContains: "卡片被拒绝"
            - textContains: "我们无法验证您的支付方式"
            - textContains: "我们未能验证您的支付方式"
            - textContains: "请选择另一支付方式并重试"
            # 马来语
            - textContains: "Kad anda telah ditolak"  # 您的卡已被拒绝
            - textContains: "Kami tidak dapat mensahihkan kaedah pembayaran"
            - textContains: "Sila pilih kaedah pembayaran yang berbeza"
            # 印尼语
            - textContains: "Kami tidak dapat memverifikasi metode pembayaran"
            - textContains: "Silakan pilih metode pembayaran"
            - textContains: "kartu ditolak"
            # 泰语
            - textContains: "บัตรของคุณถูกปฏิเสธ"  # 您的卡被拒绝
            - textContains: "ไม่สามารถยืนยัน"  # 无法验证
            - textContains: "เราตรวจสอบสิทธิ์วิธีการชำระเงินของคุณไม่ได้"  # 我们无法验证您的支付方式
            - textContains: "โปรดเลือกวิธีการชำระเงินอื่น"  # 请选择另一个支付方式
            # 通用错误元素
            - elementExists: ".error-message"
        timeout: 15000
        pollInterval: 500
        onFailure: "throw"

  # ==================== 步骤 7: 获取订阅信息 ====================
  # 7.1 跳转到订阅使用页面
  - action: navigate
    name: "跳转订阅页面"
    url: "https://windsurf.com/subscription/usage"
  
  # 7.2 提取配额信息
  - action: extract
    name: "提取配额信息"
    selector: "p.caption1.font-medium.text-sk-black\\/80 span.caption3 span"
    multiple: true
    contextKey: "quotaRaw"
    required: false
  
  # 7.3 提取账单周期信息
  - action: extract
    name: "提取账单周期"
    selector: "p.caption1"
    extractType: "text"
    filter:
      contains: "Next billing cycle"
    regex: "(\\d+)\\s+days?.*on\\s+([A-Za-z]+\\s+\\d+,\\s+\\d{4})"
    saveTo:
      days: "$1"
      date: "$2"
    contextKey: "billingInfo"
    required: false
  
  # 7.4 处理提取的数据（自定义）
  - action: custom
    name: "处理订阅数据"
    handler: "processSubscriptionData"
    optional: true

  # ==================== 步骤 8: 保存到数据库 ====================
  - action: custom
    name: "保存到数据库"
    handler: "saveToDatabase"
    optional: true

  # ==================== 步骤 9: 退出登录 ====================
  # 9.1 滚动到页面底部
  - action: scroll
    name: "滚动到页面底部"
    direction: "bottom"
  
  # 9.2 等待滚动完成
  - action: wait
    name: "等待滚动完成"
    duration: 1000
  
  # 9.3 点击退出登录
  - action: click
    name: "点击退出登录"
    selector:
      - css: 'div.body3.cursor-pointer:has-text("Log out")'
      - css: 'div.body3:has-text("Log out")'
      - xpath: '//div[contains(@class, "body3") and contains(text(), "Log out")]'
      - text: "Log out"
    timeout: 15000
    waitForNavigation: true
  
  # 9.4 验证页面已变化（离开订阅页面）
  - action: verify
    name: "验证页面已变化"
    conditions:
      success:
        - or:
          - urlContains: "/account/login"
          - urlContains: "/login"
          - urlContains: "/"
      failure:
        - urlContains: "/subscription/usage"
    timeout: 10000
    optional: true
  
  # 9.5 验证跳转到登录页
  - action: verify
    name: "验证跳转到登录页"
    conditions:
      success:
        - or:
          - urlContains: "/account/login"
          - urlContains: "/login"
    timeout: 5000
    optional: true

# 错误处理配置
errorHandling:
  screenshot: true
  retry:
    enabled: true
    maxAttempts: 3
    delay: 2000
