package kr.co.vividnext.sodalive.mypage.alarm

import android.annotation.SuppressLint
import android.app.Activity
import android.app.DatePickerDialog
import android.content.Context
import android.content.Intent
import android.media.AudioManager
import android.os.Bundle
import android.widget.CheckBox
import android.widget.Toast
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
import com.orhanobut.logger.Logger
import kr.co.vividnext.sodalive.base.BaseActivity
import kr.co.vividnext.sodalive.common.Constants
import kr.co.vividnext.sodalive.databinding.ActivityAddAlarmBinding
import kr.co.vividnext.sodalive.mypage.alarm.db.Alarm
import kr.co.vividnext.sodalive.mypage.alarm.select_audio_content.AlarmSelectAudioContentActivity
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale

class AddAlarmActivity : BaseActivity<ActivityAddAlarmBinding>(
    ActivityAddAlarmBinding::inflate
) {
    private val alarmViewModel: AlarmViewModel by viewModels()

    private lateinit var activityResultLauncher: ActivityResultLauncher<Intent>
    private lateinit var dayCheckBoxes: List<CheckBox>

    private var alarmId: Int = 0
    private var selectedContentId: Long = 0
    private var selectedContentTitle = ""
    private var selectedContentCreatorNickname = ""

    private var selectedDateCalendar = Calendar.getInstance()
    private val selectedDays = mutableListOf<String>()

    override fun onCreate(savedInstanceState: Bundle?) {
        activityResultLauncher = registerForActivityResult(
            ActivityResultContracts.StartActivityForResult()
        ) {
            if (it.resultCode == Activity.RESULT_OK) {
                this.selectedContentId = it.data?.getLongExtra(
                    Constants.EXTRA_AUDIO_CONTENT_ID,
                    0
                ) ?: 0

                this.selectedContentTitle = it.data?.getStringExtra(
                    Constants.EXTRA_AUDIO_CONTENT_TITLE
                ) ?: ""

                this.selectedContentCreatorNickname = it.data?.getStringExtra(
                    Constants.EXTRA_AUDIO_CONTENT_CREATOR_NICKNAME
                ) ?: ""

                binding.tvContentTitle.text = selectedContentTitle
            }
        }

        alarmId = intent.getIntExtra(Constants.EXTRA_ALARM_ID, -1)
        super.onCreate(savedInstanceState)
    }

    override fun setupView() {
        dayCheckBoxes = listOf(
            binding.chkSun,
            binding.chkMon,
            binding.chkTue,
            binding.chkWed,
            binding.chkThu,
            binding.chkFri,
            binding.chkSat
        )

        dayCheckBoxes.forEach {
            it.setOnCheckedChangeListener { _, _ -> updateResultText() }
        }

        val audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
        val maxVol = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC)
        binding.sbVolume.max = maxVol
        binding.sbVolume.progress = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC)

        binding.rlSelectAlarmContent.setOnClickListener {
            activityResultLauncher.launch(
                Intent(
                    applicationContext,
                    AlarmSelectAudioContentActivity::class.java
                )
            )
        }

        binding.tvSave.setOnClickListener { saveAlarm() }

        binding.toolbar.tvBack.text = "알람 설정"
        binding.toolbar.tvBack.setOnClickListener { finish() }
        binding.tvCancel.setOnClickListener { finish() }

        binding.ivCalendar.setOnClickListener {
            val datePickerDialog = DatePickerDialog(
                this,
                { _, selectedYear, selectedMonth, selectedDay ->
                    dayCheckBoxes.forEach { it.isChecked = false }
                    selectedDays.clear()

                    selectedDateCalendar.set(selectedYear, selectedMonth, selectedDay)
                    checkAndAdjustDateTime()
                },
                selectedDateCalendar.get(Calendar.YEAR),
                selectedDateCalendar.get(Calendar.MONDAY),
                selectedDateCalendar.get(Calendar.DAY_OF_MONTH)
            )

            datePickerDialog.datePicker.minDate = Calendar.getInstance().timeInMillis
            datePickerDialog.show()
        }

        binding.timePicker.setOnTimeChangedListener { _, _, _ -> checkAndAdjustDateTime() }

        if (alarmId != -1) {
            alarmViewModel.getAlarmById(alarmId).observe(this) { alarm ->
                alarm?.let {
                    binding.etAlarmTitle.setText(it.title)

                    selectedDateCalendar.timeInMillis = it.time
                    binding.timePicker.hour = selectedDateCalendar.get(Calendar.HOUR_OF_DAY)
                    binding.timePicker.minute = selectedDateCalendar.get(Calendar.MINUTE)
                    dayCheckBoxes.forEach { checkBox ->
                        checkBox.isChecked = it.days.contains(checkBox.text.toString())
                    }
                    binding.tvContentTitle.text = it.contentTitle
                    binding.sbVolume.progress = it.volume

                    selectedContentId = it.contentId
                    selectedContentTitle = it.contentTitle
                    selectedContentCreatorNickname = it.contentCreatorNickname
                }
            }
        }
        checkAndAdjustDateTime()
    }

    private fun checkAndAdjustDateTime() {
        val currentCalendar = Calendar.getInstance()

        selectedDateCalendar.set(Calendar.HOUR_OF_DAY, binding.timePicker.hour)
        selectedDateCalendar.set(Calendar.MINUTE, binding.timePicker.minute)
        selectedDateCalendar.set(Calendar.SECOND, 0)
        selectedDateCalendar.set(Calendar.MILLISECOND, 0)

        if (selectedDateCalendar.before(currentCalendar)) {
            selectedDateCalendar.add(Calendar.DAY_OF_MONTH, 1)
        }

        updateResultText()
    }

    @SuppressLint("SetTextI18n")
    private fun updateResultText() {
        selectedDays.clear()
        dayCheckBoxes.filter { it.isChecked }.map { selectedDays.add(it.text.toString()) }

        if (selectedDays.isNotEmpty()) {
            binding.tvDaysOrDate.text = if (selectedDays.size == 7) {
                "매일"
            } else {
                "매주 ${selectedDays.joinToString(", ")}"
            }
        } else {
            val dateFormat = SimpleDateFormat(
                "yyyy년 M월 d일 (E)",
                Locale.getDefault()
            )
            val formattedDate = dateFormat.format(selectedDateCalendar.time)
            binding.tvDaysOrDate.text = formattedDate
        }
    }

    private fun saveAlarm() {
        if (!validate()) return

        val alarmTitle = binding.etAlarmTitle.text.toString()
        val alarmTime = if (selectedDays.isNotEmpty()) {
            val hour = binding.timePicker.hour
            val minute = binding.timePicker.minute

            val calendar = Calendar.getInstance()
            calendar.set(Calendar.HOUR_OF_DAY, hour)
            calendar.set(Calendar.MINUTE, minute)
            calendar.set(Calendar.SECOND, 0)
            calendar.set(Calendar.MILLISECOND, 0)

            calendar.timeInMillis
        } else {
            selectedDateCalendar.timeInMillis
        }

        val calendar = Calendar.getInstance()
        calendar.timeInMillis = alarmTime

        val alarm = Alarm(
            id = if (alarmId == -1) 0 else alarmId,
            title = alarmTitle,
            time = alarmTime,
            contentId = selectedContentId,
            contentTitle = selectedContentTitle,
            contentCreatorNickname = selectedContentCreatorNickname,
            volume = binding.sbVolume.progress,
            days = selectedDays.toList(),
        )

        if (alarmId > 0) {
            alarmViewModel.update(alarm)
        } else {
            alarmViewModel.insert(alarm)
        }
        finish()
    }

    private fun validate(): Boolean {
        if (
            selectedContentId <= 0 ||
            selectedContentTitle.isBlank() ||
            selectedContentCreatorNickname.isBlank()
        ) {
            Toast.makeText(applicationContext, "알람 콘텐츠를 선택하세요", Toast.LENGTH_LONG).show()
            return false
        }

        return true
    }
}
