import { useMemo, useState } from 'react';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import {
  createSafetyQuizResult,
  listSafetyQuizResults,
} from '@/shared/api/safetyQuizResults';
import {
  getManagedContentCatalog,
  updateManagedContentCatalog,
} from '@/shared/api/contentCatalog';
import { useContentCatalogPayload } from '@/business/content-catalog/hooks';
import {
  SAFETY_QUIZ_COMPLIANCE_QUERY_SEGMENT,
  SAFETY_QUIZ_QUERY_KEYS,
} from '@/shared/constants/safetyQuiz';
import {
  CONTENT_CATALOG_QUERY_KEYS,
  CONTENT_CATALOG_TYPES,
} from '@/shared/constants/contentCatalog';
import {
  toSafetyQuizComplianceRow,
  toSafetyQuizResultCreateDto,
} from '@/business/safety-quiz/mappers';
import {
  SafetyQuizContentEditor,
  SafetyQuizPage,
  SafetyQuizSubmission,
} from '@/business/safety-quiz/types';
import {
  calculateSafetyQuizCompletionSummary,
  calculateSafetyQuizScore,
  getCurrentSafetyQuizWeek,
  parseSafetyQuizPayload,
  serializeSafetyQuizPayload,
} from '@/business/safety-quiz/selectors';
import type { SafetyQuiz, UserRole } from '@/shared/types/app';
import { getApiListRows, mapApiListRows } from '@/shared/business/apiListRows';
import { useInvalidatingMutation } from '@/shared/business/queryMutations';
import { getOptionalErrorMessage } from '@/shared/errors/errorMessages';

export function useSafetyQuizResults(weekOf?: string) {
  return useQuery({
    queryKey: weekOf ? [...SAFETY_QUIZ_QUERY_KEYS.results, weekOf] : SAFETY_QUIZ_QUERY_KEYS.results,
    queryFn: () => getApiListRows(listSafetyQuizResults(weekOf)),
  });
}

export function useSafetyQuizCompliance(weekOf: string, enabled: boolean) {
  return useQuery({
    queryKey: [...SAFETY_QUIZ_QUERY_KEYS.results, SAFETY_QUIZ_COMPLIANCE_QUERY_SEGMENT, weekOf],
    enabled,
    queryFn: () => mapApiListRows(listSafetyQuizResults(weekOf), toSafetyQuizComplianceRow),
  });
}

export function useSaveSafetyQuizResult() {
  return useInvalidatingMutation({
    mutationFn: (submission: SafetyQuizSubmission) => createSafetyQuizResult(
      toSafetyQuizResultCreateDto(submission),
    ),
    invalidateQueryKey: SAFETY_QUIZ_QUERY_KEYS.results,
  });
}

