<script setup lang="ts">
import { computed, inject, ref, watch } from 'vue'
import { lecturesApi } from '@/api'
import { ApiError } from '@/api/client'
import type { CourseDto, LectureDto, LocationDto } from '@/api/types'
import { useAuthStore } from '@/stores/auth'
import ModalDialog from '@/components/ui/ModalDialog.vue'

const props = defineProps<{
  modelValue: boolean
  courses: CourseDto[]
  locations: LocationDto[]
  loading?: boolean
}>()

const emit = defineEmits<{
  'update:modelValue': [value: boolean]
  created: [lecture: LectureDto]
  missingCourse: []
}>()

const addToast = inject('addToast') as
  | ((message: string, type?: 'success' | 'error' | 'info') => void)
  | undefined

const auth = useAuthStore()
const creating = ref(false)
const timeOptions = [
  { label: 'Через 3ч 5м', minutes: 185 },
  { label: 'Через 1ч 5м', minutes: 65 },
  { label: 'Через 5м', minutes: 5 },
]
const form = ref({
  title: 'Лекция для проверки уведомлений',
  offsetMinutes: 185,
  durationMinutes: 60,
  maxEnrollments: 100,
  courseId: null as number | null,
  teacherId: auth.user?.id ?? null,
  locationId: null as number | null,
})
const locationSearch = ref('')

const currentTeacherLabel = computed(() => {
  if (!auth.user) return 'Текущий пользователь не определён'
  return `${auth.user.name} · ID ${auth.user.id}`
})

const filteredLocations = computed(() => {
  const search = locationSearch.value.trim().toLowerCase()
  if (!search) return props.locations

  return props.locations.filter((location) =>
    formatLocation(location).toLowerCase().includes(search),
  )
})

const isOpen = computed({
  get: () => props.modelValue,
  set: (value) => emit('update:modelValue', value),
})

watch(
  () => props.modelValue,
  (isOpenNow) => {
    if (isOpenNow && !form.value.teacherId) form.value.teacherId = auth.user?.id ?? null
  },
)

function getCourseId() {
  const selectedCourseId = form.value.courseId
  if (selectedCourseId && props.courses.some((course) => course.id === selectedCourseId))
    return selectedCourseId
  return props.courses[0]?.id ?? null
}

function formatLocation(location: LocationDto) {
  return (
    [location.building, location.room ? `ауд. ${location.room}` : '', location.name]
      .filter(Boolean)
      .join(', ') || `Аудитория #${location.id}`
  )
}

function getLocation() {
  const selectedLocationId = form.value.locationId
  if (selectedLocationId) {
    const selectedLocation = props.locations.find((location) => location.id === selectedLocationId)
    if (selectedLocation) return selectedLocation
  }
  if (locationSearch.value.trim()) return filteredLocations.value[0] ?? null
  return props.locations[0] ?? null
}

function extractApiErrorDetails(err: unknown) {
  if (!(err instanceof ApiError)) return []
  const details = err.details
  if (!details || typeof details !== 'object') return []

  const problem = details as {
    title?: unknown
    detail?: unknown
    traceId?: unknown
    status?: unknown
  }
  return [
    typeof problem.title === 'string' ? `title=${problem.title}` : '',
    typeof problem.status === 'number' ? `status=${problem.status}` : '',
    typeof problem.detail === 'string' ? `detail=${problem.detail}` : '',
    typeof problem.traceId === 'string' ? `traceId=${problem.traceId}` : '',
  ].filter(Boolean)
}

async function createLecture() {
  const courseId = getCourseId()
  const title = form.value.title.trim()
  const offsetMinutes = Math.max(1, Number(form.value.offsetMinutes) || 1)
  const durationMinutes = Math.max(5, Number(form.value.durationMinutes) || 60)
  const maxEnrollments = Math.max(1, Number(form.value.maxEnrollments) || 100)
  const teacherId = form.value.teacherId ? Number(form.value.teacherId) : null

  if (!courseId) {
    addToast?.('Нужен хотя бы один курс, чтобы создать лекцию.', 'error')
    emit('missingCourse')
    isOpen.value = false
    return
  }
  if (!title) {
    addToast?.('Укажите название лекции.', 'error')
    return
  }

  creating.value = true
  try {
    const location = getLocation()
    const startsAt = new Date(Date.now() + offsetMinutes * 60_000)
    const endsAt = new Date(startsAt.getTime() + durationMinutes * 60_000)
    const createdLecture = await lecturesApi.create({
      courseId,
      teacherId,
      locationId: location?.id ?? null,
      title,
      description:
        'Лекция создана из админки для проверки системы отзывов и напоминаний о начале лекции.',
      format: location ? 'Offline' : 'Online',
      startsAt: startsAt.toISOString(),
      endsAt: endsAt.toISOString(),
      isOpen: true,
      maxEnrollments,
      onlineUrl: null,
    })

    emit('created', createdLecture)
    isOpen.value = false
    addToast?.(`Лекция создана: ${startsAt.toLocaleString('ru-RU')}.`, 'success')
  } catch (err) {
    const message = err instanceof Error ? err.message : 'Не удалось создать лекцию.'
    const details = extractApiErrorDetails(err)
    addToast?.(details.length ? `${message}: ${details.join('; ')}` : message, 'error')
  } finally {
    creating.value = false
  }
}
</script>

