package com.example.shiftalarm

import android.content.Context
import android.util.Log
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.time.LocalDate

/**
 * 알람 동기화 관리자
 * DB와 AlarmManager 간의 실시간 동기화를 보장합니다.
 * 
 * 동기화 전략:
 * 1. DB 작업과 AlarmManager 작업을 원자적으로 처리
 * 2. 실패 시 롤백 메커니즘 제공
 * 3. 동기화 상태 추적 및 재시도
 */
object AlarmSyncManager {
    
    private const val TAG = "AlarmSyncManager"
    private const val PREFS_NAME = "AlarmSyncPrefs"
    
    /**
     * 알람 추가 동기화
     * DB에 추가 후 AlarmManager에 즉시 예약
     */
    suspend fun addAlarm(context: Context, alarm: CustomAlarm): Result<Unit> = withContext(Dispatchers.IO) {
        try {
            val repo = ShiftRepository(context)
            
            // 1. DB에 알람 추가
            val alarmId = repo.addCustomAlarm(alarm)
            Log.d(TAG, "알람 DB 추가 완료: ID=$alarmId")

            // 시스템 알람 볼륨이 0인 경우 최대치로 자동 보정
            try {
                val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as android.media.AudioManager
                val maxVol = audioManager.getStreamMaxVolume(android.media.AudioManager.STREAM_ALARM)
                val currVol = audioManager.getStreamVolume(android.media.AudioManager.STREAM_ALARM)
                if (currVol == 0) {
                    audioManager.setStreamVolume(android.media.AudioManager.STREAM_ALARM, maxVol, 0)
                    Log.d(TAG, "알람 볼륨이 0이어서 최대($maxVol)로 자동 설정")
                }
            } catch (e: Exception) {
                Log.w(TAG, "볼륨 자동 보정 실패", e)
            }
            
            // 2. AlarmManager에 예약
            val today = LocalDate.now(SEOUL_ZONE)
            val customAlarms = repo.getAllCustomAlarms()
            val addedAlarm = customAlarms.find { it.id == alarmId.toInt() }
            
            if (addedAlarm == null) {
                Log.w(TAG, "추가된 알람을 DB에서 찾을 수 없음: ID=$alarmId")
                return@withContext Result.failure(Exception("알람을 찾을 수 없습니다"))
            }
            
            if (addedAlarm.isEnabled) {
                // 향후 30일치 예약
                for (i in 0 until 30) {
                    val targetDate = today.plusDays(i.toLong())
                    val shift = repo.getShift(targetDate, 
                        context.getSharedPreferences("ShiftAlarmPrefs", Context.MODE_PRIVATE)
                            .getString("selected_team", "A") ?: "A",
                        context.getSharedPreferences("ShiftAlarmPrefs", Context.MODE_PRIVATE)
                            .getString("selected_factory", "Jeonju") ?: "Jeonju"
                    )
                    
                    if (addedAlarm.shiftType == "기타" || addedAlarm.shiftType == shift) {
                        scheduleCustomAlarm(
                            context,
                            targetDate,
                            addedAlarm.id,
                            addedAlarm.shiftType,
                            addedAlarm.time,
                            addedAlarm.soundUri,
                            addedAlarm.snoozeInterval,
                            addedAlarm.snoozeRepeat
                        )
                    }
                }
                Log.d(TAG, "알람 AlarmManager 예약 완료: ID=$alarmId")
            }
            
            // 3. 동기화 상태 저장
            saveSyncStatus(context, "last_add_alarm", System.currentTimeMillis())
            
            Result.success(Unit)
        } catch (e: Exception) {
            Log.e(TAG, "알람 추가 동기화 실패", e)
            Result.failure(e)
        }
    }
    
