package com.example.shiftalarm

import android.app.AlarmManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Build
import android.util.Log
import android.widget.Toast
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.LocalTime
import java.time.ZoneId
import java.util.concurrent.TimeUnit

val SEOUL_ZONE: ZoneId = ZoneId.of("Asia/Seoul")
const val TAG = "ShiftAlarm"

/**
 * 다크모드 지원 커스텀 토스트 표시
 */
fun showCustomToast(context: Context, message: String, duration: Int = android.widget.Toast.LENGTH_SHORT) {
 try {
 val inflater = android.view.LayoutInflater.from(context)
 val layout = inflater.inflate(R.layout.custom_toast, null)
 val textView = layout.findViewById<android.widget.TextView>(R.id.toastText)
 textView.text = message

 val toast = android.widget.Toast(context)
 toast.duration = duration
 toast.view = layout
 toast.setGravity(android.view.Gravity.BOTTOM or android.view.Gravity.CENTER_HORIZONTAL, 0, 150)
 toast.show()
 } catch (e: Exception) {
 // Fallback to default toast if custom toast fails
 android.widget.Toast.makeText(context, message, duration).show()
 }
}
// ============================================
// 알람 ID 생성
// ============================================
fun getCustomAlarmId(date: LocalDate, uniqueId: Int): Int {
    // Combine date and a unique ID from DB to avoid collisions
    // Using (uniqueId % 1000) to keep it within a reasonable range
    return 200000000 + (date.year % 100) * 1000000 + date.monthValue * 10000 + date.dayOfMonth * 100 + (uniqueId % 100)
}

// ============================================
// 사용자 알람 예약
// ============================================
fun scheduleCustomAlarm(
    context: Context, 
    date: LocalDate, 
    uniqueId: Int, 
    shiftType: String, 
    time: String,
    soundUri: String? = null,
    snoozeMin: Int = 5,
    snoozeRepeat: Int = 3
) {
    val alarmId = getCustomAlarmId(date, uniqueId)
    val label = "사용자:$shiftType"
    
    val parts = time.split(":")
    if (parts.size != 2) return
    val hour = parts[0].toIntOrNull() ?: return
    val min = parts[1].toIntOrNull() ?: return
    
    cancelAlarmInternal(context, alarmId)
    
    val intent = Intent(context, AlarmReceiver::class.java).apply {
        action = "com.example.shiftalarm.ALARM_TRIGGER"
        putExtra("EXTRA_SHIFT", label)
        putExtra("EXTRA_DATE", date.toString())
        putExtra("EXTRA_TIME", time)
        putExtra("EXTRA_ALARM_ID", alarmId)
        putExtra("EXTRA_IS_CUSTOM", true)
        putExtra("EXTRA_UNIQUE_ID", uniqueId) // DB 검증용
        putExtra("EXTRA_SOUND", soundUri)
        putExtra("EXTRA_SNOOZE", snoozeMin)
        putExtra("EXTRA_SNOOZE_REPEAT", snoozeRepeat)
    }
    
    val pendingIntent = PendingIntent.getBroadcast(
        context, alarmId, intent,
        PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
    )

    val targetDateTime = LocalDateTime.of(date, LocalTime.of(hour, min))
        .withSecond(0).withNano(0)

    val alarmTime = targetDateTime.atZone(SEOUL_ZONE).toInstant().toEpochMilli()

    if (alarmTime > System.currentTimeMillis()) {
        setExactAlarm(context, alarmTime, pendingIntent)
        Log.d(TAG, "알람 예약 완료: $date $time (ID: $alarmId)")
    }
}

// ============================================
// 알람 취소 (전체 범위)
// ============================================
fun cancelCustomAlarm(context: Context, date: LocalDate, uniqueId: Int) {
    val alarmId = getCustomAlarmId(date, uniqueId)
    cancelAlarmInternal(context, alarmId)
}

/**
 * 특정 알람의 모든 예약을 완전히 취소합니다.
 * DB에서 삭제하기 전에 반드시 호출해야 합니다.
 * 삭제한 알람이 울리는 문제를 해결하기 위해 365일치 + 과거 알람까지 모두 취소
 */
