import { defineStore } from 'pinia'
import { computed, ref } from 'vue'
import { lecturesApi, usersApi } from '@/api'
import { mapApiLecture } from '@/api/mappers'
import type { Lecture } from '@/types'
import type { LectureQuery } from '@/api/types'
import { useUserStore } from './user'

export const useLecturesStore = defineStore('lectures', () => {
  const lectures = ref<Lecture[]>([])
  const registered = ref<string[]>([])
  const loading = ref(false)
  const error = ref<string | null>(null)

  const all = computed(() => lectures.value)
  const registeredIds = computed(() => registered.value)
  const registeredLectures = computed(() =>
    lectures.value.filter((l) => registered.value.includes(l.id) || l.registered),
  )

  async function fetchLectures(query: LectureQuery = {}) {
    loading.value = true
    error.value = null
    try {
      const payload = await lecturesApi.list({ PageSize: 100, ...query })
      lectures.value = payload.map(mapApiLecture)
      registered.value = lectures.value.filter((l) => l.registered).map((l) => l.id)
    } catch (err) {
      error.value = err instanceof Error ? err.message : 'Не удалось загрузить лекции.'
    } finally {
      loading.value = false
    }
  }

  async function fetchLecture(id: string) {
    error.value = null
    try {
      const lecture = mapApiLecture(await lecturesApi.get(id))
      const index = lectures.value.findIndex((item) => item.id === lecture.id)
      if (index >= 0) lectures.value[index] = lecture
      else lectures.value.push(lecture)
      if (lecture.registered && !registered.value.includes(lecture.id))
        registered.value.push(lecture.id)
      return lecture
    } catch (err) {
      error.value = err instanceof Error ? err.message : 'Не удалось загрузить лекцию.'
      return lectures.value.find((item) => item.id === id)
    }
  }

  async function fetchRegisteredForCurrentUser() {
    try {
      const enrollments = await usersApi.myEnrollments()
      const mapped = enrollments.map(mapApiLecture)
      registered.value = mapped.map((lecture) => lecture.id)
      if (mapped.length) {
        mapped.forEach((lecture) => {
          const index = lectures.value.findIndex((item) => item.id === lecture.id)
          if (index >= 0)
            lectures.value[index] = { ...lectures.value[index], ...lecture, registered: true }
          else lectures.value.push({ ...lecture, registered: true })
        })
      }
    } catch {
      // Some backend builds return an empty 200 for this endpoint; catalog detail still carries isEnrolled.
    }
  }

  async function register(lectureId: string) {
    const lecture = lectures.value.find((item) => item.id === lectureId)
    if (
      !lecture ||
      lecture.freeSeats === 0 ||
      lecture.registrationClosed ||
      registered.value.includes(lectureId)
    )
      return
    const userStore = useUserStore()
    if (!userStore.hasEnrollmentSlotAvailable) {
      throw new Error('Лимит записей достигнут. Отмените одну из записей или повысьте уровень.')
    }

    await lecturesApi.enroll(lectureId)
    registered.value.push(lectureId)
    lecture.freeSeats = Math.max(lecture.freeSeats - 1, 0)
    lecture.enrolledSeats += 1
    lecture.registered = true
    userStore.adjustActiveEnrollments(1)
    await userStore.fetchStats().catch(() => undefined)
  }

  async function unregister(lectureId: string) {
    await lecturesApi.unenroll(lectureId)
    const userStore = useUserStore()
    registered.value = registered.value.filter((id) => id !== lectureId)
    const lecture = lectures.value.find((item) => item.id === lectureId)
    if (lecture) {
      lecture.freeSeats = Math.min(lecture.freeSeats + 1, lecture.totalSeats)
      lecture.enrolledSeats = Math.max(lecture.enrolledSeats - 1, 0)
      lecture.registered = false
    }
    userStore.adjustActiveEnrollments(-1)
    await userStore.fetchStats().catch(() => undefined)
  }

  function isRegistered(lectureId: string) {
    return (
      registered.value.includes(lectureId) ||
      Boolean(lectures.value.find((item) => item.id === lectureId)?.registered)
    )
  }

  return {
    lectures,
    registered,
    loading,
    error,
    all,
    registeredIds,
    registeredLectures,
    fetchLectures,
    fetchLecture,
    fetchRegisteredForCurrentUser,
    register,
    unregister,
    isRegistered,
  }
})