<template>
  <ModalDialog
    v-model="isOpen"
    title="Создать лекцию"
    description="Для ручной проверки отзывов и уведомлений"
    icon="calendar-event"
    size="md"
  >
    <form class="create-lecture-form" @submit.prevent="createLecture">
      <label>Название</label>
      <input v-model="form.title" class="glass-input" placeholder="Например, тест уведомлений" />

      <label>Старт</label>
      <div class="start-controls">
        <div class="time-options">
          <button
            v-for="option in timeOptions"
            :key="option.minutes"
            class="time-option"
            :class="{ active: form.offsetMinutes === option.minutes }"
            type="button"
            @click="form.offsetMinutes = option.minutes"
          >
            {{ option.label }}
          </button>
        </div>
        <label class="minutes-field">
          <span>Минут до старта</span>
          <input v-model.number="form.offsetMinutes" class="glass-input" min="1" type="number" />
        </label>
      </div>

      <label>Курс</label>
      <select v-model="form.courseId" class="glass-input">
        <option :value="null">Первый доступный курс</option>
        <option v-for="course in courses" :key="course.id" :value="course.id">
          {{ course.name || `Курс #${course.id}` }}
        </option>
      </select>

      <label>
        Преподаватель
        <span class="field-hint">{{ currentTeacherLabel }}</span>
      </label>
      <input v-model.number="form.teacherId" class="glass-input" min="1" type="number" />

      <label>Аудитория</label>
      <input
        v-model="locationSearch"
        class="glass-input"
        placeholder="Поиск по корпусу, аудитории или названию"
      />
      <select v-model="form.locationId" class="glass-input">
        <option :value="null">
          {{
            filteredLocations[0]
              ? `Первая найденная: ${formatLocation(filteredLocations[0])}`
              : 'Без аудитории, онлайн'
          }}
        </option>
        <option v-for="location in filteredLocations" :key="location.id" :value="location.id">
          {{ formatLocation(location) }}
        </option>
      </select>

      <div class="create-lecture-fields">
        <label>
          <span>Длительность, мин</span>
          <input v-model.number="form.durationMinutes" class="glass-input" min="5" type="number" />
        </label>
        <label>
          <span>Мест</span>
          <input v-model.number="form.maxEnrollments" class="glass-input" min="1" type="number" />
        </label>
      </div>

      <div class="create-lecture-note">
        Лекция создаётся открытой для записи. Аудитория подставится автоматически, если она уже есть
        в справочнике.
      </div>

      <div class="create-lecture-actions">
        <button class="btn-secondary" type="button" :disabled="creating" @click="isOpen = false">
          Отмена
        </button>
        <button class="btn-primary" type="submit" :disabled="creating || loading">
          {{ creating ? 'Создаём...' : 'Создать' }}
        </button>
      </div>
    </form>
  </ModalDialog>
</template>

<style scoped>
.create-lecture-form {
  display: flex;
  flex-direction: column;
  gap: 10px;
  color: var(--color-text);
}
.create-lecture-form label {
  font-size: 12px;
  font-weight: 600;
  color: var(--color-text-secondary);
}
.field-hint {
  display: block;
  margin-top: 3px;
  font-weight: 500;
  color: var(--color-text-muted);
}
.start-controls {
  display: flex;
  align-items: flex-end;
  gap: 10px;
  flex-wrap: wrap;
}
.time-options {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}
.minutes-field {
  flex: 1 1 160px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.time-option {
  border: 1px solid var(--color-border-glass);
  border-radius: 999px;
  padding: 8px 12px;
  background: var(--color-white-a72);
  color: var(--color-text-secondary);
  cursor: pointer;
}
.time-option.active {
  background: var(--color-primary-a18);
  border-color: var(--color-primary-light);
  color: var(--color-primary-dark);
  font-weight: 600;
}
.create-lecture-fields {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 10px;
}
.create-lecture-fields label {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.create-lecture-note {
  font-size: 12px;
  color: var(--color-text-secondary);
  line-height: 1.4;
}
.create-lecture-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 4px;
}
</style>
