require 'rails_helper'

feature 'Valuation spending proposals' do

  background do
    @valuator = create(:valuator, user: create(:user, username: 'Rachel', email: 'rachel@valuators.org'))
    login_as(@valuator.user)
  end

  scenario 'Disabled with a feature flag' do
    Setting['feature.spending_proposals'] = nil
    expect{ visit valuation_spending_proposals_path }.to raise_exception(FeatureFlags::FeatureDisabled)
  end

  scenario 'Index shows spending proposals assigned to current valuator' do
    spending_proposal1 = create(:spending_proposal)
    spending_proposal2 = create(:spending_proposal)

    spending_proposal1.valuators << @valuator

    visit valuation_spending_proposals_path

    expect(page).to have_content(spending_proposal1.title)
    expect(page).to_not have_content(spending_proposal2.title)
  end

  scenario 'Index shows no spending proposals to admins no valuators' do
    spending_proposal1 = create(:spending_proposal)
    spending_proposal2 = create(:spending_proposal)
    spending_proposal1.valuators << @valuator

    logout
    login_as create(:administrator).user
    visit valuation_spending_proposals_path

    expect(page).to_not have_content(spending_proposal1.title)
    expect(page).to_not have_content(spending_proposal2.title)
  end

  scenario 'Index orders spending proposals by votes' do
    spending_proposal10 = create(:spending_proposal, cached_votes_up: 10)
    spending_proposal100 = create(:spending_proposal, cached_votes_up: 100)
    spending_proposal1 = create(:spending_proposal, cached_votes_up: 1)

    spending_proposal1.valuators << @valuator
    spending_proposal10.valuators << @valuator
    spending_proposal100.valuators << @valuator

    visit valuation_spending_proposals_path

    expect(spending_proposal100.title).to appear_before(spending_proposal10.title)
    expect(spending_proposal10.title).to appear_before(spending_proposal1.title)
  end

  scenario 'Index shows assignments info' do
    spending_proposal1 = create(:spending_proposal)
    spending_proposal2 = create(:spending_proposal)
    spending_proposal3 = create(:spending_proposal)

    valuator1 = create(:valuator, user: create(:user))
    valuator2 = create(:valuator, user: create(:user))
    valuator3 = create(:valuator, user: create(:user))

    spending_proposal1.valuator_ids = [@valuator.id]
    spending_proposal2.valuator_ids = [@valuator.id, valuator1.id, valuator2.id]
    spending_proposal3.valuator_ids = [@valuator.id, valuator3.id]

    visit valuation_spending_proposals_path

    within("#spending_proposal_#{spending_proposal1.id}") do
      expect(page).to have_content("Rachel")
    end

    within("#spending_proposal_#{spending_proposal2.id}") do
      expect(page).to have_content("3 valuators assigned")
    end

    within("#spending_proposal_#{spending_proposal3.id}") do
      expect(page).to have_content("2 valuators assigned")
    end
  end

  scenario "Index filtering by geozone", :js do
    geozone = create(:geozone, name: "District 9")
    spending_proposal1 = create(:spending_proposal, title: "Realocate visitors", geozone: geozone)
    spending_proposal2 = create(:spending_proposal, title: "Destroy the city")
    spending_proposal1.valuators << @valuator
    spending_proposal2.valuators << @valuator

    visit valuation_spending_proposals_path
    expect(page).to have_link("Realocate visitors")
    expect(page).to have_link("Destroy the city")

    click_link "District 9", exact: false

    expect(page).to have_link("Realocate visitors")
    expect(page).to_not have_link("Destroy the city")

    click_link "All city", exact: false

    expect(page).to have_link("Destroy the city")
    expect(page).to_not have_link("Realocate visitors")

    click_link "All zones", exact: false
    expect(page).to have_link("Realocate visitors")
    expect(page).to have_link("Destroy the city")
  end

  scenario "Current filter is properly highlighted" do
    filters_links = {'valuating' => 'Under valuation',
                     'valuation_finished' => 'Valuation finished'}

    visit valuation_spending_proposals_path

    expect(page).to_not have_link(filters_links.values.first)
    filters_links.keys.drop(1).each { |filter| expect(page).to have_link(filters_links[filter]) }

    filters_links.each_pair do |current_filter, link|
      visit valuation_spending_proposals_path(filter: current_filter)

      expect(page).to_not have_link(link)

      (filters_links.keys - [current_filter]).each do |filter|
        expect(page).to have_link(filters_links[filter])
      end
    end
  end

  scenario "Index filtering by valuation status" do
    valuating = create(:spending_proposal, title: "Ongoing valuation")
    valuated = create(:spending_proposal, title: "Old idea", valuation_finished: true)
    valuating.valuators << @valuator
    valuated.valuators << @valuator

    visit valuation_spending_proposals_path(filter: 'valuation_open')

    expect(page).to have_content("Ongoing valuation")
    expect(page).to_not have_content("Old idea")

    visit valuation_spending_proposals_path(filter: 'valuating')

    expect(page).to have_content("Ongoing valuation")
    expect(page).to_not have_content("Old idea")

    visit valuation_spending_proposals_path(filter: 'valuation_finished')

    expect(page).to_not have_content("Ongoing valuation")
    expect(page).to have_content("Old idea")
  end

  feature 'Show' do
    scenario 'visible for assigned valuators' do
      administrator = create(:administrator, user: create(:user, username: 'Ana', email: 'ana@admins.org'))
      valuator2 = create(:valuator, user: create(:user, username: 'Rick', email: 'rick@valuators.org'))
      spending_proposal = create(:spending_proposal,
                                  geozone: create(:geozone),
                                  association_name: 'People of the neighbourhood',
                                  price: 1234,
                                  feasible: false,
                                  feasible_explanation: 'It is impossible',
                                  administrator: administrator)
      spending_proposal.valuators << [@valuator, valuator2]

      visit valuation_spending_proposals_path

      click_link spending_proposal.title

      expect(page).to have_content(spending_proposal.title)
      expect(page).to have_content(spending_proposal.description)
      expect(page).to have_content(spending_proposal.author.name)
      expect(page).to have_content(spending_proposal.association_name)
      expect(page).to have_content(spending_proposal.geozone.name)
      expect(page).to have_content('1234')
      expect(page).to have_content('Not feasible')
      expect(page).to have_content('It is impossible')
      expect(page).to have_content('Ana (ana@admins.org)')

      within('#assigned_valuators') do
        expect(page).to have_content('Rachel (rachel@valuators.org)')
        expect(page).to have_content('Rick (rick@valuators.org)')
      end
    end

    scenario 'visible for admins' do
      logout
      login_as create(:administrator).user

      administrator = create(:administrator, user: create(:user, username: 'Ana', email: 'ana@admins.org'))
      valuator2 = create(:valuator, user: create(:user, username: 'Rick', email: 'rick@valuators.org'))
      spending_proposal = create(:spending_proposal,
                                  geozone: create(:geozone),
                                  association_name: 'People of the neighbourhood',
                                  price: 1234,
                                  feasible: false,
                                  feasible_explanation: 'It is impossible',
                                  administrator: administrator)
      spending_proposal.valuators << [@valuator, valuator2]

      visit valuation_spending_proposal_path(spending_proposal)

      expect(page).to have_content(spending_proposal.title)
      expect(page).to have_content(spending_proposal.description)
      expect(page).to have_content(spending_proposal.author.name)
      expect(page).to have_content(spending_proposal.association_name)
      expect(page).to have_content(spending_proposal.geozone.name)
      expect(page).to have_content('1234')
      expect(page).to have_content('Not feasible')
      expect(page).to have_content('It is impossible')
      expect(page).to have_content('Ana (ana@admins.org)')

      within('#assigned_valuators') do
        expect(page).to have_content('Rachel (rachel@valuators.org)')
        expect(page).to have_content('Rick (rick@valuators.org)')
      end
    end

    scenario 'not visible for not assigned valuators' do
      logout
      login_as create(:valuator).user

      administrator = create(:administrator, user: create(:user, username: 'Ana', email: 'ana@admins.org'))
      valuator2 = create(:valuator, user: create(:user, username: 'Rick', email: 'rick@valuators.org'))
      spending_proposal = create(:spending_proposal,
                                  geozone: create(:geozone),
                                  association_name: 'People of the neighbourhood',
                                  price: 1234,
                                  feasible: false,
                                  feasible_explanation: 'It is impossible',
                                  administrator: administrator)
      spending_proposal.valuators << [@valuator, valuator2]

      expect { visit valuation_spending_proposal_path(spending_proposal) }.to raise_error "Not Found"
    end

  end

  feature 'Valuate' do
    background do
      @spending_proposal = create(:spending_proposal,
                                geozone: create(:geozone),
                                administrator: create(:administrator))
      @spending_proposal.valuators << @valuator
    end

    scenario 'Dossier empty by default' do
      visit valuation_spending_proposals_path
      click_link @spending_proposal.title

      within('#price') { expect(page).to have_content('Undefined') }
      within('#price_first_year') { expect(page).to have_content('Undefined') }
      within('#time_scope') { expect(page).to have_content('Undefined') }
      within('#feasibility') { expect(page).to have_content('Undefined') }
      expect(page).to_not have_content('Valuation finished')
      expect(page).to_not have_content('Internal comments')
    end

    scenario 'Edit dossier' do
      visit valuation_spending_proposals_path
      within("#spending_proposal_#{@spending_proposal.id}") do
        click_link "Edit"
      end

      fill_in 'spending_proposal_price', with: '12345'
      fill_in 'spending_proposal_price_first_year', with: '9876'
      fill_in 'spending_proposal_price_explanation', with: 'Very cheap idea'
      choose  'spending_proposal_feasible_true'
      fill_in 'spending_proposal_feasible_explanation', with: 'Everything is legal and easy to do'
      fill_in 'spending_proposal_time_scope', with: '19 months'
      fill_in 'spending_proposal_internal_comments', with: 'Should be double checked by the urbanism area'
      click_button 'Save changes'

      expect(page).to have_content "Dossier updated"

      visit valuation_spending_proposals_path
      click_link @spending_proposal.title

      within('#price') { expect(page).to have_content('12345') }
      within('#price_first_year') { expect(page).to have_content('9876') }
      expect(page).to have_content('Very cheap idea')
      within('#time_scope') { expect(page).to have_content('19 months') }
      within('#feasibility') { expect(page).to have_content('Feasible') }
      expect(page).to_not have_content('Valuation finished')
      expect(page).to have_content('Internal comments')
      expect(page).to have_content('Should be double checked by the urbanism area')
    end

    scenario 'Feasibility can be marked as pending' do
      visit valuation_spending_proposal_path(@spending_proposal)
      click_link 'Edit dossier'

      expect(find "#spending_proposal_feasible_nil").to be_checked
      choose 'spending_proposal_feasible_true'
      click_button 'Save changes'

      visit edit_valuation_spending_proposal_path(@spending_proposal)
      expect(find "#spending_proposal_feasible_nil").to_not be_checked
      expect(find "#spending_proposal_feasible_true").to be_checked

      choose 'spending_proposal_feasible_nil'
      click_button 'Save changes'

      visit edit_valuation_spending_proposal_path(@spending_proposal)
      expect(find "#spending_proposal_feasible_nil").to be_checked
    end

    scenario 'Feasibility selection makes proper fields visible', :js do
      feasible_true_fields  = ['Price (€)','Cost during the first year (€)','Price explanation','Time scope']
      feasible_false_fields = ['Feasibility explanation']
      feasible_any_fields   = ['Valuation finished','Internal comments']
      feasible_nil_fields   = feasible_true_fields + feasible_false_fields + feasible_any_fields

      visit edit_valuation_spending_proposal_path(@spending_proposal)

      expect(find "#spending_proposal_feasible_nil").to be_checked

      feasible_nil_fields.each do |field|
        expect(page).to have_content(field)
      end

      choose 'spending_proposal_feasible_true'

      feasible_false_fields.each do |field|
        expect(page).to_not have_content(field)
      end

      (feasible_true_fields + feasible_any_fields).each do |field|
        expect(page).to have_content(field)
      end

      choose 'spending_proposal_feasible_false'

      feasible_true_fields.each do |field|
        expect(page).to_not have_content(field)
      end

      (feasible_false_fields + feasible_any_fields).each do |field|
        expect(page).to have_content(field)
      end

      click_button 'Save changes'

      visit edit_valuation_spending_proposal_path(@spending_proposal)

      expect(find "#spending_proposal_feasible_false").to be_checked
      feasible_true_fields.each do |field|
        expect(page).to_not have_content(field)
      end

      (feasible_false_fields + feasible_any_fields).each do |field|
        expect(page).to have_content(field)
      end

      choose 'spending_proposal_feasible_nil'

      feasible_nil_fields.each do |field|
        expect(page).to have_content(field)
      end
    end

    scenario 'Finish valuation' do
      visit valuation_spending_proposal_path(@spending_proposal)
      click_link 'Edit dossier'

      check 'spending_proposal_valuation_finished'
      click_button 'Save changes'

      visit valuation_spending_proposals_path
      expect(page).to_not have_content @spending_proposal.title
      click_link 'Valuation finished'

      expect(page).to have_content @spending_proposal.title
      click_link @spending_proposal.title
      expect(page).to have_content('Valuation finished')
    end

    scenario 'Validates price formats' do
      visit valuation_spending_proposals_path
      within("#spending_proposal_#{@spending_proposal.id}") do
        click_link "Edit"
      end

      fill_in 'spending_proposal_price', with: '12345,98'
      fill_in 'spending_proposal_price_first_year', with: '9876.6'
      click_button 'Save changes'

      expect(page).to have_content('2 errors')
      expect(page).to have_content('Only integer numbers', count: 2)
    end
  end

  context "Summary" do

    background do
      admin = create(:administrator)
      login_as(admin.user)
    end

    scenario "Summary table" do
      scarlett  = create(:valuator)
      john = create(:valuator)

      finished_and_feasible1 = create(:spending_proposal, valuation_finished: true, feasible: true, price: '3000000')
      finished_and_feasible2 = create(:spending_proposal, valuation_finished: true, feasible: true, price: '7000000')

      finished_and_unfeasible1 = create(:spending_proposal, valuation_finished: true, feasible: false)
      finished_and_unfeasible2 = create(:spending_proposal, valuation_finished: true, feasible: false)

      in_evaluation1 = create(:spending_proposal, feasible: true, valuation_finished: false)
      in_evaluation2 = create(:spending_proposal, feasible: true, valuation_finished: false)

      finished_and_feasible1.valuators << scarlett
      finished_and_feasible2.valuators << scarlett

      finished_and_unfeasible1.valuators << john
      finished_and_unfeasible2.valuators << john

      in_evaluation1.valuators << scarlett
      in_evaluation2.valuators << john

      visit admin_spending_proposals_path

      click_link "Valuator summary"

      expect(page).to have_content "Valuator summary for investment projects"

      within("#valuator_#{scarlett.id}") do
        expect(page).to have_css(".finished-and-feasible-count", text: '2')
        expect(page).to have_css(".finished-and-unfeasible-count", text: '0')
        expect(page).to have_css(".finished-count", text: '2')
        expect(page).to have_css(".in-evaluation-count", text: '1')
        expect(page).to have_css(".total-count", text: '3')
        expect(page).to have_css(".total-price", text: "$10,000,000.00")
      end

      within("#valuator_#{john.id}") do
        expect(page).to have_css(".finished-and-feasible-count", text: '0')
        expect(page).to have_css(".finished-and-unfeasible-count", text: '2')
        expect(page).to have_css(".finished-count", text: '2')
        expect(page).to have_css(".in-evaluation-count", text: '1')
        expect(page).to have_css(".total-count", text: '3')
        expect(page).to have_css(".total-price", text: '$0.00')
      end
    end

    scenario "Order by investment project count" do
      isabel = create(:valuator)
      john = create(:valuator)
      scarlett  = create(:valuator)

      3.times { create(:spending_proposal, valuators: [scarlett])}
      1.times { create(:spending_proposal, valuators: [john])}
      2.times { create(:spending_proposal, valuators: [isabel])}

      visit admin_spending_proposals_path
      click_link "Valuator summary"

      expect(scarlett.email).to appear_before(isabel.email)
      expect(isabel.email).to appear_before(john.email)
    end

    scenario "Back link" do
      visit admin_spending_proposals_path

      click_link "Valuator summary"
      expect(page).to have_content "Valuator summary for investment projects"

      click_link "Go back"
      expect(page).to have_content "Investment projects for participatory budgeting"
    end

  end
end