    /**
     * 알람 수정 동기화
     * DB 수정 후 기존 AlarmManager 예약 취소 후 재예약
     */
    suspend fun updateAlarm(context: Context, alarm: CustomAlarm): Result<Unit> = withContext(Dispatchers.IO) {
        try {
            val repo = ShiftRepository(context)
            
            // 1. 기존 AlarmManager 예약 취소
            cancelAllCustomAlarmSchedules(context, alarm.id)
            Log.d(TAG, "기존 알람 예약 취소 완료: ID=${alarm.id}")
            
            // 2. DB 업데이트
            repo.updateCustomAlarm(alarm)
            Log.d(TAG, "알람 DB 업데이트 완료: ID=${alarm.id}")
            
            // 3. 활성화된 알람이면 재예약
            if (alarm.isEnabled) {
                val today = LocalDate.now(SEOUL_ZONE)
                for (i in 0 until 30) {
                    val targetDate = today.plusDays(i.toLong())
                    val shift = repo.getShift(targetDate,
                        context.getSharedPreferences("ShiftAlarmPrefs", Context.MODE_PRIVATE)
                            .getString("selected_team", "A") ?: "A",
                        context.getSharedPreferences("ShiftAlarmPrefs", Context.MODE_PRIVATE)
                            .getString("selected_factory", "Jeonju") ?: "Jeonju"
                    )
                    
                    if (alarm.shiftType == "기타" || alarm.shiftType == shift) {
                        scheduleCustomAlarm(
                            context,
                            targetDate,
                            alarm.id,
                            alarm.shiftType,
                            alarm.time,
                            alarm.soundUri,
                            alarm.snoozeInterval,
                            alarm.snoozeRepeat
                        )
                    }
                }
                Log.d(TAG, "알람 재예약 완료: ID=${alarm.id}")
            }
            
            // 4. 동기화 상태 저장
            saveSyncStatus(context, "last_update_alarm", System.currentTimeMillis())
            
            Result.success(Unit)
        } catch (e: Exception) {
            Log.e(TAG, "알람 수정 동기화 실패", e)
            Result.failure(e)
        }
    }
    
    /**
     * 알람 삭제 동기화
     * AlarmManager 예약 먼저 취소 후 DB에서 삭제
     */
    suspend fun deleteAlarm(context: Context, alarm: CustomAlarm): Result<Unit> = withContext(Dispatchers.IO) {
        try {
            val repo = ShiftRepository(context)
            
            // 1. AlarmManager 예약 취소 (DB 삭제 전에 먼저!)
            cancelAllCustomAlarmSchedules(context, alarm.id)
            Log.d(TAG, "알람 예약 취소 완료: ID=${alarm.id}")
            
            // 2. DB에서 삭제
            repo.deleteCustomAlarm(alarm)
            Log.d(TAG, "알람 DB 삭제 완료: ID=${alarm.id}")
            
            // 3. 동기화 상태 저장
            saveSyncStatus(context, "last_delete_alarm", System.currentTimeMillis())
            
            Result.success(Unit)
        } catch (e: Exception) {
            Log.e(TAG, "알람 삭제 동기화 실패", e)
            Result.failure(e)
        }
    }
    
