require 'rails_helper'

describe Dunlop::OverdueHandling do
  before do
    subject.define do
      when_workflow_step :contractor_initialization, is: 2.days, from: {owner_initialization: :plan_date}
    end
  end

  describe ".handle_overdue!" do
    it "sets to overdue when needed" do
      workflow_instance_1 = create :workflow_instance_scenario1
      workflow_instance_1.owner_initialization.update_columns(plan_date: 3.days.ago.to_date)

      subject.handle_overdue!

      workflow_instance_1.reload.should be_overdue
      workflow_instance_1.contractor_initialization.should be_overdue
    end

    it "sets to overdue when needed" do
      workflow_instance_2 = create :workflow_instance_scenario1
      workflow_instance_2.owner_initialization.update_columns(plan_date: 1.day.ago.to_date)

      subject.handle_overdue!

      workflow_instance_2.reload.should_not be_overdue
      workflow_instance_2.contractor_initialization.should_not be_overdue
    end

    it "sets to overdue when needed" do
      workflow_instance_3 = create :workflow_instance_scenario1
      workflow_instance_3.owner_initialization.update_columns(plan_date: 5.days.from_now.to_date)

      subject.handle_overdue!

      workflow_instance_3.reload.should_not be_overdue
      workflow_instance_3.contractor_initialization.should_not be_overdue
    end

    it "sets to overdue when needed" do
      # exact match, also overdue
      workflow_instance_4 = create :workflow_instance_scenario1
      workflow_instance_4.owner_initialization.update_columns(plan_date: 2.days.ago.to_date)

      subject.handle_overdue!

      # exact match, also overdue
      workflow_instance_4.reload.should be_overdue
      workflow_instance_4.contractor_initialization.should be_overdue
    end

    it "sets to overdue when needed" do
      # completed overdue times are ignored of course
      workflow_instance_5 = create :workflow_instance_scenario1, :all_completed
      workflow_instance_5.owner_initialization.update_columns(plan_date: 20.days.ago.to_date)

      subject.handle_overdue!

      workflow_instance_5.reload.should be_all_completed
      workflow_instance_5.contractor_initialization.should be_completed
    end

    it "sets to overdue when needed" do
      workflow_instance_6 = create :workflow_instance_scenario1
      workflow_instance_6.owner_initialization.update_columns(plan_date: 20.days.ago.to_date)
      workflow_instance_6.owner_initialization.reject!

      subject.handle_overdue!

      # any_rejected wins over overdue for overal workflow_instance state
      workflow_instance_6.reload.should be_any_rejected
      workflow_instance_6.contractor_initialization.should be_overdue
    end
  end

  describe "changing the date specified as target in the configuration" do
    it "sets to overdue when date change creates overdue situation" do
      workflow_instance = create :workflow_instance_scenario1, :overdue
      workflow_instance.owner_initialization.update_columns(plan_date: 1.day.ago.to_date)

      # Trigger the callbacks
      workflow_instance.owner_initialization.update plan_date: 3.days.ago.to_date

      reload_model workflow_instance

      workflow_instance.contractor_initialization.should be_overdue
      workflow_instance.should be_overdue
    end

    it "removes overdue when the date is no longer overdue" do
      workflow_instance = create :workflow_instance_scenario1, :overdue
      workflow_instance.owner_initialization.update_columns(plan_date: 3.days.ago.to_date)
      workflow_instance.contractor_initialization.update_columns(state: 'overdue')

      # Trigger the callbacks
      workflow_instance.owner_initialization.update plan_date: 1.day.ago.to_date

      reload_model workflow_instance

      workflow_instance.contractor_initialization.should be_processing
      workflow_instance.should be_active
    end

    it "removes overdue when the date is removed" do
      workflow_instance = create :workflow_instance_scenario1, :overdue
      workflow_instance.owner_initialization.update_columns(plan_date: 3.days.ago.to_date)
      workflow_instance.contractor_initialization.update_columns(state: 'overdue')

      # Trigger the callbacks
      workflow_instance.owner_initialization.update plan_date: nil

      reload_model workflow_instance

      workflow_instance.contractor_initialization.should be_processing
      workflow_instance.should be_active
    end

    it "does not set rejected records to overdue" do
      workflow_instance = create :workflow_instance_scenario1, :overdue
      workflow_instance.owner_initialization.update_columns(plan_date: 1.day.ago.to_date)
      workflow_instance.contractor_initialization.reject!

      # Trigger the callbacks
      workflow_instance.owner_initialization.update plan_date: 3.days.ago.to_date

      reload_model workflow_instance

      workflow_instance.contractor_initialization.should be_rejected
      workflow_instance.should be_any_rejected
    end

    it "does not set completed records to overdue" do
      workflow_instance = create :workflow_instance_scenario1, :overdue
      workflow_instance.owner_initialization.update_columns(plan_date: 1.day.ago.to_date)
      workflow_instance.contractor_initialization.complete!

      # Trigger the callbacks
      workflow_instance.owner_initialization.update plan_date: 3.days.ago.to_date

      reload_model workflow_instance

      workflow_instance.contractor_initialization.should be_completed
      workflow_instance.should be_active
    end
  end

  describe "completing an overdue workflow step" do
    it "activates the workflow instance from overdue state when the overdue workflow step is completed" do
      workflow_instance = create :workflow_instance_scenario1, :overdue
      workflow_instance.reload.should be_overdue
      workflow_instance.owner_initialization.should be_pending
      workflow_instance.contractor_initialization.should be_overdue
      workflow_instance.contractor_initialization.complete!

      workflow_instance.reload.should be_active
    end

    it "rejects the workflow instance from overdue state when the overdue workflow step is completed" do
      workflow_instance = create :workflow_instance_scenario1, :overdue
      workflow_instance.contractor_initialization.reject!

      workflow_instance.reload.should be_any_rejected
    end
  end
end
