import { register } from '@/services/mock/registry'
import { endpoints } from '@/services/api/endpoints'
import { adminCourses } from '@/services/mock/fixtures/admin-courses'
import { adminSessions } from '@/services/mock/fixtures/admin-sessions'
import {
  adminExams,
  examAttempts,
  examAttemptReviews,
  examParticipants,
} from '@/services/mock/fixtures/admin-exams'
import {
  filterDateRange,
  filterItems,
  findOrThrow,
  isoNow,
  makeId,
  paginate,
  removeById,
  updateById,
} from '@/services/mock/helpers'

const resolveCourseFromSession = (session) => {
  const courseId = session?.course?.id ?? session?.courseId
  if (courseId == null) return null
  return adminCourses.find((c) => c.id === Number(courseId)) || null
}

const sessionSnapshot = (session) => (session ? { id: session.id, title: session.title } : null)

const courseSnapshot = (course) => (course ? { id: course.id, title: course.title } : null)

register('GET', endpoints.getExamsList, ({ query }) => {
  let list = filterItems(adminExams, query, {
    title: 'includes',
    courseId: (item, v) => String(item.course?.id) === String(v),
    sessionId: (item, v) => String(item.sessionId) === String(v),
    termId: (item, v) => {
      const course = adminCourses.find((c) => c.id === Number(item.course?.id))
      const termId = course?.termId ?? course?.term?.id ?? null
      return String(termId) === String(v)
    },
  })
  list = filterDateRange(list, query)
  const { data: items, meta } = paginate(list, query)
  return {
    success: true,
    message: 'OK',
    data: items,
    meta,
  }
})

register('GET', endpoints.showExam, ({ params }) => ({
  success: true,
  message: 'OK',
  data: findOrThrow(adminExams, params.id),
}))

register('POST', endpoints.addNewExam, ({ data }) => {
  const session = adminSessions.find((s) => s.id === Number(data.sessionId))
  const course = resolveCourseFromSession(session)
  const item = {
    id: makeId(),
    sessionId: session?.id ?? Number(data.sessionId) ?? null,
    title: data.title || '',
    description: data.description || '',
    score: Number(data.score) || 0,
    minimumScore: Number(data.minimumScore ?? data.passingScore ?? data.passScore) || 0,
    durationMinutes: Number(data.durationMinutes) || 0,
    isRandom: data.isRandom ?? false,
    isActive: data.isActive ?? true,
    questions: [],
    // UI-only fallbacks for ExamItem / ExamDetailsModal.
    session: sessionSnapshot(session),
    sessionTitle: session?.title || '',
    course: courseSnapshot(course),
    courseTitle: course?.title || '',
    questionsCount: 0,
    createdAt: isoNow(),
  }
  adminExams.unshift(item)
  return {
    success: true,
    message: 'Exam created.',
    data: item,
  }
})

register('PATCH', endpoints.updateExam, ({ params, data }) => {
  const patch = {}
  if (data.title !== undefined) patch.title = data.title
  if (data.description !== undefined) patch.description = data.description
  if (data.score !== undefined) patch.score = Number(data.score) || 0
  if (data.minimumScore !== undefined) patch.minimumScore = Number(data.minimumScore) || 0
  if (data.durationMinutes !== undefined) patch.durationMinutes = Number(data.durationMinutes) || 0
  if (data.isRandom !== undefined) patch.isRandom = !!data.isRandom
  if (data.isActive !== undefined) patch.isActive = !!data.isActive
  if (data.sessionId !== undefined) {
    const session = adminSessions.find((s) => s.id === Number(data.sessionId))
    const course = resolveCourseFromSession(session)
    patch.sessionId = session?.id ?? Number(data.sessionId) ?? null
    patch.session = sessionSnapshot(session)
    patch.sessionTitle = session?.title ?? ''
    patch.course = courseSnapshot(course)
    patch.courseTitle = course?.title ?? ''
  }
  return {
    success: true,
    message: 'Exam updated.',
    data: updateById(adminExams, params.id, patch),
  }
})

register('DELETE', endpoints.deleteExam, ({ params }) => {
  removeById(adminExams, params.id)
  return { success: true, message: 'Exam deleted.', data: null }
})

// POST /exams/:examId/questions — atomic question + options create.
register('POST', endpoints.addExamQuestion, ({ params, data }) => {
  const exam = findOrThrow(adminExams, params.examId)
  const questionId = makeId()
  const options = Array.isArray(data.options) ? data.options : []
  const question = {
    id: questionId,
    questionText: data.questionText || '',
    position: data.position ?? (exam.questions?.length ?? 0) + 1,
    score: Number(data.score) || 0,
    options: options.map((opt, idx) => ({
      id: questionId * 100 + idx + 1,
      optionText: opt.optionText || '',
      isCorrect: !!opt.isCorrect,
    })),
  }
  exam.questions = [...(exam.questions || []), question]
  exam.questionsCount = exam.questions.length
  return {
    success: true,
    message: 'Question added.',
    data: question,
  }
})

// POST /questions/:questionId/options — single option append.
register('POST', endpoints.addQuestionOption, ({ params, data }) => {
  for (const exam of adminExams) {
    const question = (exam.questions || []).find((q) => String(q.id) === String(params.questionId))
    if (question) {
      const option = {
        id: makeId(),
        optionText: data.optionText || '',
        isCorrect: !!data.isCorrect,
      }
      question.options = [...(question.options || []), option]
      return {
        success: true,
        message: 'Option added.',
        data: option,
      }
    }
  }
  return { success: false, message: 'Question not found.', data: null }
})

register('GET', endpoints.getExamAttempts, ({ params, query }) => {
  const list = examAttempts.get(Number(params.examId)) || []
  const { data: items, meta } = paginate(list, query)
  return { success: true, message: 'OK', data: { items, meta } }
})

// GET /exam-attempts/:id — full per-attempt review payload.
register('GET', endpoints.showExamAttempt, ({ params }) => {
  const review = examAttemptReviews.get(Number(params.id))
  return { success: true, message: 'OK', data: review || null }
})

// FE-mock-only — single-participant detail not yet on the backend.
register('GET', endpoints.showExamParticipant, ({ params }) => {
  const list = examParticipants.get(Number(params.examId)) || []
  const found = list.find((p) => String(p.id) === String(params.participantId))
  return { data: found || null }
})
