class SinglePageCheckoutContext < PublicContext

  def initialize
    super
    existing_spc_react = Page.find_by(url: "/create-account")
    existing_spc_react.destroy unless existing_spc_react.nil?

    existing_spc_v2 = Page.find_by(url: "/create-account-V2")
    existing_spc_v2.destroy unless existing_spc_v2.nil?

    Testing::PageGenerator.create_page("creator-checkout")
    Testing::PageGenerator.create_page("sign-up")
  end

  def given_visit_page(url, params)
    @coupon_code = get_param(params, 'coupon_code')
    @plan_id     = get_param(params, 'plan_id')
    unless current_path == url
      url += "?#{params}" if params.length > 0
      visit url
    end
    wait_for_ajax
  end

  def fill_new_account_info(table)
    expect(page).to have_css("form[data-test=\"createAccount\"]")
    new_acc = table.rows_hash

    find("input[data-test=\"password\"]").set(new_acc["password"])
    find("input[data-test=\"confirmPassword\"]").set(new_acc["confirm password"])
    find("input[data-test=\"accountName\"]").set(new_acc["account name"])
    find("input[data-test=\"schoolName\"]").set(new_acc["school name"])
    page.execute_script("$('input:focus').blur()")
  end

  def fill_in_stripe(name, value)
    selector = "input[name=#{name}]"
    all("iframe").each do |iframe|
      within_frame iframe do
        element = find(selector, wait: 0.5)
        if element
          value.each_char do |char|
            sleep 0.01
            element.send_keys(char)
          end
          return true
        end
      rescue Capybara::ElementNotFound
        next
      end
    end
    fail "Couldn't find Stripe input #{name.inspect}"
  end

  def fill_in_stripe_field(table)
    expect(page).to have_css("h4", text: "Payment information")
    card_info = table.rows_hash

    fill_in_stripe("cardnumber", card_info["cardnumber"]) if card_info["cardnumber"]
    fill_in_stripe("exp-date", card_info["exp-date"]) if card_info["exp-date"]
    fill_in_stripe("cvc", card_info["cvc"]) if card_info["cvc"]

    select(card_info["country"], from: "stripe-country") if card_info["country"]
    select(card_info["state"], from: "stripe-state") if card_info["state"]
    find("#stripe-postal-code").set(card_info["postal code"] + "\n") if card_info["postal code"]
    page.execute_script("$('input:focus').blur()")
  end

  def fill_in_fields_v2(fields)
    stripe_fields = ['card number', 'card expiration', 'cvc code', 'postal code']
    fields.each do |field_and_values|
      field, value = field_and_values[0], field_and_values[1]
      if stripe_fields.include?(field)
        fill_in_stripe_field_v2(field, value)
      else
        fill_in_non_stripe_field_v2(field, value)
      end
    end
  end

  def fill_in_stripe_field_v2(field, value)
    within("##{field.split(' ').join('-')}") do
      Capybara.within_frame(find('iframe')['name']) do
        value.split('').each do |number|
          count = find_all('input').size
          input_field = count == 1 ? find('input') : find('input.inputElement')
          input_field.send_keys(number)
          input_field.native.send_keys(:tab)
        end
      end
    end
  end

  def fill_in_non_stripe_field_v2(field, value)
    select_fields = ['country code', 'region code']
    if (select_fields.include?(field))
      select value, :from => "#{field.split(' ').join('-')}"
    else
      fill_in "#{field.split(' ').join('-')}", with: value
    end
  end

  def enter_coupon_code(credential_type, coupon, plan)
    coupon = all_coupons['coupon code'][credential_type][coupon][plan]
    find("button[data-test=\"couponCodeOpen\"]").click
    fill_in_coupon_box(coupon)
    find("button[data-test=\"couponCodeApply\"]").click
    wait_for_ajax
  end

  def fill_in_coupon_box(coupon)
    find("input[data-test=\"codeInput\"]").set(coupon)
  end

  def enter_coupon_code_v2(credential_type, coupon, plan)
    coupon = all_coupons['coupon code'][credential_type][coupon][plan]
    find('#add-coupon-box').click
    fill_in_coupon_code_v2 coupon
    find('.dark-green-button').click
    wait_for_ajax
  end

  def fill_in_coupon_code_v2(coupon)
    fill_in 'coupon-code', with: coupon
  end

  def find_purchase_btn
    purchase_button = "button[data-test=\"purchasePlan\"]"
    expect(page).to have_css(purchase_button)
  end

  def expect_purchase_btn_disabled
    purchase_button = find("button[data-test=\"purchasePlan\"]")
    expect(purchase_button.disabled?).to eq(true)
  end

  def click_purchase
    purchase_button = find("button[data-test=\"purchasePlan\"]")
    expect(purchase_button.disabled?).to be false
    purchase_button.click
    wait_for_ajax
  end

  def press_purchase_v2
    page.execute_script "document.getElementById('purchase-plan').scrollIntoView()"
    page.find("#purchase-plan").click
  end

  def fill_email_address_field(email)
    email_input = "input[data-test=\"email-input\"]"
    expect(page).to have_css(email_input)
    find(email_input).set(email + "\n")
  end

  def verify_existing_account
    password_field = "input[data-test=\"password\"]"
    expect(page).to have_css(password_field)
    find(password_field).set("password")
    click_on "Verify"
  end

  def verify_existing_account_v2
    page.fill_in "existing-account-password", with: "password"
    find("#verify-email-with-password").click()
  end

  def select_existing_school(name)
    choose_school = find("div[data-test=\"foundAccount\"] > div:nth-child(2) > select")
    choose_school.click
    choose_school.all("option")[position].click
  end

  def select_existing_school_v2(position)
    find("#choose-account-information-select").all("option:not(:disabled)")[position].select_option
  end

  def change_school_name(name)
    choose_school = find("div[data-test=\"foundAccount\"] > div:nth-child(2) > select")
    choose_school.click
    choose_school.all("option").each do |opt|
      opt.click if opt.text.include? name
    end
  end

  def create_new_school(name)
    choose_school = find("div[data-test=\"foundAccount\"] > div:nth-child(2) > select")
    choose_school.click
    choose_school.all("option").each do |opt|
      opt.click if opt.value == "CREATE"
    end
    school_name_input = "input[data-test=\"schoolNameInput\"]"
    expect(page).to have_css(school_name_input)
    find(school_name_input).set(name)
  end

  def click_new_payment_method
    expect(page).to have_button("Click here to use a new payment method.")
    click_on("Click here to use a new payment method.")
  end

  def click_new_payment_method_v2
    find("#new-payment-method-existing-account").click()
  end

  def choose_create_new_school(name)
    schools = find("div[data-test=\"foundAccount\"] > div:nth-child(2) > select").click
    schools.all("option").last.click

    school_name_input = "input[data-test=\"schoolNameInput\"]"
    expect(page).to have_css(school_name_input)
    find(school_name_input).set(name)
  end

  def choose_create_new_school_v2
    find("#choose-account-information-select").all("option:not(:disabled)").last.select_option
  end

  def expect_payment_info_exist
    expect(page).to have_content("Upgrade will be made using")
    expect(page).to have_content(" card ending in ")
  end

  def expect_not_to_see_schools_with_name(name)
    options = find("div[data-test=\"foundAccount\"] > div:nth-child(2) > select").all("option")
    options.each do |option|
      expect(option.disabled?).to eq(true) if option.text.include? name
    end
  end

  def expect_correct_information
    plan = Plan.find_by(app_monthly_plan_id: @plan_id)
    if plan
      price = plan.monthly_price
      duration = 'monthly'
    else
      plan = Plan.find_by(app_annual_plan_id: @plan_id)
      price = plan.annual_price
      duration = 'annually'
    end
    expect(page).to have_content(duration)
    expect(page).to have_content(price)
  end

  def expect_correct_order_summar_plan_start_date
    date = find('#top-billing-cycle-start-date').text()
    
    expect_proper_date_format(date)
    expect_content_on_page("Your next billing cycle is #{date}")
  end

  def expect_immediate_billing_cycle_start
    plan_price = get_plan_price
    expect_content_on_page("Your $#{plan_price} #{get_annual_or_monthly} subscription will begin today.")
  end

  def expect_no_order_summary_plan_start_date
    hidden = find("#billing-cycle-start", visible: false)[:class].split(' ').include?("hidden")
    expect(hidden).to be true
  end

  def expect_correct_plan_price(total)
    order_total = find("#creator-checkout-root > div > div.col.col-12-xs.col-5-m.m-l-auto-m > section > form > div:nth-child(5) > section > div > div")
    expect(order_total).to have_text(total)
  end

  def expect_correct_total_price_v2(total)
    expect(find("h3.final-plan-price")).to have_text(total)
  end

  def expect_correct_coupon(code)
    expect(find("input[data-test=\"codeInput\"]").value).to eq(code)
  end

  def expect_correct_coupon_code_v2(code)
    expect(find('#coupon-code', visible: false).value).to eq(code)
  end

  def expect_enabled_apply_button
    disabled_purchase_btn = find("button[data-test=\"purchasePlan\"]")[:disabled]
    expect(disabled_purchase_btn).to eq "true"
  end

  def expect_enabled_apply_button_v2
    is_disabled = find(".dark-green-button")[:class].include?("disabled")
    expect(is_disabled).to be false
  end

  def expect_not_to_see_schools_with_plan_id(plan_id)
    options = find("#choose-account-information-select").all("option[data-school-plan-id='#{plan_id}']")
    options.each do |option|
      expect(option.disabled?).to eq true
    end
  end

  private

  def get_param(params, param)
    coupon_code = params.split('&').select do |string|
      (string.index("#{param}=") || -1) >= 0
    end
    coupon_code.first.split("#{param}=").last unless coupon_code.first.nil?
  end

  def expect_proper_date_format(date)
    proper_format = /\d{1,2}\s+(Jan(uary)?|Feb(ruary)?|Mar(ch)?|Apr(il)?|May|Jun(e)?|Jul(y)?|Aug(ust)?|Sep(tember)?|Oct(ober)?|Nov(ember)?|Dec(ember)?)\s+\d{4}/.match?(date)
    expect(proper_format).to be true
  end

  def get_plan_price
    annual_or_monthly = get_annual_or_monthly
    Plan.find_by("app_#{annual_or_monthly}_plan_id" => @plan_id)["#{annual_or_monthly}_price"]
  end

  def get_annual_or_monthly
    Plan.get_annual_plan_ids.include?(@plan_id.to_i) ? 'annual' : 'monthly'
  end

  def all_coupons
    {
      'coupon code' => {
        'invalid' => {'3 months free' => {'Professional Annual' => 'notACode'}},
        'valid' => {'3 months free' => {'Basic Monthly' => 'EDC6AA8515948BDD16643BA44EA18D70'}}
      }
    }
  end
end
