import { setNoPossibleAnswersPenalties } from '../utils/classes'
import { Question } from '../types/basicTypes'
import {
    noPossibleAnswerMatchPenalty,
    SearchResultQuestion,
} from '../utils/qdbUtils'

const matchPercent = 100

const questionWithNormalPossibleAnswers: Question = {
    Q: 'asd',
    A: 'asd',
    data: {
        type: 'simple',
        possibleAnswers: [
            { type: 'txt', val: 'rubber duck' },
            { type: 'txt', val: 'super laptop' },
            { type: 'txt', val: 'nothing in particular' },
            { type: 'txt', val: 'something giberish' },
        ],
    },
}

const questionWithNormalPossibleAnswersWithLabels: Question = {
    Q: 'asd',
    A: 'asd',
    data: {
        type: 'simple',
        possibleAnswers: [
            { type: 'txt', val: 'a) nothing in particular' },
            { type: 'txt', val: 'b) super laptop' },
            { type: 'txt', val: 'c) something giberish' },
            { type: 'txt', val: 'd) rubber duck' },
        ],
    },
}

const questionWithNormalPossibleAnswers2: Question = {
    Q: 'asd',
    A: 'asd',
    data: {
        type: 'simple',
        possibleAnswers: [
            { type: 'txt', val: 'rubber duck' },
            { type: 'txt', val: 'cat' },
            { type: 'txt', val: 'nothing in particular' },
            { type: 'txt', val: 'dog' },
        ],
    },
}

const questionWithNormalPossibleAnswers3: Question = {
    Q: 'asd',
    A: 'asd',
    data: {
        type: 'simple',
        possibleAnswers: [
            { type: 'txt', val: 'rubber duck 2' },
            { type: 'txt', val: 'whale' },
            { type: 'txt', val: 'nothing in particular 2' },
            { type: 'txt', val: 'sea lion' },
        ],
    },
}

const questionWithNormalPossibleAnswers4: Question = {
    Q: 'asd',
    A: 'asd',
    data: {
        type: 'simple',
        possibleAnswers: [
            { type: 'txt', val: 'rubber duck' },
            { type: 'txt', val: 'super laptop' },
        ],
    },
}

const questionWithSimilarPossibleAnswers: Question = {
    Q: 'asd',
    A: 'asd',
    data: {
        type: 'simple',
        possibleAnswers: [
            { type: 'txt', val: 'asd' },
            { type: 'txt', val: 'basd' },
            { type: 'txt', val: 'aaa' },
            { type: 'txt', val: 'bbb' },
        ],
    },
}

const questionWithTrueFalsePossibleAnser: Question = {
    Q: 'asd',
    A: 'asd',
    data: {
        type: 'simple',
        possibleAnswers: [
            { type: 'txt', val: 'true' },
            { type: 'txt', val: 'false' },
        ],
    },
}

const questionWithNoPossibleAnswer: Question = {
    Q: 'asd',
    A: 'asd',
    data: {
        type: 'simple',
    },
}

const resNormal: SearchResultQuestion = {
    q: questionWithNormalPossibleAnswers,
    match: matchPercent,
    detailedMatch: {
        qMatch: matchPercent,
        aMatch: matchPercent,
        dMatch: matchPercent,
        matchedSubjName: 'testSubj',
        avg: matchPercent,
    },
}

const resNormal2: SearchResultQuestion = {
    q: questionWithNormalPossibleAnswers2,
    match: matchPercent,
    detailedMatch: {
        qMatch: matchPercent,
        aMatch: matchPercent,
        dMatch: matchPercent,
        matchedSubjName: 'testSubj',
        avg: matchPercent,
    },
}

const resNormal3: SearchResultQuestion = {
    q: questionWithNormalPossibleAnswers3,
    match: matchPercent,
    detailedMatch: {
        qMatch: matchPercent,
        aMatch: matchPercent,
        dMatch: matchPercent,
        matchedSubjName: 'testSubj',
        avg: matchPercent,
    },
}

