require "capybara/dsl"
require "rspec/matchers"

class GlobalContext
  include RSpec::Matchers
  include Capybara::DSL

  def initialize
    @current_user = nil
  end

  def create_blog_settings!
    template = Template.create!(name: "Blog Settings")

    # HOMEPAGE SETTINGS -----
    homepage_header = Field.create!(name: "Homepage - Header", template_id: template.id, field_type: "text", mandatory: true, char_limit: 400, order: 0, object_type: "")
    homepage_subheader = Field.create!(name: "Homepage - Subheader", template_id: template.id, field_type: "text", mandatory: true, char_limit: 400, order: 1, object_type: "")

    homepage_cu_1 = Field.create!(name: "Homepage - Content Download 1", template_id: template.id, field_type: "content_download", mandatory: false, char_limit: 0, order: 2, object_type: "Content Download")
    homepage_cu_1_event_name = Field.create!(name: "Homepage - Content Download 1 Event Name", template_id: template.id, field_type: "text", mandatory: true, char_limit: 100, order: 3, object_type: "")
    homepage_cu_1_workflow_id = Field.create!(name: "Homepage - Content Download 1 Workflow ID", template_id: template.id, field_type: "number", mandatory: true, char_limit: 100, order: 4, object_type: "")

    homepage_cu_2 = Field.create!(name: "Homepage - Content Download 2", template_id: template.id, field_type: "content_download", mandatory: false, char_limit: 0, order: 5, object_type: "Content Download")
    homepage_cu_2_event_name = Field.create!(name: "Homepage - Content Download 2 Event Name", template_id: template.id, field_type: "text", mandatory: true, char_limit: 100, order: 6, object_type: "")
    homepage_cu_2_workflow_id = Field.create!(name: "Homepage - Content Download 2 Workflow ID", template_id: template.id, field_type: "number", mandatory: true, char_limit: 0, order: 7, object_type: "")


    # RESOURCES SETTINGS -----
    resources_header = Field.create!(name: "Resources - Header", template_id: template.id, field_type: "text", mandatory: true, char_limit: 200, order: 8, object_type: "")
    resources_subheader = Field.create!(name: "Resources - Subheader", template_id: template.id, field_type: "text", mandatory: true, char_limit: 200, order: 9, object_type: "")

    resources_content_download_fields = [
      Field.create!(name: "Resources - Category 1 Content Download 1", template_id: template.id, field_type: "content_download", mandatory: false, char_limit: 0, order: 10, object_type: "Content Download"),
      Field.create!(name: "Resources - Category 1 Content Download 2", template_id: template.id, field_type: "content_download", mandatory: false, char_limit: 0, order: 11, object_type: "Content Download"),
      Field.create!(name: "Resources - Category 1 Content Download 3", template_id: template.id, field_type: "content_download", mandatory: false, char_limit: 0, order: 12, object_type: "Content Download"),
      Field.create!(name: "Resources - Category 1 Content Download 4", template_id: template.id, field_type: "content_download", mandatory: false, char_limit: 0, order: 13, object_type: "Content Download"),
      Field.create!(name: "Resources - Category 1 Content Download 5", template_id: template.id, field_type: "content_download", mandatory: false, char_limit: 0, order: 14, object_type: "Content Download"),

      Field.create!(name: "Resources - Category 2 Content Download 1", template_id: template.id, field_type: "content_download", mandatory: false, char_limit: 0, order: 15, object_type: "Content Download"),
      Field.create!(name: "Resources - Category 2 Content Download 2", template_id: template.id, field_type: "content_download", mandatory: false, char_limit: 0, order: 16, object_type: "Content Download"),
      Field.create!(name: "Resources - Category 2 Content Download 3", template_id: template.id, field_type: "content_download", mandatory: false, char_limit: 0, order: 17, object_type: "Content Download"),
      Field.create!(name: "Resources - Category 2 Content Download 4", template_id: template.id, field_type: "content_download", mandatory: false, char_limit: 0, order: 18, object_type: "Content Download"),
      Field.create!(name: "Resources - Category 2 Content Download 5", template_id: template.id, field_type: "content_download", mandatory: false, char_limit: 0, order: 19, object_type: "Content Download"),
    ]

    resources_featured_cu = Field.create!(name: "Resources - Featured Content Download", template_id: template.id, field_type: "content_download", mandatory: false, char_limit: 0, order: 25, object_type: "Content Download")
    resources_featured_cu_event_name = Field.create!(name: "Resources - Featured Content Download Event Name", template_id: template.id, field_type: "text", mandatory: true, char_limit: 200, order: 26, object_type: "")
    resources_featured_cu_workflow_id = Field.create!(name: "Resources - Featured Content Download Workflow ID", template_id: template.id, field_type: "number", mandatory: true, char_limit: 200, order: 27, object_type: "")

    @blog_settings = Objekt.create!(template_id: template.id)

    ObjektField.create!(objekt_id: @blog_settings.id, field_id: homepage_header.id, value: "Homepage Header")
    ObjektField.create!(objekt_id: @blog_settings.id, field_id: homepage_subheader.id, value: "Homepage Subheader")

    ObjektField.create!(objekt_id: @blog_settings.id, field_id: homepage_cu_1.id, value: @content_download_1.id)
    ObjektField.create!(objekt_id: @blog_settings.id, field_id: homepage_cu_1_event_name.id, value: "Homepage Content Download 1 Event Name")
    ObjektField.create!(objekt_id: @blog_settings.id, field_id: homepage_cu_1_workflow_id.id, value: 1)

    ObjektField.create!(objekt_id: @blog_settings.id, field_id: homepage_cu_2.id, value: @content_download_2.id)
    ObjektField.create!(objekt_id: @blog_settings.id, field_id: homepage_cu_2_event_name.id, value: "Homepage Content Download 2 Event Name")
    ObjektField.create!(objekt_id: @blog_settings.id, field_id: homepage_cu_2_workflow_id.id, value: 2)

    ObjektField.create!(objekt_id: @blog_settings.id, field_id: resources_header.id, value: "Resources Header")
    ObjektField.create!(objekt_id: @blog_settings.id, field_id: resources_subheader.id, value: "Resources Subeader")

    ObjektField.create!(objekt_id: @blog_settings.id, field_id: resources_featured_cu.id, value: @content_download_1.id)
    ObjektField.create!(objekt_id: @blog_settings.id, field_id: resources_featured_cu_event_name.id, value: "Resources Featured Content Download Event Name")
    ObjektField.create!(objekt_id: @blog_settings.id, field_id: resources_featured_cu_workflow_id.id, value: 1)

    resources_content_download_fields.each do |cu_field|
      ObjektField.create!(objekt_id: @blog_settings.id, field_id: cu_field.id, value: @content_download_1.id)
    end
  end

  def change_nice_select_option(value, element)
    capitalized_value = value.split(' ').map(&:capitalize).join(' ')
    within(:xpath, get_parent_path(element.path)) do
      if find('span', visible: false).text.downcase != value.downcase
        nice_select = find('div.nice-select')
        list_item = select_option(nice_select, capitalized_value)
        return list_item
      else
        return find('li', text: capitalized_value, visible: false)
      end
    end
  end

  def get_parent_path(child_path)
    child_path.split('/')[0...-1].join('/')
  end

  def select_option(nice_select_field, text)
    nice_select_field.click
    within(nice_select_field) do
      return find("li", :text => text).click
    end
  end

  def create_plans
    @all ||= Plan.create!(name: "All Plans", annual_included: false, monthly_price: 0, order: 0, app_monthly_plan_id: 0)
    @free ||= Plan.create!(name: "Free", tagline: "Get started for free", annual_included: false, monthly_price: 0, includes_text: "All of our base features", order: 1, app_monthly_plan_id: 4)
    @basic ||= Plan.create!(name: "Basic", tagline: "Create your first online course", annual_included: true, monthly_price: 39, annual_price: 348, includes_text: "All of our base features, plus:", order: 2, app_monthly_plan_id: 153, app_annual_plan_id: 152)
    @professional ||= Plan.create!(name: "Professional", tagline: "Our most popular plan", annual_included: true, monthly_price: 119, annual_price: 1188, includes_text: "Everything in Basic, plus:", order: 3, app_monthly_plan_id: 186, app_annual_plan_id: 185)
    @business ||= Plan.create!(name: "Business", tagline: "Experience the best of Teachable", annual_included: true, monthly_price: 299, annual_price: 2988, includes_text: "Everything in Professional, plus:", order: 4, app_monthly_plan_id: 218, app_annual_plan_id:219)
  end

  def create_plan_features
    get_plan_features.each do |plan_name, features|
      plan_instance = instance_variable_get("@#{make_snake_case(plan_name)}")
      features.each_with_index do |feature_text, index|
        feature = Feature.find_by(text: feature_text) || Feature.create!({text: feature_text})
        tooltip_id = create_tooltip(plan_name, feature_text)
        PlanFeature.create!({plan_id: plan_instance.id, feature_id: feature.id, order: index, tooltip_id: tooltip_id})
      end
    end
  end

  def create_tooltip(plan_name, feature_text)
    plan_tooltips = get_tooltips[plan_name]
    if plan_tooltips && plan_tooltips[feature_text]
      tooltip_text = plan_tooltips[feature_text]
      tooltip = Tooltip.find_by(text: tooltip_text) || Tooltip.create!({text: tooltip_text})
      return tooltip.id
    end
    nil
  end

  def click_a_tag(button_text)
    expect(page).to have_text(button_text)
    begin
      find('a', text: button_text).click
    rescue
      btns = all('.btn').select { |btn| btn.value == button_text }
      if btns.length == 0
        btns = all('a').select { |btn| btn.text == button_text }
      end
      btns.first.click
    end

    wait_for_ajax
  end

  def switch_to_recently_opened_tab
    window = page.driver.browser.window_handles
    page.driver.browser.switch_to.window(window.last)
  end

  def get_uniq_str
    DateTime.now.to_s.remove(':')
  end

  def expect_content_on_page(text)
    expect(page).to have_content(text)
  end

  def expect_content_not_on_page(text)
    expect(page).to have_no_content(text)
  end

  def expect_input_value_on_page(text)
    expect(page).to have_selector("input[value='#{text}']")
  end

  # Public Helpers
  def make_lazy_camel_case(text)
    text.gsub(/\s/, '_').camelize(:lower)
  end

  def wait_for_ajax
    Timeout.timeout(Capybara.default_max_wait_time) do
      sleep(0.5) until finished_all_ajax_requests?
    end
  end

  def wait_for_redirect(timeout = 90)
    Timeout.timeout(timeout) do
      sleep(0.5) until current_url.include? ".zeachable.com/"
    end
  end

  def wait_until(timeout = Capybara.default_max_wait_time)
    Timeout.timeout(timeout) do
      sleep(0.5) until (value = yield)
      value
    end
  end

  def create_page_from_configuration(url)
    Testing::PageGenerator.create_page(url)
  end

  def percy_snapshot(page_name)
    page.execute_script("window.scrollBy({ top: document.body.scrollHeight, behavior: 'smooth'})")
    sleep(3)
    Percy.snapshot(page, name: page_name) if ENV["CI"]
  end

  def given_logged_in(name)
    @current_user = User.find_by(name: name) || create_user!(name)
    token = AAA::Test.generate_token(
      id:    @current_user.id,
      name:  @current_user.name,
      email: @current_user.email,
    )
    visit "/after-login?token=#{token}&no_redirect=true"
  end

  private

  def finished_all_ajax_requests?
    page.evaluate_script('(window.jQuery && window.jQuery.active) || 0').zero?
  end

  def make_snake_case(text)
    text.downcase.split(' ').join('_')
  end

  def get_ancestor_path(child_path, end_node = -1)
    child_path.split('/')[0...end_node].join('/')
  end

  def get_plan_features
    {
      'All' => ["Basic quizzes", "Discussion forums", "Integrated payment processing"],
      "Free" => [],
      'Basic' => ["2 owners/authors", "5% transaction fees", "Coupon codes", "Custom domain support", "Monthly payouts"],
      'Professional' => ["5 owners/authors", "Advanced reports", "Advanced theme customization", "Graded quizzes", "No transaction fees"],
      'Business' => ["Instant payouts", "Extra support", "Priority product support", "25 owners/authors", "Bulk student enrollments"]
    }
  end

  def get_tooltips
    {
      "Basic" => {
        "Monthly payouts" => "Has 30-day delay"
      },
      "Professional" => {
        "No transaction fees" => "0% rate only applies if you set up custom payment gateways."
      },
      "Business" => {
        "Instant payouts" => "If you set up direct payment gateways via Stripe and PayPal."
      }
    }
  end

  def create_menu_options(field_type, optionable_id, optionable_type)
    if field_type == 'dropdown'
      ['No', 'Yes'].each_with_index do |option, index|
        MenuOption.create!({value: option, optionable_id: optionable_id, optionable_type: optionable_type, order: index})
      end
    end
  end

  def create_partial_fields(partial_id, fields)
    fields.each do |field_type, type_hash|
      number_already_made_fields = Partial.find(partial_id).partial_fields.length
      type_hash['field_names'].each_with_index do |field_name, index|
        order = number_already_made_fields + index
        field_values = get_default_fields(field_name, field_type, type_hash['char_limit'], order)
        partial_field = PartialField.create!(field_values.merge({partial_id: partial_id, mandatory: type_hash['mandatory'], object_type: type_hash['object_type']}))
        create_menu_options(field_type, partial_field.id, 'PartialField')
        create_header_options if field_type == 'header'
      end
    end
  end

  def get_default_fields(name, type, char_limit, order)
    {
      name: name,
      field_type: type,
      char_limit: char_limit,
      order: order
    }
  end

  def create_page_partial(page_id, partial_id, parent_partial_field_id)
    order = PagePartial.where(page_id: page_id).length
    page_partial = PagePartial.create!(partial_id: partial_id, page_id: page_id, order: order, page_partial_field_id: parent_partial_field_id)
    PagePartialField.create_page_partial_fields!(page_partial)
    page_partial
  end

  def create_pricing_page
    unless Page.find_by(name: 'Pricing')
      pricing_page = Page.create!(
      name: 'Pricing',
      url: '/pricing',
      active: true,
      title_text: 'this is the pricing page',
      description: 'pricing page description',
      canonical_url: 'http://teachable.com/pricing',
      creator_id: 1,
      )
      pricing_partial = Partial.create!(name: 'Pricing Table')
      pricing_page_partial = PagePartial.create!(partial_id: pricing_partial.id, page_id: pricing_page.id, order: 1)

      default_field_params = { partial_id: pricing_partial.id, field_type: 'text', char_limit: 50 }
      default_page_partial_params = { page_partial_id: pricing_page_partial.id, value: '' }
      blank_fields = [
        'Upgrade Src',
        'Monthly Basic Coupon Code',
        'Monthly Professional Coupon Code',
        'Monthly Business Coupon Code',
        'Annual Basic Coupon Code',
        'Annual Professional Coupon Code',
        'Annual Business Coupon Code',
        'utm_sales_page_cta'
      ]
      blank_fields.each_with_index do |field_name, i|
        partial_field_params = default_field_params.merge({ name: field_name, order: i })
        partial_field = PartialField.create!(partial_field_params)

        page_partial_field_params = default_page_partial_params.merge({ partial_field_id: partial_field.id })
        PagePartialField.create!(page_partial_field_params)
      end

      toggle_field = PartialField.create!(default_field_params.merge({ name: 'Show Monthly/Annual Switch', order: blank_fields.length }))
      PagePartialField.create!(default_page_partial_params.merge({ value: 'Yes', partial_field_id: toggle_field.id }))

      biz_field = PartialField.create!(default_field_params.merge({ name: 'Show Business', order: blank_fields.length + 1 }))
      PagePartialField.create!(default_page_partial_params.merge({ value: 'Yes', partial_field_id: biz_field.id }))

      create_plans
    end
  end
end
