import { questionNumber } from '@/components/Questionnaire/classes'
import { Classes, Divider } from '@blueprintjs/core'
import { css, cx } from '@emotion/css'
import type { Content, Question } from '@inject/graphql/fragment-types'
import type { FC, ReactNode } from 'react'
import { Fragment, useCallback } from 'react'
import ContentComponent from '../ContentComponent'
import QuestionContent from './QuestionContent'
import type { QuestionAndAnswer, QuestionProps } from './types'

const wrapper = css`
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  height: 100%;
  width: 100%;
  gap: 1rem;
`

const contentWrapper = css`
  flex: 1;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 1rem;
  width: 100%;
`

const body = css`
  flex: 1;
  margin: 0.5rem;
`

const bodyGrid = css`
  display: grid;
  grid-template-columns: auto auto 1fr;
  row-gap: 1rem;
  column-gap: 0.5rem;
`

const questionActionsWrapper = css`
  display: flex;
  justify-content: flex-end;
`

const footer = css`
  display: flex;
  justify-content: flex-end;
  width: 100%;
`

const descriptionClass = css`
  margin: 0.5rem;
  padding: 1rem;
  border-radius: 0.5rem;

  border: 1px solid rgba(0, 0, 0, 0.2);
  border-radius: 0.5rem;
  .${Classes.DARK} & {
    border-color: rgba(255, 255, 255, 0.2);
  }
`

type QuestionnaireProps = {
  questionsAndAnswers: QuestionAndAnswer[]
  content: Content
  callout?: ReactNode
  actions?: ReactNode
  teamId: string
  exerciseId: string
  inInstructor: boolean
} & (
  | {
      type: 'answering'
      disabled: (questionId: string) => boolean | undefined
      onChange: (questionId: string) => (value: string) => void
      questionActions?: never
    }
  | {
      type: 'reviewing'
      // in this type, disabled should always be true
      disabled?: never
      onChange?: never
      questionActions: (question: Question) => ReactNode
    }
)

const Questionnaire: FC<QuestionnaireProps> = ({
  teamId,
  exerciseId,
  questionsAndAnswers,
  content,
  callout,
  type,
  disabled,
  onChange,
  actions,
  questionActions,
  inInstructor,
}) => {
  const getQuestionProps = useCallback(
    ({ question, answer }: QuestionAndAnswer): QuestionProps => {
      switch (type) {
        case 'answering':
          return {
            question,
            answer,
            type,
            disabled: disabled(question.id),
            onChange: onChange(question.id),
            teamId,
            inInstructor,
          }
        case 'reviewing':
          return {
            question,
            answer,
            type,
            teamId,
            inInstructor,
          }
      }
    },
    [disabled, inInstructor, onChange, teamId, type]
  )

  return (
    <div className={wrapper}>
      {callout}

      <div className={contentWrapper}>
        {(content.rendered || content.fileInfo) && (
          <div className={descriptionClass}>
            <ContentComponent
              content={content}
              teamId={teamId}
              exerciseId={exerciseId}
              inInstructor={inInstructor}
            />
          </div>
        )}

        <div
          className={cx({
            [body]: true,
            [bodyGrid]: questionsAndAnswers.length > 1,
          })}
        >
          {questionsAndAnswers.map((questionAndAnswer, questionIndex) => (
            <Fragment key={questionAndAnswer.question.id}>
              {questionsAndAnswers.length > 1 && (
                <>
                  <div
                    className={questionNumber}
                  >{`${questionIndex + 1}.`}</div>
                  <Divider />
                </>
              )}
              <div>
                <QuestionContent {...getQuestionProps(questionAndAnswer)} />
                {questionActions && (
                  <div className={questionActionsWrapper}>
                    {questionActions(questionAndAnswer.question)}
                  </div>
                )}
                {questionAndAnswer.question.note && (
                  <div className={Classes.TEXT_MUTED}>
                    {`Note: ${questionAndAnswer.question.note}`}
                  </div>
                )}
              </div>
            </Fragment>
          ))}
        </div>
      </div>

      {actions && <div className={footer}>{actions}</div>}
    </div>
  )
}

export default Questionnaire