fun cancelAllCustomAlarmSchedules(context: Context, uniqueId: Int) {
    val today = LocalDate.now(SEOUL_ZONE)
    
    // 1. 과거 30일치 취소 (혹시 모를 과거 예약)
    for (i in -30 until 0) {
        val targetDate = today.plusDays(i.toLong())
        cancelCustomAlarm(context, targetDate, uniqueId)
    }
    
    // 2. 향후 365일치 모든 가능한 ID 취소 (1년치 완전 커버)
    for (i in 0 until 365) {
        val targetDate = today.plusDays(i.toLong())
        cancelCustomAlarm(context, targetDate, uniqueId)
    }
    
    // 3. 스누즈 알람도 취소 (스누즈는 999999 ID 사용)
    cancelSnoozeAlarm(context)
    
    // 4. 테스트 알람도 취소 (테스트는 888888 ID 사용)
    cancelTestAlarm(context)
    
    // 5. 해당 uniqueId와 관련된 모든 가능한 PendingIntent 취소 (추가 안전장치)
    cancelAllPendingIntentsForUniqueId(context, uniqueId)
    
    Log.d(TAG, "알람 예약 완전 취소 완료 (ID: $uniqueId, 범위: -30일 ~ +365일)")
}

/**
 * 특정 uniqueId에 대한 모든 가능한 PendingIntent를 취소합니다.
 * 알람 ID 생성 공식의 역연산을 통해 모든 가능성을 커버합니다.
 */
private fun cancelAllPendingIntentsForUniqueId(context: Context, uniqueId: Int) {
    val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
    
    // uniqueId % 100의 모든 가능한 값에 대해 취소 시도
    val baseId = uniqueId % 100
    
    // 현재 연도 기준으로 여러 해에 걸친 가능한 ID들
    val currentYear = LocalDate.now(SEOUL_ZONE).year % 100
    val years = listOf(currentYear - 1, currentYear, currentYear + 1)
    
    for (year in years) {
        if (year < 0) continue
        for (month in 1..12) {
            for (day in 1..31) {
                try {
                    val alarmId = 200000000 + year * 1000000 + month * 10000 + day * 100 + baseId
                    val intent = Intent(context, AlarmReceiver::class.java).apply {
                        action = "com.example.shiftalarm.ALARM_TRIGGER"
                    }
                    val pendingIntent = PendingIntent.getBroadcast(
                        context, alarmId, intent,
                        PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
                    )
                    alarmManager.cancel(pendingIntent)
                    pendingIntent.cancel()
                } catch (e: Exception) {
                    // 무시 - 유효하지 않은 날짜 조합
                }
            }
        }
    }
    
    Log.d(TAG, "uniqueId $uniqueId 관련 모든 PendingIntent 취소 완료")
}

/**
 * 스누즈 알람 취소
 */
/**
 * 스누즈 알람 취소 - 모든 가능한 스누즈 ID 취소
 */
fun cancelSnoozeAlarm(context: Context) {
    val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
    
    // 주요 스누즈 ID들 취소
    val snoozeIds = listOf(999999, 999998, 999997, 999996, 999995)
    
    for (snoozeId in snoozeIds) {
        val intent = Intent(context, AlarmReceiver::class.java).apply {
            action = "com.example.shiftalarm.SNOOZE"
        }
        val pendingIntent = PendingIntent.getBroadcast(
            context, snoozeId, intent,
            PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
        )
        alarmManager.cancel(pendingIntent)
        pendingIntent.cancel()
    }
    
    Log.d(TAG, "스누즈 알람 취소 완료")
}

/**
 * 테스트 알람 취소
 */
private fun cancelTestAlarm(context: Context) {
    val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
    val intent = Intent(context, AlarmReceiver::class.java).apply {
        action = "com.example.shiftalarm.ALARM_TRIGGER"
    }
    val pendingIntent = PendingIntent.getBroadcast(
        context, 888888, intent,
        PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
    )
    alarmManager.cancel(pendingIntent)
    pendingIntent.cancel()
    Log.d(TAG, "테스트 알람 취소 완료")
}

private fun cancelAlarmInternal(context: Context, alarmId: Int) {
    val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
    val intent = Intent(context, AlarmReceiver::class.java).apply {
        action = "com.example.shiftalarm.ALARM_TRIGGER"
    }
    val pendingIntent = PendingIntent.getBroadcast(
        context, alarmId, intent,
        PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
    )
    alarmManager.cancel(pendingIntent)
    pendingIntent.cancel()
}

// ============================================
// 정밀 알람 설정 (setAlarmClock 우선)
// ============================================
private fun setExactAlarm(context: Context, triggerTime: Long, pendingIntent: PendingIntent) {
    val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
    
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        if (!alarmManager.canScheduleExactAlarms()) {
            Log.e(TAG, "정확한 알람 권한 없음!")
            return
        }
    }

    // setAlarmClock은 Doze 모드에서도 정확하게 작동하며 상단바 알람 아이콘을 활성화함 (신뢰도 최고)
    try {
        val viewIntent = Intent(context, MainActivity::class.java).apply {
            addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP)
        }
        val viewPendingIntent = PendingIntent.getActivity(
            context, 0, viewIntent,
            PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
        )
        
        val clockInfo = AlarmManager.AlarmClockInfo(triggerTime, viewPendingIntent)
        alarmManager.setAlarmClock(clockInfo, pendingIntent)
        Log.d(TAG, "setAlarmClock 예약 성공: ${java.util.Date(triggerTime)}")
    } catch (e: Exception) {
        Log.e(TAG, "setAlarmClock 실패, fallback 사용", e)
        try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerTime, pendingIntent)
                Log.d(TAG, "setExactAndAllowWhileIdle 예약 성공")
            } else {
                alarmManager.setExact(AlarmManager.RTC_WAKEUP, triggerTime, pendingIntent)
                Log.d(TAG, "setExact 예약 성공")
            }
        } catch (e2: Exception) {
            Log.e(TAG, "모든 알람 예약 방법 실패", e2)
        }
    }
}

