When(/^I upload an? (valid|invalid) music video$/) do |validity|
  on(Video::VideoPage) do |page|
    page.wait_until { page.cancel_upload? || page.delete_video? || page.video_upload? }
    step "I cancel the video upload" if page.cancel_upload?
    page.loading_element.wait_while(&:present?) if page.loading?
    page.upload_video(validity)
    @product_id = @browser.url.scan(/\d+/).last
    puts "Product ID: #{@product_id}"
    page.wait_until { page.active_step? }
    page.wait_until(300) { page.completed_step_elements.size == 1 }
  end
end

Then(/^the video starts the validation process$/) do
  on(Video::VideoPage) do |page|
    eventually do
      expect(page.active_step).to eql("VALIDATE")
    end
  end
end

Then(/^the video eventually fails the validation process$/) do
  on(Video::VideoPage) do |page|
    eventually(timeout: 180) do
      expect(page.validation_errors?).to be true
    end
  end
end

When(/^I fill out the video metadata fields and refresh$/) do
  on(Video::VideoPage) do |page|
    page.wait_until { page.video_title? }
    page.loading_element.wait_while(&:present?) if page.loading?
    page.populate_video_basics(@release_data)
    page.populate_video_content(@release_data)
    page.populate_video_rights_and_distribution(@release_data)
    page.wait_until { page.special_instructions == @release_data[:special_instructions] }
    page.save
    page.refresh
  end
end

Then(/^the video metadata is still present after the refresh$/) do
  on(Video::VideoPage) do |page|
    page.wait_until { !page.video_title_element.when_present.text.nil? }
    # Since select lists take a bit longer to populate:
    page.wait_until(120) { page.type_of_video == @release_data[:type_of_video] }
    page.loading_element.wait_while(&:present?) if page.loading?
    # waits a bit longer in case some fields haven't finished populating
    wait_a_bit = proc do |exception, try|
      puts "#{exception.class}: '#{exception.message}' - Retry attempt: #{try}"
    end
    Retriable.retriable(on: RSpec::Expectations::ExpectationNotMetError, tries: 3,
                        base_interval: 5, on_retry: wait_a_bit) do
      the_vals = page.video_page_values
      expect(the_vals).to eq @release_data
    end
  end
end

When(/^the video finishes validating$/) do
  on(Video::VideoPage) do |page|
    eventually(timeout: 180) do
      # First completed step means the upload finished
      # Second completed step means video validation finished
      expect(page.completed_step_elements.size).to eq 2
    end
  end
end

Then(/^the video preview should appear$/) do
  on(Video::VideoPage) do |page|
    eventually(timeout: 180) do
      expect(page.video_player?).to be true
    end
    page.video_player_element.div_element(class: "Loader").when_present.wait_while(&:present?)
    unless page.video_player_element.when_present.div_element(class: "Poster-icon").present?
      page.video_player_element.link_element(text: "reload the player").click
    end
    page.video_player_element.div_element(class: "Poster-icon").wait_until(&:present?)
    page.preview_start_time = "00:03"
    page.play_preview
    page.elapsed_time_element.wait_until(&:present?)
    # Verifies that preview started at 3 seconds
    expect(page.elapsed_time.split(":").last.to_i).to be >= 3
  end
end

When(/^I submit the video product$/) do
  on(Video::VideoPage) do |page|
    expect(page.save_or_submit_element.text).to eql "SAVE & REVIEW"
    page.save_or_submit
    page.wait_until { page.save_or_submit_element.text == "SUBMIT FOR APPROVAL" }
    # Click it with JS since the page scrolls to the top and the native click might miss
    page.click_with_javascript(page.save_or_submit_element)
  end
end

Then(/^the video product is queued up for approval$/) do
  on(Video::VideoPage) do |page|
    expect(page.product_notification_element.when_present.text).to eq "Product Submitted"
    # add expectation to verify that a UPC has been generated on product submission
    release_status = Support::DbClient.query_art_relations(
      "SELECT release_status FROM releases WHERE release_id = '#{@product_id}'"
    ).first["release_status"]
    expect(release_status).to eql "transfer_to_content"
  end
end

Then(/^I see that the product delivery links go to the appropriate pages$/) do
  on(Video::VideoApprovalPage) do |page|
    upc = Support::DbClient.query_art_relations(
      "SELECT display_upc FROM releases WHERE release_id = '#{@product_id}'"
    ).first["display_upc"]
    page.wait_until { page.add_edit_carveouts_element.when_present.href.include? upc }
    expect(page.add_edit_carveouts_element.href)
      .to include "cont_mgmt/track_restriction.php?upc=#{upc}"
    expect(page.add_edit_exclusivity_element.href)
      .to include "cont_mgmt/ex_release_exclusive_pop.php?release_id=#{@product_id}"
    expect(page.view_delivery_history_element.href)
      .to include "warehouse/individual_upc_overall.php?upc=#{upc}"
  end
end