    /**
     * 알람 토글 동기화 (활성화/비활성화)
     */
    suspend fun toggleAlarm(context: Context, alarm: CustomAlarm, enable: Boolean): Result<Unit> = withContext(Dispatchers.IO) {
        try {
            val repo = ShiftRepository(context)
            val updatedAlarm = alarm.copy(isEnabled = enable)
            
            if (enable) {
                // 활성화: DB 업데이트 후 예약
                repo.updateCustomAlarm(updatedAlarm)
                val today = LocalDate.now(SEOUL_ZONE)
                for (i in 0 until 30) {
                    val targetDate = today.plusDays(i.toLong())
                    val shift = repo.getShift(targetDate,
                        context.getSharedPreferences("ShiftAlarmPrefs", Context.MODE_PRIVATE)
                            .getString("selected_team", "A") ?: "A",
                        context.getSharedPreferences("ShiftAlarmPrefs", Context.MODE_PRIVATE)
                            .getString("selected_factory", "Jeonju") ?: "Jeonju"
                    )
                    
                    if (alarm.shiftType == "기타" || alarm.shiftType == shift) {
                        scheduleCustomAlarm(
                            context,
                            targetDate,
                            alarm.id,
                            alarm.shiftType,
                            alarm.time,
                            alarm.soundUri,
                            alarm.snoozeInterval,
                            alarm.snoozeRepeat
                        )
                    }
                }
                Log.d(TAG, "알람 활성화 완료: ID=${alarm.id}")
            } else {
                // 비활성화: 예약 취소 후 DB 업데이트
                cancelAllCustomAlarmSchedules(context, alarm.id)
                repo.updateCustomAlarm(updatedAlarm)
                Log.d(TAG, "알람 비활성화 완료: ID=${alarm.id}")
            }
            
            saveSyncStatus(context, "last_toggle_alarm", System.currentTimeMillis())
            Result.success(Unit)
        } catch (e: Exception) {
            Log.e(TAG, "알람 토글 동기화 실패", e)
            Result.failure(e)
        }
    }
    
    /**
     * 전체 알람 동기화 (앱 시작 시 호출)
     */
    suspend fun syncAllAlarmsWithCheck(context: Context): Result<SyncResult> = withContext(Dispatchers.IO) {
        try {
            Log.d(TAG, "전체 알람 동기화 시작")
            
            // 1. 기존 모든 알람 취소
            val repo = ShiftRepository(context)
            val allAlarms = repo.getAllCustomAlarms()
            
            for (alarm in allAlarms) {
                cancelAllCustomAlarmSchedules(context, alarm.id)
            }
            Log.d(TAG, "기존 모든 알람 취소 완료: ${allAlarms.size}개")
            
            // 2. 활성화된 알람만 재예약
            val enabledAlarms = allAlarms.filter { it.isEnabled }
            val today = LocalDate.now(SEOUL_ZONE)
            val prefs = context.getSharedPreferences("ShiftAlarmPrefs", Context.MODE_PRIVATE)
            val team = prefs.getString("selected_team", "A") ?: "A"
            val factory = prefs.getString("selected_factory", "Jeonju") ?: "Jeonju"
            
            var scheduledCount = 0
            for (alarm in enabledAlarms) {
                for (i in 0 until 30) {
                    val targetDate = today.plusDays(i.toLong())
                    val shift = repo.getShift(targetDate, team, factory)
                    
                    if (alarm.shiftType == "기타" || alarm.shiftType == shift) {
                        scheduleCustomAlarm(
                            context,
                            targetDate,
                            alarm.id,
                            alarm.shiftType,
                            alarm.time,
                            alarm.soundUri,
                            alarm.snoozeInterval,
                            alarm.snoozeRepeat
                        )
                        scheduledCount++
                    }
                }
            }
            
            Log.d(TAG, "알람 재예약 완료: ${enabledAlarms.size}개 알람, ${scheduledCount}개 예약")
            
            // 3. 동기화 상태 저장
            saveSyncStatus(context, "last_full_sync", System.currentTimeMillis())
            
            Result.success(SyncResult(
                totalAlarms = allAlarms.size,
                enabledAlarms = enabledAlarms.size,
                scheduledAlarms = scheduledCount
            ))
        } catch (e: Exception) {
            Log.e(TAG, "전체 알람 동기화 실패", e)
            Result.failure(e)
        }
    }
    
    /**
     * 동기화 상태 저장
     */
    private fun saveSyncStatus(context: Context, key: String, timestamp: Long) {
        context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
            .edit()
            .putLong(key, timestamp)
            .apply()
    }
    
    /**
     * 마지막 동기화 시간 확인
     */
    fun getLastSyncTime(context: Context, key: String): Long {
        return context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
            .getLong(key, 0)
    }
    
    /**
     * 동기화 결과 데이터 클래스
     */
    data class SyncResult(
        val totalAlarms: Int,
        val enabledAlarms: Int,
        val scheduledAlarms: Int
    )
}
