import { SESSION_TYPE } from '@/enums'
import { register } from '@/services/mock/registry'
import { endpoints } from '@/services/api/endpoints'
import { adminCourses } from '@/services/mock/fixtures/admin-courses'
import {
  adminSessions,
  makeSession,
  sessionAttendance,
} from '@/services/mock/fixtures/admin-sessions'
import {
  filterDateRange,
  filterItems,
  findOrThrow,
  isoNow,
  makeId,
  paginate,
  removeById,
  updateById,
} from '@/services/mock/helpers'

const enrich = (session) => ({
  ...session,
  sessionTypeFa: SESSION_TYPE[session.sessionType] || session.sessionTypeFa || '',
})

register('GET', endpoints.getSessionsList, ({ query }) => {
  let list = filterItems(adminSessions, query, {
    title: 'includes',
    courseId: (item, v) => String(item.course?.id ?? item.courseId) === String(v),
    sessionType: 'eq',
    type: 'eq',
  })
  list = filterDateRange(list, query)
  // eslint-disable-next-line unicorn/no-array-callback-reference
  const { data: items, meta } = paginate(list.map(enrich), query)
  return {
    success: true,
    message: 'OK',
    data: { items, meta },
  }
})

register('GET', endpoints.showSession, ({ params }) => {
  const session = enrich(findOrThrow(adminSessions, params.id))
  const course = adminCourses.find((c) => c.id === session.courseId)
  return {
    success: true,
    message: 'OK',
    data: { ...session, course: course ? { id: course.id, title: course.title } : session.course },
  }
})

// Form sends a flat payload (startTime, endTime, meetingLink, contentType, etc.).
// We mirror those into the legacy `sessionConfig` shape too so SessionDetailsModal
// (which reads `sessionConfig.startTime` / `sessionConfig.meetingLink`) keeps working.
const buildSessionConfig = (data) => ({
  startTime: data.startTime ?? data.sessionConfig?.startTime ?? null,
  endTime: data.endTime ?? data.sessionConfig?.endTime ?? null,
  meetingLink: data.meetingLink ?? data.sessionConfig?.meetingLink ?? null,
})

register('POST', endpoints.addNewSession, ({ data }) => {
  const course = adminCourses.find((c) => c.id === Number(data.courseId))
  const sessionConfig = buildSessionConfig(data)
  const item = makeSession({
    id: makeId(),
    courseId: course?.id ?? (data.courseId ? Number(data.courseId) : null),
    title: data.title || '',
    description: data.description || '',
    type: data.sessionType === 'online' ? 'online' : 'offline',
    startsAt: sessionConfig.startTime,
    endsAt: sessionConfig.endTime,
    link: sessionConfig.meetingLink,
    course: course ? { id: course.id, title: course.title } : null,
    sessionType: data.sessionType || 'in_person',
    contentType: data.contentType || '',
    contentMediaId: data.contentMediaId ?? null,
    durationMinutes: Number(data.durationMinutes) || 0,
    sessionConfig,
    createdAt: isoNow(),
  })
  adminSessions.unshift(item)
  return {
    success: true,
    message: 'Session created.',
    data: enrich(item),
  }
})

register('PATCH', endpoints.updateSession, ({ params, data }) => {
  const patch = {}
  if (data.title !== undefined) patch.title = data.title
  if (data.description !== undefined) patch.description = data.description
  if (data.startTime !== undefined) patch.startsAt = data.startTime
  if (data.endTime !== undefined) patch.endsAt = data.endTime
  if (data.meetingLink !== undefined) patch.link = data.meetingLink
  if (data.courseId !== undefined) {
    patch.courseId = Number(data.courseId) || null
    const course = adminCourses.find((c) => c.id === Number(data.courseId))
    patch.course = course ? { id: course.id, title: course.title } : null
  }
  if (data.sessionType !== undefined) {
    patch.sessionType = data.sessionType
    patch.type = data.sessionType === 'online' ? 'online' : 'offline'
  }
  if (data.contentType !== undefined) patch.contentType = data.contentType
  if (data.contentMediaId !== undefined) patch.contentMediaId = data.contentMediaId
  if (data.durationMinutes !== undefined) patch.durationMinutes = Number(data.durationMinutes) || 0
  // Keep sessionConfig in sync for SessionDetailsModal display fallback.
  if (
    data.startTime !== undefined ||
    data.endTime !== undefined ||
    data.meetingLink !== undefined
  ) {
    const existing = findOrThrow(adminSessions, params.id)?.sessionConfig || {}
    patch.sessionConfig = {
      ...existing,
      startTime: data.startTime ?? existing.startTime,
      endTime: data.endTime ?? existing.endTime,
      meetingLink: data.meetingLink ?? existing.meetingLink,
    }
  }
  const updated = updateById(adminSessions, params.id, patch)
  return {
    success: true,
    message: 'Session updated.',
    data: enrich(updated),
  }
})

register('DELETE', endpoints.deleteSession, ({ params }) => {
  removeById(adminSessions, params.id)
  return {
    success: true,
    message: 'Session deleted.',
    data: null,
  }
})

register('GET', endpoints.getSessionsAttendance, ({ params, query }) => {
  const list = sessionAttendance.get(Number(params.sessionId)) || []
  return paginate(list, query)
})