When(/^I edit the video's project info$/) do
  on(Video::VideoApprovalPage) do |page|
    @project_description = "Project description #{Time.stamp}"
    page.wait_until { page.project_info? }
    page.edit_project_info
    page.wait_until { !page.project_description_element.when_present.text.empty? }
    page.project_description = @project_description
    page.save_project_description
  end
end

Then(/^I see the updated project info$/) do
  on(Video::VideoApprovalPage) do |page|
    eventually do
      expect(page.project_info_element.div_element(class: "OAProjectInfo-column-values").text)
        .to include @project_description
    end
  end
end

When(/^I reject the video product$/) do
  on(Video::VideoApprovalPage) do |page|
    page_refresh = proc do |exception, try|
      puts "#{exception.class}: '#{exception.message}' - Retry attempt: #{try}"
      page.refresh
    end
    Retriable.retriable(on: Watir::Wait::TimeoutError, tries: 2, on_retry: page_refresh) do
      page.wait_until(10) { page.product_status_element.when_present.text == "NEW SUBMISSION" }
    end
    @rejection_message = "Rejected #{Time.stamp}"
    page.reject_video_submission(@rejection_message)
  end
end

Then(/^the video product should be rejected$/) do
  on(Video::VideoApprovalPage) do |page|
    page.wait_until { page.error_box? }
    eventually { expect(page.error_box).to include @rejection_message }
  end
end

When(/^I approve the video product$/) do
  on(Video::VideoApprovalPage) do |page|
    page.wait_until { page.product_status_element.when_present.text == "NEW SUBMISSION" }
    page.content_is_approved_element.click
    page.release_is_approved_element.click
    page.wait_until { !page.approve_video_element.disabled? }
    page.approve_video
  end
end

Then(/^the video product should be in content$/) do
  eventually(timeout: 10) do
    release_status = Support::DbClient.query_art_relations(
      "SELECT release_status FROM releases WHERE release_id = '#{@product_id}'"
    ).first["release_status"]
    expect(release_status).to eql "in_content"
  end
end

Given(/^a submitted music video product$/) do
  @product_id = 2_541_075
  if Support::DbClient.current_release_status(@product_id) == "transfer_to_content"
    Support::Services::OwsVideo.reject_product(@product_id)
  end
  step "I am on the Video::ExistingVideoPage for the product"
  on(Video::VideoPage) do |page|
    page.wait_until { page.cancel_upload? || page.delete_video? || page.video_upload? }
    # Delete the video if it hasn't finished validation
    if page.cancel_upload?
      page.cancel_upload
      page.confirm_delete_video_element.when_present.click
      page.wait_until { page.video_upload? }
      page.refresh
    end
    page.new_artist_element.wait_until(&:present?)
    if page.video_upload?
      step "I upload a valid music video"
      step "the video starts the validation process"
      step "the video finishes validating"
      step "the video preview should appear"
    end
    # Update release date to something in the future
    page.apply_release_date(Date.today + 10)
  end
  step "I submit the video product"
end

And(/^I am on an in-progress video product page$/) do
  @product_id = 2_570_625
  step "I am on the Video::ExistingVideoPage for the product"
end

And(/^I cancel the video upload$/) do
  on(Video::VideoPage) do |page|
    page.cancel_upload_element.when_present.click
    @workflow_id = Support::DbClient.query_art_relations(
      "SELECT latest_pipeline_run_id FROM product_video WHERE release_id = '#{@product_id}'"
    ).first["latest_pipeline_run_id"]
    page.confirm_delete_video_element.when_present.click
    page.wait_until { page.video_upload? }
  end
end

Then(/^the video workflow is cancelled$/) do
  eventually(timeout: 10) do
    job_status = Support::Services::OwsVideo.video_job_status(@workflow_id)
    expect(job_status).to eql("CANCELLED")
  end
end

When(/^I enter a video title without saving the form$/) do
  on(Video::VideoPage).video_title_element.when_present.set Time.stamp
end

Then(/^I see a warning pop up when I attempt to navigate away$/) do
  @browser.after_hooks.without do |page|
    on(Workstation::BasePage).logout
    expect(page.alert.exists?).to be true
    page.alert.ok
  end
end

When(/^I set the video type to (.*?)$/) do |video_type|
  on(Video::VideoPage) do |page|
    page.genre_element.wait_until(&:present?)
    page.retry_select_and_assert("type_of_video", video_type)
  end
end

Then(/^the genre select list should be automatically set to (.*?)$/) do |genre|
  on(Video::VideoPage) do |page|
    eventually(timeout: 10) do
      expect(page.genre).to eql genre
      expect(page.genre_element.attribute("class")).to include "is-disabled"
    end
  end
end

Then(/^the subgenre select list can be set to (.*?)$/) do |subgenre|
  on(Video::VideoPage).retry_select_and_assert("subgenre", subgenre)
end

When(/^I try to save a (.*?) without selecting a (.*?)/) do |field_to_fill, _|
  on(Video::VideoPage) do |page|
    page.contributor_row_element.wait_until(&:present?)
    if page.contributor_row_element.div_element(class: "Metadata-error").present?
      page.refresh
      page.contributor_row_element.wait_until(&:present?)
    end
    if field_to_fill == "contributor"
      page.contributor_name = Time.stamp
      expect(page.contributor_role_element.text).to eql "Select..."
    elsif field_to_fill == "contributor role"
      page.retry_select_and_assert("contributor_role", "Composer")
      expect(page.contributor_name_element.text).to eql ""
    end
    page.save
  end
end

Then(/^I see a warning saying both contributor fields must be present$/) do
  on(Video::VideoPage) do |page|
    expect(page.contributor_row_element.div_element(class: "Metadata-error").when_present.text)
      .to include "Both contributor role and name must be present."
  end
end

When(/^I enter (\d+) new video products? on the bulk ingest form$/) do |num|
  on(Video::BulkIngestVideoPage) do |page|
    page.start_process
    page.wait_until { page.bulk_ingest_form.present? }
    @new_video_titles = []
    (1..num).each do |i|
      step "I have valid Video Product data"
      @new_video_titles.push "Watir Ingest Video #{@release_data[:product_code]}"
      page.populate_bulk_ingest_form(i, @release_data)
    end
    page.submit_bulk_form
  end
end

Then(/^I see an ingestion success after submitting the form$/) do
  on(Video::BulkIngestVideoPage) do |page|
    eventually { expect(page.success_tick?).to be true }
    results_table = page.results_table_element.text
    @new_video_titles.each do |video_title|
      expect(results_table.include?(video_title)).to be true
    end
  end
end
