package com.example.elva.ui.calendar

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.GridLayoutManager
import com.example.elva.R
import com.example.elva.databinding.FragmentPeriodCalendarBinding
import com.example.elva.data.models.health.Period
import com.google.android.material.datepicker.MaterialDatePicker
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
import java.time.Instant
import java.time.LocalDate
import java.time.ZoneId
import java.time.format.DateTimeFormatter
import java.time.format.TextStyle
import java.util.*

@AndroidEntryPoint
class PeriodCalendarFragment : Fragment() {

    private var _binding: FragmentPeriodCalendarBinding? = null
    private val binding get() = _binding!!
    private val viewModel: PeriodCalendarViewModel by viewModels()
    private lateinit var calendarAdapter: CalendarAdapter

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding = FragmentPeriodCalendarBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        setupCalendar()
        setupListeners()
        observeState()
    }

    private fun setupCalendar() {
        calendarAdapter = CalendarAdapter { date ->
            viewModel.onDateSelected(date)
            showEditPeriodDialog(date)
        }

        binding.rvCalendar.apply {
            layoutManager = GridLayoutManager(requireContext(), 7)
            adapter = calendarAdapter
        }
    }

    private fun setupListeners() {
        binding.btnPrevMonth.setOnClickListener {
            viewModel.previousMonth()
        }

        binding.btnNextMonth.setOnClickListener {
            viewModel.nextMonth()
        }

        binding.fabAddPeriod.setOnClickListener {
            showAddPeriodDialog()
        }
    }

    private fun observeState() {
        viewLifecycleOwner.lifecycleScope.launch {
            viewModel.state.collect { state ->
                updateUI(state)
            }
        }
    }

    private fun updateUI(state: PeriodCalendarState) {
        // Update month/year header
        val formatter = DateTimeFormatter.ofPattern("LLLL yyyy", Locale("ru"))
        binding.tvMonthYear.text = state.currentMonth.format(formatter)
            .replaceFirstChar { it.uppercase() }

        // Update calendar
        val days = generateCalendarDays(state)
        calendarAdapter.submitList(days)

        // Update cycle info
        state.cycleInfo.lastPeriodStart?.let { lastStart ->
            val daysSince = java.time.temporal.ChronoUnit.DAYS.between(lastStart, LocalDate.now())
            binding.tvCycleDay.text = getString(R.string.cycle_day_format, daysSince.toInt() + 1)
        } ?: run {
            binding.tvCycleDay.text = getString(R.string.no_cycle_data)
        }

        state.cycleInfo.nextPeriodPrediction?.let { nextPeriod ->
            val daysUntil = java.time.temporal.ChronoUnit.DAYS.between(LocalDate.now(), nextPeriod)
            binding.tvNextPeriod.text = getString(R.string.next_period_format, daysUntil.toInt())
        } ?: run {
            binding.tvNextPeriod.text = getString(R.string.no_prediction)
        }
    }

    private fun generateCalendarDays(state: PeriodCalendarState): List<CalendarDay> {
        val days = mutableListOf<CalendarDay>()
        val yearMonth = state.currentMonth
        val firstDay = yearMonth.atDay(1)
        val lastDay = yearMonth.atEndOfMonth()

        // Добавляем пустые ячейки для выравнивания начала месяца
        val firstDayOfWeek = firstDay.dayOfWeek.value - 1 // 0 = Monday
        repeat(firstDayOfWeek) {
            days.add(CalendarDay(null, CalendarDayType.EMPTY))
        }

        // Добавляем дни месяца
        var currentDate = firstDay
        while (currentDate <= lastDay) {
            val dayType = getDayType(currentDate, state)
            days.add(CalendarDay(currentDate, dayType))
            currentDate = currentDate.plusDays(1)
        }

        return days
    }

    private fun getDayType(date: LocalDate, state: PeriodCalendarState): CalendarDayType {
        // Проверяем, является ли день периодом
        val isPeriod = state.periods.any { period ->
            !date.isBefore(period.startDate) && !date.isAfter(period.endDate)
        }
        if (isPeriod) return CalendarDayType.PERIOD

        // Проверяем, является ли день прогнозируемым периодом
        state.cycleInfo.nextPeriodPrediction?.let { nextPeriod ->
            if (date >= nextPeriod && date < nextPeriod.plusDays(5)) {
                return CalendarDayType.PREDICTED
            }
        }

        // Проверяем фертильное окно
        state.cycleInfo.ovulationPrediction?.let { ovulation ->
            if (date >= ovulation.minusDays(5) && date <= ovulation.plusDays(1)) {
                return CalendarDayType.FERTILE
            }
        }

        return CalendarDayType.NORMAL
    }

    private fun showAddPeriodDialog() {
        val datePicker = MaterialDatePicker.Builder.dateRangePicker()
            .setTitleText(R.string.select_period_dates)
            .build()

        datePicker.addOnPositiveButtonClickListener { selection ->
            val startDate = Instant.ofEpochMilli(selection.first)
                .atZone(ZoneId.systemDefault())
                .toLocalDate()
            val endDate = Instant.ofEpochMilli(selection.second)
            .atZone(ZoneId.systemDefault())
            .toLocalDate()

        val period = Period(
            id = 0,
            startDate = startDate,
            endDate = endDate,
            flow = FlowIntensity.MEDIUM,
            notes = ""
        )
        viewModel.savePeriod(period)
    }

        datePicker.show(parentFragmentManager, "date_picker")
    }

    private fun showEditPeriodDialog(date: LocalDate) {
        val dialog = EditPeriodDialog.newInstance(date)
        dialog.setOnSaveListener { period ->
            viewModel.savePeriod(period)
        }
        dialog.setOnDeleteListener { periodId ->
            viewModel.deletePeriod(periodId)
        }
        dialog.show(parentFragmentManager, "edit_period")
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}

data class CalendarDay(
    val date: LocalDate?,
    val type: CalendarDayType
)

enum class CalendarDayType {
    EMPTY,
    NORMAL,
    PERIOD,
    PREDICTED,
    FERTILE,
    SELECTED
}