export function useSafetyQuizPage(userRole: UserRole): SafetyQuizPage {
  const quizQuery = useContentCatalogPayload<SafetyQuiz | null>(
    CONTENT_CATALOG_TYPES.safetyQbsQuiz,
    null,
  );
  const [quizStarted, setQuizStarted] = useState(false);
  const [currentQuestionIndex, setCurrentQuestionIndex] = useState(0);
  const [selectedAnswer, setSelectedAnswer] = useState<number | null>(null);
  const [showExplanation, setShowExplanation] = useState(false);
  const [score, setScore] = useState(0);
  const [quizComplete, setQuizComplete] = useState(false);
  const [answers, setAnswers] = useState<readonly number[]>([]);
  const quiz = quizQuery.payload;
  const weekOf = getCurrentSafetyQuizWeek(new Date());
  const canViewCompliance = userRole === 'director' || userRole === 'superintendent';
  const complianceQuery = useSafetyQuizCompliance(weekOf, canViewCompliance);
  const saveResultMutation = useSaveSafetyQuizResult();
  const complianceRows = complianceQuery.data ?? [];

  function startQuiz() {
    setQuizStarted(true);
  }

  function selectAnswer(answerIndex: number) {
    const question = quiz?.questions[currentQuestionIndex];

    if (showExplanation || !question) {
      return;
    }

    setSelectedAnswer(answerIndex);
    setShowExplanation(true);

    if (answerIndex === question.correctIndex) {
      setScore((currentScore) => currentScore + 1);
    }
  }

  async function goToNextQuestion() {
    if (selectedAnswer === null || !quiz) {
      return;
    }

    const nextAnswers = [...answers, selectedAnswer];

    if (currentQuestionIndex < quiz.questions.length - 1) {
      setAnswers(nextAnswers);
      setCurrentQuestionIndex((current) => current + 1);
      setSelectedAnswer(null);
      setShowExplanation(false);
      return;
    }

    const finalScore = calculateSafetyQuizScore(quiz, nextAnswers);
    setQuizComplete(true);
    setAnswers(nextAnswers);
    setScore(finalScore);
    await saveResultMutation.mutateAsync({
      quizId: quiz.id,
      quizTitle: quiz.title,
      score: finalScore,
      totalQuestions: quiz.questions.length,
      answers: nextAnswers,
      weekOf,
    });
  }

  function resetQuiz() {
    setQuizStarted(false);
    setCurrentQuestionIndex(0);
    setSelectedAnswer(null);
    setShowExplanation(false);
    setScore(0);
    setQuizComplete(false);
    setAnswers([]);
  }

  return {
    quiz,
    weekOf,
    stage: quizComplete ? 'complete' : quizStarted ? 'question' : 'intro',
    currentQuestionIndex,
    selectedAnswer,
    showExplanation,
    score,
    answers,
    complianceRows,
    completionSummary: calculateSafetyQuizCompletionSummary(complianceRows),
    canViewCompliance,
    canManageQuizContent: canViewCompliance,
    isQuizLoading: quizQuery.isLoading,
    isComplianceLoading: complianceQuery.isLoading,
    isSavingResult: saveResultMutation.isPending,
    quizError: quizQuery.error,
    complianceError: complianceQuery.error,
    saveResultError: saveResultMutation.error,
    startQuiz,
    selectAnswer,
    goToNextQuestion,
    resetQuiz,
  };
}

export function useSafetyQuizContentEditor(): SafetyQuizContentEditor {
  const queryClient = useQueryClient();
  const [draftOverride, setDraftOverride] = useState<string | null>(null);
  const [validationError, setValidationError] = useState<string | null>(null);
  const [savedMessage, setSavedMessage] = useState<string | null>(null);
  const contentType = CONTENT_CATALOG_TYPES.safetyQbsQuiz;
  const managedQuery = useQuery({
    queryKey: [...CONTENT_CATALOG_QUERY_KEYS.content, 'managed', contentType],
    queryFn: () => getManagedContentCatalog<SafetyQuiz>(contentType),
  });
  const saveMutation = useMutation({
    mutationFn: (payload: SafetyQuiz) => updateManagedContentCatalog(contentType, { payload }),
    onSuccess: async (response) => {
      const serializedPayload = serializeSafetyQuizPayload(response.payload);
      setDraftOverride(serializedPayload);
      setValidationError(null);
      setSavedMessage('Safety quiz content saved.');
      await Promise.all([
        queryClient.invalidateQueries({ queryKey: [...CONTENT_CATALOG_QUERY_KEYS.content, contentType] }),
        queryClient.invalidateQueries({ queryKey: [...CONTENT_CATALOG_QUERY_KEYS.content, 'managed', contentType] }),
      ]);
    },
  });
  const serverDraft = useMemo(
    () => (managedQuery.data?.payload ? serializeSafetyQuizPayload(managedQuery.data.payload) : ''),
    [managedQuery.data],
  );
  const draft = draftOverride ?? serverDraft;

  const canSave = useMemo(
    () => Boolean(draft.trim()) && !managedQuery.isLoading && !saveMutation.isPending,
    [draft, managedQuery.isLoading, saveMutation.isPending],
  );

  return {
    draft,
    isLoading: managedQuery.isLoading,
    isSaving: saveMutation.isPending,
    errorMessage: getOptionalErrorMessage(
      managedQuery.error || saveMutation.error,
      'Safety quiz content could not be loaded or saved.',
    ),
    validationError,
    savedMessage,
    canSave,
    setDraft: (nextDraft) => {
      setDraftOverride(nextDraft);
      setValidationError(null);
      setSavedMessage(null);
    },
    reset: () => {
      setDraftOverride(null);
      setValidationError(null);
      setSavedMessage(null);
    },
    save: async () => {
      const result = parseSafetyQuizPayload(draft);

      if (typeof result === 'string') {
        setValidationError(result);
        setSavedMessage(null);
        return;
      }

      await saveMutation.mutateAsync(result);
    },
  };
}
