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

import android.app.AlarmManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import kr.co.vividnext.sodalive.common.Constants
import kr.co.vividnext.sodalive.mypage.alarm.db.Alarm
import kr.co.vividnext.sodalive.mypage.alarm.receiver.AlarmReceiver
import java.util.Calendar

class AlarmScheduler(private val context: Context) {
    fun setAlarm(alarm: Alarm) {
        if (alarm.days.isEmpty()) {
            setOneTimeAlarm(alarm)
        } else {
            setRepeatingAlarm(alarm)
        }
    }

    private fun setOneTimeAlarm(alarm: Alarm) {
        val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager

        val alarmIntent = Intent(context, AlarmReceiver::class.java).let { intent ->
            intent.putExtra(Constants.EXTRA_ALARM_ID, alarm.id)
            createPendingIntent(requestCode = alarm.id, intent)
        }

        val calendar = Calendar.getInstance()
        calendar.timeInMillis = alarm.time

        // 현재 시간보다 이전이면 내일 해당 시간으로 설정
        if (calendar.timeInMillis <= System.currentTimeMillis()) {
            calendar.add(Calendar.DAY_OF_YEAR, 1)
        }

        val info = AlarmManager.AlarmClockInfo(calendar.timeInMillis, alarmIntent)
        alarmManager.setAlarmClock(info, alarmIntent)
    }

    private fun setRepeatingAlarm(alarm: Alarm) {
        val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager

        alarm.days.forEach { day ->
            val requestCode = alarm.id * 10 + getDayOfWeek(day)
            val alarmIntent = Intent(context, AlarmReceiver::class.java).let { intent ->
                intent.putExtra(Constants.EXTRA_ALARM_ID, alarm.id)
                createPendingIntent(requestCode, intent)
            }

            val calendar = getNextAlarmTime(day, alarm.time)

            // 현재 시간이 설정된 알람 시간보다 늦으면 다음 주에 울리도록 설정
            if (calendar.timeInMillis <= System.currentTimeMillis()) {
                calendar.add(Calendar.WEEK_OF_YEAR, 1)
            }

            val info = AlarmManager.AlarmClockInfo(calendar.timeInMillis, alarmIntent)
            alarmManager.setAlarmClock(info, alarmIntent)
        }
    }

    fun cancelAlarm(alarm: Alarm) {
        val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager

        if (alarm.days.isEmpty()) {
            val alarmIntent = createPendingIntent(
                requestCode = alarm.id,
                intent = Intent(context, AlarmReceiver::class.java)
            )
            alarmManager.cancel(alarmIntent)
        } else {
            alarm.days.forEach { day ->
                val requestCode = alarm.id * 10 + getDayOfWeek(day)
                val alarmIntent = createPendingIntent(
                    requestCode,
                    Intent(context, AlarmReceiver::class.java)
                )
                alarmManager.cancel(alarmIntent)
            }
        }
    }

    private fun createPendingIntent(requestCode: Int, intent: Intent): PendingIntent {
        val flags = if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
            PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
        } else {
            PendingIntent.FLAG_UPDATE_CURRENT
        }
        return PendingIntent.getBroadcast(context, requestCode, intent, flags)
    }

    private fun getNextAlarmTime(day: String, timeInMillis: Long): Calendar {
        val calendar = Calendar.getInstance()
        calendar.timeInMillis = timeInMillis
        calendar.set(Calendar.DAY_OF_WEEK, getDayOfWeek(day))
        return calendar
    }

    private fun getDayOfWeek(day: String): Int {
        return when (day) {
            "일" -> Calendar.SUNDAY
            "월" -> Calendar.MONDAY
            "화" -> Calendar.TUESDAY
            "수" -> Calendar.WEDNESDAY
            "목" -> Calendar.THURSDAY
            "금" -> Calendar.FRIDAY
            "토" -> Calendar.SATURDAY
            else -> Calendar.MONDAY
        }
    }
}
