package ru.fincode.tsudesk.feature.schedule.presentation.screen

import ru.fincode.tsudesk.feature.schedule.domain.model.LessonEntity
import ru.fincode.tsudesk.feature.schedule.domain.model.LessonType
import ru.fincode.tsudesk.feature.schedule.domain.model.ScheduleEntity
import ru.fincode.tsudesk.feature.schedule.presentation.util.dowRuShort
import ru.fincode.tsudesk.feature.schedule.presentation.util.todayString
import java.util.Calendar

object ScheduleUiMapper {

    /**
     * Маппинг уроков на выбранный день (dd.MM.yyyy)
     */
    fun mapDayLessons(entity: ScheduleEntity, selectedDate: String): List<UiLesson> {
        val today = todayString()
        val nowMinutes = nowMinutes()

        return entity.lessons
            .asSequence()
            .filter { it.date == selectedDate }
            .sortedBy { startMinutesOrMax(it.time) }
            .map { lesson ->
                val (badgeText, badgeKind) = badgeFor(lesson)
                UiLesson(
                    id = stableId(lesson),
                    time = normalizeTime(lesson.time),
                    title = lesson.name,
                    teacher = lesson.teacher,
                    room = lesson.room,
                    badgeText = badgeText,
                    badgeKind = badgeKind,
                    isNow = isNowLesson(
                        lessonDate = lesson.date,
                        lessonTime = lesson.time,
                        today = today,
                        nowMinutes = nowMinutes
                    )
                )
            }
            .toList()
    }

    /**
     * Группировка на неделю по списку dayStrip (порядок сохраняется)
     */
    fun mapWeekGrouped(entity: ScheduleEntity, dayStrip: List<String>): List<UiWeekDay> {
        val lessonsByDate = entity.lessons.groupBy { it.date }
        val today = todayString()
        val nowMinutes = nowMinutes()

        return dayStrip.map { date ->
            val lessons = (lessonsByDate[date].orEmpty())
                .sortedBy { startMinutesOrMax(it.time) }
                .map { lesson ->
                    val (badgeText, badgeKind) = badgeFor(lesson)
                    UiLesson(
                        id = stableId(lesson),
                        time = normalizeTime(lesson.time),
                        title = lesson.name,
                        teacher = lesson.teacher,
                        room = lesson.room,
                        badgeText = badgeText,
                        badgeKind = badgeKind,
                        isNow = isNowLesson(
                            lessonDate = lesson.date,
                            lessonTime = lesson.time,
                            today = today,
                            nowMinutes = nowMinutes
                        )
                    )
                }

            UiWeekDay(
                date = date,
                title = weekDayTitle(date),
                lessons = lessons
            )
        }
    }

    private fun weekDayTitle(date: String): String {
        // "Пн, 12.01.2026" (dowRuShort уже без java.time)
        return "${dowRuShort(date)}, $date"
    }

    private fun badgeFor(lesson: LessonEntity): Pair<String, BadgeKind> {
        return when (lesson.type) {
            LessonType.LECTURE -> "Лекция" to BadgeKind.INFO
            LessonType.PRACTICE -> "Практика" to BadgeKind.PRIMARY
            LessonType.LAB -> "Лабораторная" to BadgeKind.LAB
            LessonType.DEFAULT -> {
                // fallback: если API прислал typeName — укоротим до 1 слова, иначе "Занятие"
                val text = lesson.typeName.trim().ifBlank { "Занятие" }.let { tn ->
                    tn.split(' ', ',', ';').firstOrNull().orEmpty().ifBlank { "Занятие" }
                }
                text to BadgeKind.MUTED
            }
        }
    }

    /**
     * Стабильный id для LazyColumn key
     */
    private fun stableId(lesson: LessonEntity): String {
        // date|time|name|room|teacher
        return buildString {
            append(lesson.date)
            append('|')
            append(lesson.time)
            append('|')
            append(lesson.name)
            append('|')
            append(lesson.room)
            append('|')
            append(lesson.teacher)
        }
    }

    /**
     * "08:30 — 10:00" / "08:30-10:00" / "08:30 - 10:00" -> "08:30 — 10:00"
     */
    private fun normalizeTime(raw: String): String {
        val (s, e) = parseStartEnd(raw) ?: return raw.trim()
        return "$s — $e"
    }

    /**
     * Парсит начало/конец из строки времени.
     * Возвращает null если не смогли распознать.
     */
    private fun parseStartEnd(raw: String): Pair<String, String>? {
        // Достаём 2 времени формата HH:mm
        val matches = Regex("""\b([01]\d|2[0-3]):[0-5]\d\b""")
            .findAll(raw)
            .map { it.value }
            .toList()

        if (matches.size >= 2) return matches[0] to matches[1]
        return null
    }

    private fun startMinutesOrMax(rawTime: String): Int {
        val start = parseStartEnd(rawTime)?.first ?: return Int.MAX_VALUE
        return toMinutes(start) ?: Int.MAX_VALUE
    }

    private fun toMinutes(hhmm: String): Int? {
        val parts = hhmm.split(':')
        if (parts.size != 2) return null
        val h = parts[0].toIntOrNull() ?: return null
        val m = parts[1].toIntOrNull() ?: return null
        return h * 60 + m
    }

    private fun nowMinutes(): Int {
        val c = Calendar.getInstance()
        val h = c.get(Calendar.HOUR_OF_DAY)
        val m = c.get(Calendar.MINUTE)
        return h * 60 + m
    }

    private fun isNowLesson(
        lessonDate: String,
        lessonTime: String,
        today: String,
        nowMinutes: Int
    ): Boolean {
        if (lessonDate != today) return false
        val (s, e) = parseStartEnd(lessonTime) ?: return false
        val start = toMinutes(s) ?: return false
        val end = toMinutes(e) ?: return false
        // обычно end > start; если вдруг кривые данные — не подсвечиваем
        if (end <= start) return false
        return nowMinutes in start..end
    }
}