require "rails_helper"

RSpec.describe Validations::TenancyValidations do
  subject(:tenancy_validator) { validator_class.new }

  before do
    Timecop.freeze(Time.zone.local(2021, 5, 1))
  end

  after do
    Timecop.unfreeze
  end

  let(:validator_class) { Class.new { include Validations::TenancyValidations } }
  let(:record) { FactoryBot.create(:lettings_log, startdate: Time.zone.local(2021, 5, 1), needstype: 1, rent_type: 1) }

  describe "fixed term tenancy validations" do
    context "when fixed term tenancy" do
      context "when type of tenancy is not assured or assured shorthold" do
        let(:expected_error) { I18n.t("validations.tenancy.length.fixed_term_not_required") }

        it "tenancy length should not be present" do
          record.tenancy = 3
          record.tenancylength = 10
          tenancy_validator.validate_fixed_term_tenancy(record)
          expect(record.errors["needstype"]).to include(match(expected_error))
          expect(record.errors["rent_type"]).not_to include(match(expected_error))
          expect(record.errors["tenancylength"]).to include(match(expected_error))
          expect(record.errors["tenancy"]).to include(match(expected_error))
        end
      end

      context "when type of tenancy is assured shorthold" do
        let(:expected_error) do
          I18n.t(
            "validations.tenancy.length.shorthold",
            min_tenancy_length: 2,
          )
        end

        before { record.tenancy = 4 }

        context "when tenancy length is less than 2" do
          it "adds an error" do
            record.tenancylength = 1
            tenancy_validator.validate_fixed_term_tenancy(record)
            expect(record.errors["needstype"]).to include(match(expected_error))
            expect(record.errors["rent_type"]).to include(match(expected_error))
            expect(record.errors["tenancylength"]).to include(match(expected_error))
            expect(record.errors["tenancy"]).to include(match(expected_error))
          end
        end

        context "when tenancy length is greater than 99" do
          it "adds an error" do
            record.tenancylength = 100
            tenancy_validator.validate_fixed_term_tenancy(record)
            expect(record.errors["needstype"]).to include(match(expected_error))
            expect(record.errors["rent_type"]).to include(match(expected_error))
            expect(record.errors["tenancylength"]).to include(match(expected_error))
            expect(record.errors["tenancy"]).to include(match(expected_error))
          end
        end

        context "when tenancy length is between 2-99" do
          it "does not add an error" do
            record.tenancylength = 3
            tenancy_validator.validate_fixed_term_tenancy(record)
            expect(record.errors).to be_empty
          end
        end

        context "when tenancy length has not been answered" do
          it "does not add an error" do
            record.tenancylength = nil
            tenancy_validator.validate_fixed_term_tenancy(record)
            expect(record.errors).to be_empty
          end
        end
      end

      context "when the collection start year is before 2022" do
        context "when type of tenancy is secure" do
          let(:expected_error) do
            I18n.t(
              "validations.tenancy.length.secure",
              min_tenancy_length: 2,
            )
          end

          before { record.tenancy = 1 }

          context "when tenancy length is less than 2" do
            it "adds an error" do
              record.tenancylength = 1
              tenancy_validator.validate_fixed_term_tenancy(record)
              expect(record.errors["needstype"]).to include(match(expected_error))
              expect(record.errors["tenancylength"]).to include(match(expected_error))
              expect(record.errors["tenancy"]).to include(match(expected_error))
            end
          end

          context "when tenancy length is greater than 99" do
            it "adds an error" do
              record.tenancylength = 100
              tenancy_validator.validate_fixed_term_tenancy(record)
              expect(record.errors["needstype"]).to include(match(expected_error))
              expect(record.errors["tenancylength"]).to include(match(expected_error))
              expect(record.errors["tenancy"]).to include(match(expected_error))
            end
          end

          context "when tenancy length is between 2-99" do
            it "does not add an error" do
              record.tenancylength = 3
              tenancy_validator.validate_fixed_term_tenancy(record)
              expect(record.errors).to be_empty
            end
          end

          context "when tenancy length has not been answered" do
            it "does not add an error" do
              record.tenancylength = nil
              tenancy_validator.validate_fixed_term_tenancy(record)
              expect(record.errors).to be_empty
            end
          end
        end
      end

      context "when the collection start year is 2022 or later" do
        before do
          Timecop.freeze(2022, 5, 1)
        end

        after do
          Timecop.unfreeze
        end

        let(:record) { FactoryBot.create(:lettings_log, startdate: Time.zone.local(2022, 5, 1), needstype: 1, rent_type: 1) }

        context "when type of tenancy is Secure - fixed term" do
          let(:expected_error) do
            I18n.t(
              "validations.tenancy.length.secure",
              min_tenancy_length: 2,
            )
          end

          before { record.tenancy = 6 }

          context "when tenancy length is less than 2" do
            it "adds an error" do
              record.tenancylength = 1
              tenancy_validator.validate_fixed_term_tenancy(record)
              expect(record.errors["needstype"]).to include(match(expected_error))
              expect(record.errors["tenancylength"]).to include(match(expected_error))
              expect(record.errors["tenancy"]).to include(match(expected_error))
            end
          end

          context "when tenancy length is greater than 99" do
            it "adds an error" do
              record.tenancylength = 100
              tenancy_validator.validate_fixed_term_tenancy(record)
              expect(record.errors["needstype"]).to include(match(expected_error))
              expect(record.errors["tenancylength"]).to include(match(expected_error))
              expect(record.errors["tenancy"]).to include(match(expected_error))
            end
          end

          context "when tenancy length is between 2-99" do
            it "does not add an error" do
              record.tenancylength = 3
              tenancy_validator.validate_fixed_term_tenancy(record)
              expect(record.errors).to be_empty
            end
          end

          context "when tenancy length has not been answered" do
            it "does not add an error" do
              record.tenancylength = nil
              tenancy_validator.validate_fixed_term_tenancy(record)
              expect(record.errors).to be_empty
            end
          end
        end

        context "when type of tenancy is Secure - lifetime" do
          let(:expected_error) do
            I18n.t(
              "validations.tenancy.length.secure",
              min_tenancy_length: 2,
            )
          end

          before { record.tenancy = 7 }

          context "when tenancy length is less than 2" do
            it "adds an error" do
              record.tenancylength = 1
              tenancy_validator.validate_fixed_term_tenancy(record)
              expect(record.errors["needstype"]).to include(match(expected_error))
              expect(record.errors["tenancylength"]).to include(match(expected_error))
              expect(record.errors["tenancy"]).to include(match(expected_error))
            end
          end

          context "when tenancy length is greater than 99" do
            it "adds an error" do
              record.tenancylength = 100
              tenancy_validator.validate_fixed_term_tenancy(record)
              expect(record.errors["needstype"]).to include(match(expected_error))
              expect(record.errors["tenancylength"]).to include(match(expected_error))
              expect(record.errors["tenancy"]).to include(match(expected_error))
            end
          end

          context "when tenancy length is between 2-99" do
            it "does not add an error" do
              record.tenancylength = 3
              tenancy_validator.validate_fixed_term_tenancy(record)
              expect(record.errors).to be_empty
            end
          end

          context "when tenancy length has not been answered" do
            it "does not add an error" do
              record.tenancylength = nil
              tenancy_validator.validate_fixed_term_tenancy(record)
              expect(record.errors).to be_empty
            end
          end
        end
      end
    end
  end

  describe "tenancy type validations" do
    let(:field) { "validations.other_field_missing" }
    let(:main_field_label) { "tenancy type" }
    let(:other_field) { "tenancyother" }
    let(:other_field_label) { "other tenancy type" }
    let(:expected_error) { I18n.t(field, main_field_label:, other_field_label:) }

    context "when tenancy type is other" do
      before { record.tenancy = 3 }

      it "validates that other tenancy type is provided" do
        record.tenancyother = nil
        tenancy_validator.validate_other_tenancy_type(record)
        expect(record.errors[other_field]).to include(match(expected_error))
      end

      it "expects that other tenancy type is provided" do
        record.tenancyother = "Some other tenancy type"
        tenancy_validator.validate_other_tenancy_type(record)
        expect(record.errors[other_field]).to be_empty
      end
    end

    context "when tenancy type is not other" do
      let(:field) { "validations.other_field_not_required" }

      it "validates that other tenancy type is not provided" do
        record.tenancy = 2
        record.tenancyother = "Some other tenancy type"
        tenancy_validator.validate_other_tenancy_type(record)
        expect(record.errors[other_field]).to include(match(expected_error))
      end

      it "expects that other tenancy type is not provided" do
        record.tenancy = 1
        record.tenancyother = nil
        tenancy_validator.validate_other_tenancy_type(record)
        expect(record.errors[other_field]).to be_empty
      end
    end
  end

  describe "joint tenancy validation" do
    context "when the data inputter has said that there is only one member in the household" do
      before do
        Timecop.freeze(2022, 5, 1)
      end

      after do
        Timecop.unfreeze
      end

      let(:record) { FactoryBot.create(:lettings_log, startdate: Time.zone.local(2022, 5, 1)) }
      let(:expected_error) { I18n.t("validations.tenancy.not_joint") }
      let(:hhmemb_expected_error) { I18n.t("validations.tenancy.joint_more_than_one_member") }

      it "displays an error if the data inputter says the letting is a joint tenancy" do
        record.hhmemb = 1
        record.joint = 1
        tenancy_validator.validate_joint_tenancy(record)
        expect(record.errors["joint"]).to include(match(expected_error))
        expect(record.errors["hhmemb"]).to include(match(hhmemb_expected_error))
      end

      it "does not display an error if the data inputter says the letting is not a joint tenancy" do
        record.hhmemb = 1
        record.joint = 2
        tenancy_validator.validate_joint_tenancy(record)
        expect(record.errors["joint"]).to be_empty
        expect(record.errors["hhmemb"]).to be_empty
      end

      it "does not display an error if the data inputter has given the household members but not input if it is a joint tenancy" do
        record.hhmemb = 1
        record.joint = nil
        tenancy_validator.validate_joint_tenancy(record)
        expect(record.errors["joint"]).to be_empty
        expect(record.errors["hhmemb"]).to be_empty
      end

      it "does not error when don't know answer to joint" do
        record.hhmemb = 1
        record.joint = 3

        tenancy_validator.validate_joint_tenancy(record)

        expect(record.errors["joint"]).to be_empty
        expect(record.errors["hhmemb"]).to be_empty
      end
    end
  end
end