const resNormal4: SearchResultQuestion = {
    q: questionWithNormalPossibleAnswers4,
    match: matchPercent,
    detailedMatch: {
        qMatch: matchPercent,
        aMatch: matchPercent,
        dMatch: matchPercent,
        matchedSubjName: 'testSubj',
        avg: matchPercent,
    },
}

const resSimilar: SearchResultQuestion = {
    q: questionWithSimilarPossibleAnswers,
    match: matchPercent,
    detailedMatch: {
        qMatch: matchPercent,
        aMatch: matchPercent,
        dMatch: matchPercent,
        matchedSubjName: 'testSubj',
        avg: matchPercent,
    },
}

const resTrueFalse: SearchResultQuestion = {
    q: questionWithTrueFalsePossibleAnser,
    match: matchPercent,
    detailedMatch: {
        qMatch: matchPercent,
        aMatch: matchPercent,
        dMatch: matchPercent,
        matchedSubjName: 'testSubj',
        avg: matchPercent,
    },
}

const resNoPossibleAnswer: SearchResultQuestion = {
    q: questionWithNoPossibleAnswer,
    match: matchPercent,
    detailedMatch: {
        qMatch: matchPercent,
        aMatch: matchPercent,
        dMatch: matchPercent,
        matchedSubjName: 'testSubj',
        avg: matchPercent,
    },
}

const testFunction = (
    question: Question,
    searchResult: SearchResultQuestion[],
    index: number
) => {
    const updated = setNoPossibleAnswersPenalties(
        question.data.possibleAnswers,
        searchResult
    )

    updated.forEach((x, i) => {
        if (i !== index) {
            expect(x.match).toBe(matchPercent - noPossibleAnswerMatchPenalty)
            expect(x.detailedMatch.qMatch).toBe(
                matchPercent - noPossibleAnswerMatchPenalty
            )
        } else {
            expect(x.match).toBe(100)
            expect(x.detailedMatch.qMatch).toBe(100)
        }
    })

    return updated
}

test('Possible answer penalty applies correctly (normal possible answers)', () => {
    testFunction(
        questionWithNormalPossibleAnswers,
        [
            resNormal,
            resNormal2,
            resNormal3,
            resNormal4,
            resSimilar,
            resTrueFalse,
            resNoPossibleAnswer,
        ],
        0
    )
})

test('Possible answer penalty applies correctly (normal possible answers, with labels)', () => {
    testFunction(
        questionWithNormalPossibleAnswersWithLabels,
        [
            resNormal,
            resNormal2,
            resNormal3,
            resNormal4,
            resSimilar,
            resTrueFalse,
            resNoPossibleAnswer,
        ],
        0
    )
})

test('Possible answer penalty applies correctly (similar possible answers)', () => {
    testFunction(
        questionWithSimilarPossibleAnswers,
        [
            resNormal,
            resNormal2,
            resNormal3,
            resNormal4,
            resSimilar,
            resTrueFalse,
            resNoPossibleAnswer,
        ],
        4
    )
})

test('Possible answer penalty applies correctly (true false possible answers)', () => {
    testFunction(
        questionWithTrueFalsePossibleAnser,
        [
            resNormal,
            resNormal2,
            resNormal3,
            resNormal4,
            resSimilar,
            resTrueFalse,
            resNoPossibleAnswer,
        ],
        5
    )
})

test('Possible answer penalty applies correctly (no possible answers)', () => {
    const updated = setNoPossibleAnswersPenalties(
        questionWithNoPossibleAnswer.data.possibleAnswers,
        [
            resNormal,
            resNormal2,
            resNormal3,
            resNormal4,
            resSimilar,
            resTrueFalse,
            resNoPossibleAnswer,
        ]
    )

    updated.forEach((x) => {
        expect(x.match).toBe(100)
        expect(x.detailedMatch.qMatch).toBe(100)
    })
})

test('Possible answer penalty applies correctly (empty searchResult)', () => {
    const updated = testFunction(questionWithTrueFalsePossibleAnser, [], 0)
    expect(updated.length).toBe(0)
})