// ============================================
// 스누즈
// ============================================
fun scheduleSnooze(context: Context, snoozeMin: Int, soundUri: String? = null, snoozeRepeat: Int = 3) {
    val intent = Intent(context, AlarmReceiver::class.java).apply {
        action = "com.example.shiftalarm.SNOOZE"
        putExtra("EXTRA_SHIFT", "SNOOZE")
        putExtra("EXTRA_SOUND", soundUri)
        putExtra("EXTRA_SNOOZE", snoozeMin)
        putExtra("EXTRA_SNOOZE_REPEAT", snoozeRepeat)
    }
    val pendingIntent = PendingIntent.getBroadcast(
        context, 999999, intent,
        PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
    )

    val triggerTime = System.currentTimeMillis() + (snoozeMin * 60 * 1000)
    setExactAlarm(context, triggerTime, pendingIntent)
}

// ============================================
// 테스트 알람 (5초 후)
// ============================================
fun scheduleTestAlarm(context: Context) {
    val intent = Intent(context, AlarmReceiver::class.java).apply {
        action = "com.example.shiftalarm.ALARM_TRIGGER"
        putExtra("EXTRA_SHIFT", "테스트")
    }
    val pendingIntent = PendingIntent.getBroadcast(
        context, 888888, intent,
        PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
    )
    val triggerTime = System.currentTimeMillis() + 5000
    setExactAlarm(context, triggerTime, pendingIntent)
}

// ============================================
// 전체 동기화 (30일치 예약)
// ============================================
suspend fun syncAllAlarms(context: Context) {
    Log.d(TAG, "===== 전체 알람 동기화 시작 (30일) =====")
    val prefs = context.getSharedPreferences("ShiftAlarmPrefs", Context.MODE_PRIVATE)
    val repo = ShiftRepository(context)
    
    val today = LocalDate.now(SEOUL_ZONE)
    val team = prefs.getString("selected_team", "A") ?: "A"
    val factory = prefs.getString("selected_factory", "Jeonju") ?: "Jeonju"
    
    // 1. 기존 알람 모두 취소 (안전장치)
    // Custom 알람의 경우 ID가 uniqueId 기반이므로 모든 가능성 있는 ID를 취소하기는 어려움.
    // 대신 AlarmManager에서 해당 PendingIntent를 정확히 취소해야 함.
    // 하지만 uniqueId를 알 수 없으므로, 모든 날짜 루프에서 취소 시도.
    
    val customAlarms = repo.getAllCustomAlarms()
    
    for (i in 0 until 30) {
        val targetDate = today.plusDays(i.toLong())
        // 기본 알람 ID 취소 (이제 안 쓰지만 하위 호환/청소용)
        val legacyId = 100000000 + (targetDate.year % 100) * 1000000 + targetDate.monthValue * 10000 + targetDate.dayOfMonth * 100
        cancelAlarmInternal(context, legacyId)
        
        // 커스텀 알람 취소
        customAlarms.forEach { alarm ->
            cancelCustomAlarm(context, targetDate, alarm.id)
        }
    }

    if (!ShiftAlarmDefaults.isMasterAlarmEnabled(prefs)) {
        Log.d(TAG, "마스터 알람이 꺼져 있어 예약을 중단합니다.")
        return
    }

    // 2. 새로운 스케줄 생성
    for (i in 0 until 30) {
        val targetDate = today.plusDays(i.toLong())
        val shift = repo.getShift(targetDate, team, factory)
        
        for (alarm in customAlarms) {
            if (!alarm.isEnabled) continue
            
            // 근무 연동 조건 확인
            if (alarm.shiftType == "기타" || alarm.shiftType == shift) {
                scheduleCustomAlarm(
                    context, 
                    targetDate, 
                    alarm.id, 
                    alarm.shiftType, 
                    alarm.time, 
                    alarm.soundUri, 
                    alarm.snoozeInterval, 
                    alarm.snoozeRepeat
                )
            }
        }
    }
    Log.d(TAG, "===== 전체 알람 동기화 완료 =====")
}
