const addDays = require('date-fns/addDays');
const Helper = require('./fq-helper');
const data = require('./fq-helper-test-data');

describe('hasErrorUA', () => {
  it('should find no error in form question - TextBox', () => {
    const answer = 'test';

    expect(Helper.hasError(data.inputQuestion, answer)).toBeFalsy();
  });

  it('should validate email input type question', () => {
    const answer = 'test@ucdavis';

    expect(Helper.hasError(data.inputEmailQuestion, answer)).toBeTruthy();
  });

  test.each`
    answer    | expected
    ${100}    | ${false}
    ${-100}   | ${false}
    ${'abc'}  | ${true}
    ${'abc1'} | ${true}
    ${'@'}    | ${true}
    ${'@1'}   | ${true}
  `('given input number question and $answer then hasError is: $expected', ({ answer, expected }) => {
    expect(Helper.hasError(data.inputNumberQuestion, answer)).toBe(expected);
  });

  test.each`
    min          | max          | answer | expected
    ${0}         | ${100}       | ${0}   | ${false}
    ${0}         | ${100}       | ${50}  | ${false}
    ${0}         | ${100}       | ${100} | ${false}
    ${undefined} | ${undefined} | ${101} | ${false}
    ${undefined} | ${undefined} | ${-1}  | ${false}
    ${0}         | ${100}       | ${-1}  | ${true}
    ${0}         | ${undefined} | ${-1}  | ${true}
    ${0}         | ${100}       | ${101} | ${true}
    ${undefined} | ${100}       | ${101} | ${true}
  `('given min: $min and max: $max and $answer then hasError is: $expected', ({ min, max, answer, expected }) => {
    const question = {
      ...data.inputNumberQuestion,
      inputProps: {
        type: 'number',
        min,
        max,
      },
    };
    expect(Helper.hasError(question, answer)).toBe(expected);
  });

  it('should validate datepicker type question', () => {
    const answer = '01/01/2021';

    expect(Helper.hasError(data.datepickerQuestion, answer)).toBeFalsy();
  });

  it('should validate datepicker type question with future date', () => {
    const answer = addDays(new Date(), 5);

    expect(Helper.hasError(data.datepickerQuestion, answer)).toBeTruthy();
  });

  it('should validate datepicker type question with past date', () => {
    const question = {
      ...data.datepickerQuestion,
      disableFuture: false,
      disablePast: true,
    };

    const answer = addDays(new Date(), -1);

    expect(Helper.hasError(question, answer)).toBeTruthy();
  });

  it('should validate datepicker type question with minDate', () => {
    const question = {
      ...data.datepickerQuestion,
      disableFuture: false,
      minDate: '06/01/2021',
    };

    const answer = '05/01/2021';

    expect(Helper.hasError(question, answer)).toBeTruthy();
  });

  it('should validate datepicker type question with maxDate', () => {
    const question = {
      ...data.datepickerQuestion,
      disableFuture: false,
      maxDate: '06/01/2021',
    };

    const answer = '07/01/2021';

    expect(Helper.hasError(question, answer)).toBeTruthy();
  });

  it('should validate datepicker type question', () => {
    const answer = '01/01/2021';

    expect(Helper.hasError(data.datepickerQuestion, answer)).toBeFalsy();
  });

  it('should find error in form question - datepicker', () => {
    const answer = 'its jan 1st 2021';

    expect(Helper.hasError(data.datepickerQuestion, answer)).toBeTruthy();
  });

  it('should validate datepicker type question with maxDate', () => {
    const answer = {
      duration: {
        requestStart: null,
        requestEnd: '12/31/2021',
      },
    };

    expect(Helper.hasError(data.datepickerGroupQuestions, answer)).toBeFalsy();
  });

  it('should validate datepicker type question with minDate', () => {
    const answer = {
      duration: {
        requestStart: '01/01/2021',
        requestEnd: null,
      },
    };

    expect(Helper.hasError(data.datepickerGroupQuestions, answer)).toBeFalsy();
  });

  it('should validate datepicker type question with date range', () => {
    const answer = {
      duration: {
        requestStart: '01/01/2021',
        requestEnd: '12/31/2021',
      },
    };

    expect(Helper.hasError(data.datepickerGroupQuestions, answer)).toBeFalsy();
  });

  it('should find error in form question when date is out of the range', () => {
    const answer = {
      duration: {
        requestStart: '10/01/2021',
        requestEnd: '09/31/2021',
      },
    };

    expect(Helper.hasError(data.datepickerGroupQuestions, answer)).toBeFalsy();
  });

  it('should validate datepicker type question with date range being same date', () => {
    const answer = {
      duration: {
        requestStart: '01/01/2021',
        requestEnd: '01/01/2021',
      },
    };

    expect(Helper.hasError(data.datepickerGroupQuestions, answer)).toBeFalsy();
  });

  it('should find error in form question - TextBox', () => {
    const answer = '';

    expect(Helper.hasError(data.inputQuestion, answer)).toBeTruthy();
  });

  it('should find no error in form question - TextArea', () => {
    const answer = { project_summary: 'testing with some longer data' };

    expect(Helper.hasError(data.textAreaQuestion, answer)).toBeFalsy();
  });

  it('should find no error in form question - checkBox', () => {
    const answer = [
      {
        label: 'Whole plants',
        value: 'Whole_plants',
      },
    ];

    expect(Helper.hasError(data.checkboxQuestion, answer)).toBeFalsy();
  });

  it('should find error in form question - checkBox', () => {
    const answer = {
      rDNA_or_pathogens: [],
    };

    expect(Helper.hasError(data.checkboxQuestion, answer)).toBeTruthy();
  });

  it('should find no error in form question - Radio', () => {
    const answer = {
      permit_required: 'Yes',
    };
    expect(Helper.hasError(data.radioQuestion, answer)).toBeFalsy();
  });

  it('should find no error in form question - dropdown', () => {
    const answer = {
      biological_safety_level: [
        {
          label: 'BSL-1',
          value: 'BSL-1',
        },
      ],
    };

    expect(Helper.hasError(data.dropdownQuestion, answer)).toBeFalsy();
  });

  it('should find no error in form GroupQuestion', () => {
    const answer = {
      project_overview: {
        project_title: 'test',
        rDNA_or_pathogens: [
          {
            label: 'Whole plants',
            value: 'Whole_plants',
          },
        ],
      },
    };

    expect(Helper.hasError(data.groupQuestion, answer)).toBeTruthy();
  });

  it('should find no error in form question - with followup and no dependent required', () => {
    const answer = {
      personnel_followup: {
        edit_bua_on_behalf_of_pi: 'No',
        person_working_with: [
          {
            label: 'Bloodborne pathogen',
            value: 'Bloodborne_pathogen',
          },
        ],
      },
    };

    expect(Helper.hasError(data.peopleGroup, answer)).toBeFalsy();
  });

  it('should find error in form question - with followup and dependent undefined', () => {
    const answer = {
      personnel: {
        personnel_authorized_to_work: {
          personnel_followup: {
            edit_bua_on_behalf_of_pi: 'Yes',
            person_working_with: [
              {
                label: 'Bloodborne pathogen',
                value: 'Bloodborne_pathogen',
              },
            ],
          },
        },
      },
    };

    expect(Helper.hasError(data.peopleGroup, answer)).toBeTruthy();
  });

  it('should find error in form question -  when people/location/agent Array[0]', () => {
    const answer = {
      personnel: {
        personnel_authorized_to_work: [],
      },
    };

    expect(Helper.hasError(data.peopleGroup, answer)).toBeTruthy();
  });

  it('should find no error in form question -  with followup and dependent Questions answered.', () => {
    const answer = {
      personnel_followup: {
        edit_bua_on_behalf_of_pi: 'Yes',
        edit_bua_on_behalf_of_pi_yes: {
          contact_type: [
            {
              label: 'Lab',
              value: 'Lab',
            },
          ],
        },
        person_working_with: [
          {
            label: 'Bloodborne pathogen',
            value: 'Bloodborne_pathogen',
          },
        ],
      },
    };

    expect(Helper.hasError(data.peopleGroup, answer)).toBeFalsy();
  });

  it('should validate second level nested question for the child of multiple parent questions ', () => {
    expect(Helper.hasError(data.deeplynestedQuestion, data.requiredthSecondLevelNestedAnswer)).toBeTruthy();
  });

  it('should validate third level nested questions for the child of multiple parent questions ', () => {
    expect(Helper.hasError(data.deeplynestedQuestion, data.requiredThirdLevelNestedAnswer)).toBeTruthy();
  });

  it('should validate multiple nested questions for the child of multiple parent questions ', () => {
    expect(Helper.hasError(data.deeplynestedQuestion, data.sharedParentSecondAndThirdLevelAnswer)).toBeFalsy();
  });

  it('should validate required nested questions if and only if required parent questions are selected', () => {
    const minimumRequiredAnswer = {
      cell_lines: {
        source_organism: 'Invertebrates_source_organism',
        provider_of_materials: 'first level nested required answer',
        will_this_cell_line_be_used_or_put_in_storage_only: 'storage_only',
      },
    };
    expect(Helper.hasError(data.deeplynestedQuestion, minimumRequiredAnswer)).toBeFalsy();
  });

  it('should validate nested textbox questions for the child of multiple parent questions ', () => {
    expect(Helper.hasError(data.multpleNestedQuestionWithSharedParents, data.nestedRequiredAnswerTextBox)).toBeTruthy();
  });

  it('should validate checkbox nested questions for the child of multiple parent questions ', () => {
    expect(
      Helper.hasError(data.multpleNestedQuestionWithSharedParents, data.nestedRequiredAnswerCheckBoxes),
    ).toBeTruthy();
  });

  it('should validate nested questions for the child of multiple parent questions ', () => {
    expect(Helper.hasError(data.multpleNestedQuestionWithSharedParents, data.minimumNestedRequiredAnswer)).toBeFalsy();
  });

  it('should check whether multiple answers that have matched parents with multiple value ', () => {
    expect(
      // eslint-disable-next-line
      Helper._multipleAnswersHaveMatchedParents(
        data.multipleAnswersHaveMatchedParentsQuestion,
        data.multipleAnswersHaveMatchedParentsAnswer,
      ),
    ).toBeTruthy();
  });

  it('should have at least one answer that have matched parents with multiple value ', () => {
    expect(
      // eslint-disable-next-line
      Helper.hasDependentError(
        data.multipleAnswersHaveMatchedParentsQuestion,
        data.multipleAnswersHaveMatchedParentsAnswerIncomplete,
      ),
    ).toBeTruthy();
  });

  it('should have at least one answer that have matched parents with multiple value ', () => {
    expect(
      // eslint-disable-next-line
      Helper.hasDependentError(
        data.multipleAnswersHaveMatchedParentsQuestion,
        data.multipleAnswersHaveMatchedParentsAnswer,
      ),
    ).toBeFalsy();
  });

  it('should validate multiple answer that have matched parents with multiple value ', () => {
    expect(
      // eslint-disable-next-line
      Helper.hasDependentError(
        data.multipleAnswersHaveMatchedParentsQuestion,
        data.multipleAnswersHaveMatchedParentsAnswerComplete,
      ),
    ).toBeFalsy();
  });

  it('should check whether multiple answers that have matched parents with multiple value ', () => {
    expect(
      // eslint-disable-next-line
      Helper._multipleAnswersHaveMatchedParents(
        data.multipleAnswersHaveMatchedParentsQuestion,
        data.multipleAnswersHaveMatchedParentsAnswer,
      ),
    ).toBeTruthy();
  });

  it('should check whether parent value is a single value that matched the answer', () => {
    expect(
      // eslint-disable-next-line
      Helper._answerHasMatchedParent(data.answerHasMatchedParentQuestion, data.answerHasMatchedParentAnswer),
    ).toBeTruthy();
  });

  it('should check when parent value is not a single value that matched the answer', () => {
    expect(
      // eslint-disable-next-line
      Helper._answerHasMatchedParent(
        data.multipleAnswersHaveMatchedParentsQuestion,
        data.multipleAnswersHaveMatchedParentsAnswer,
      ),
    ).toBeFalsy();
  });

  it('should check single answer has a matched parnts value', () => {
    expect(
      // eslint-disable-next-line
      Helper._singleAnswerHasMatchedParnts(
        data.singleAnswerHasMatchedParntsQuestion,
        data.singleAnswerHasMatchedParntsAnswer,
      ),
    ).toBeTruthy();
  });

  it('should validate every responses of addanother question type', () => {
    expect(Helper.hasAddAnotherError(data.addAnotherQuestion, data.addAnotherAnswerValid)).toBeFalsy();
  });

  it('should validate against incomplete responses in each of addanother question type', () => {
    expect(Helper.hasAddAnotherError(data.addAnotherQuestion, data.addAnotherAnswerSomeIncomplete)).toBeTruthy();
  });

  it('should validate against invalid responses in each question within addanother question type', () => {
    expect(Helper.hasAddAnotherError(data.addAnotherQuestion, data.addAnotherAnswerSomeInvalid)).toBeTruthy();
  });

  it('should validate against partial incomplete responses within addanother question type', () => {
    expect(Helper.hasAddAnotherError(data.addAnotherQuestion, data.addAnotherAnswerPartialIncomplete)).toBeTruthy();
  });

  it('should validate against followup question for BIOLOGICAL library type', () => {
    expect(Helper.hasFollowUpError(data.libraryTypeQuestion, data.libraryTypeAnswer)).toBeFalsy();
  });
  it('should validate against followup question for BIOLOGICAL library type incomplete answer', () => {
    expect(Helper.hasFollowUpError(data.libraryTypeQuestion, data.libraryTypeIncompleteAnswer)).toBeTruthy();
  });
  it('should validate against librarytype question for BIOLOGICAL library type', () => {
    expect(Helper.hasLibraryError(data.libraryTypeQuestion, [])).toBeTruthy();
  });
  it('should validate against librarytype question for BIOLOGICAL library type', () => {
    expect(Helper.hasLibraryError(data.libraryTypeQuestion, data.libraryTypeIncompleteAnswer)).toBeTruthy();
  });

  it('should set default value to response when value is missing', () => {
    const questions = [
      data.textAreaQuestion,
      {
        ...data.checkboxQuestion,
        defaultValue: 'Seed',
      },
    ];
    const responses = { project_summary: 'test' };
    const expected = { project_summary: 'test', rDNA_or_pathogens: 'Seed' };
    expect(Helper.setDefaultValueToResponses(responses, questions)).toStrictEqual(expected);
  });

  it('should not set default value to response when value is exist', () => {
    const questions = [
      data.textAreaQuestion,
      {
        ...data.checkboxQuestion,
        defaultValue: 'Seed',
      },
    ];
    const responses = { project_summary: 'test', rDNA_or_pathogens: 'Whole_plants' };
    const expected = { project_summary: 'test', rDNA_or_pathogens: 'Whole_plants' };
    expect(Helper.setDefaultValueToResponses(responses, questions)).toStrictEqual(expected);
  });

  it('should set default value to response when response is null or undefined', () => {
    const questions = [
      data.textAreaQuestion,
      {
        ...data.checkboxQuestion,
        defaultValue: 'Seed',
      },
    ];
    const responses = null;
    const expected = { rDNA_or_pathogens: 'Seed' };
    expect(Helper.setDefaultValueToResponses(responses, questions)).toStrictEqual(expected);
  });

  it('should return error when exceed the number from maxNumberKey', () => {
    const responses = {
      pesticideUse: {
        plantAmt: 145,
        acresOrUnitsTreated: 150,
      },
    };
    expect(Helper.isFormValid(data.numberGroupQuestions, responses)).toBeFalsy();
  });

  it('should return success when exceed the number from maxNumberKey', () => {
    const responses = {
      pesticideUse: {
        plantAmt: 145,
        acresOrUnitsTreated: 140,
      },
    };
    expect(Helper.isFormValid(data.numberGroupQuestions, responses)).toBeTruthy();
  });

  it('should return error when exceed the number from minNumber', () => {
    const responses = {
      pesticideUse: {
        plantAmt: 145,
        acresOrUnitsTreated: 5,
      },
    };
    expect(Helper.isFormValid(data.numberGroupQuestions, responses)).toBeFalsy();
  });

  it('should return success when exceed the number from minNumber', () => {
    const responses = {
      pesticideUse: {
        plantAmt: 145,
        acresOrUnitsTreated: 20,
      },
    };
    expect(Helper.isFormValid(data.numberGroupQuestions, responses)).toBeTruthy();
  });

  it('should validate add-another question in group question', () => {
    const responses = {
      notifyOthers: {
        notify: 'Yes',
        details: {
          recipients: [
            {
              _id: '5e8f8f8f8f8f8f8f8f8f8f8',
              item: {
                email: 'test@rss.com',
              },
            },
          ],
          comments: 'test comments',
        },
      },
    };
    expect(Helper.isFormValid([data.addAnotherGroupQuestion], responses)).toBeTruthy();
  });

  it('should validate recipients question', () => {
    const responses = {
      recipients: [{ email: 'test@rss.com' }],
    };
    expect(Helper.isFormValid([data.recipientsQuestion], responses)).toBeTruthy();
  });
});
