package com.example.shiftalarm

import android.app.KeyguardManager
import android.content.Context
import android.content.Intent
import android.media.AudioAttributes
import android.media.AudioManager
import android.media.MediaPlayer
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.os.PowerManager
import android.os.VibrationEffect
import android.os.Vibrator
import android.util.Log
import android.view.MotionEvent
import android.view.View
import android.view.WindowManager
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.activity.enableEdgeToEdge
import com.example.shiftalarm.databinding.ActivityAlarmBinding
import androidx.core.content.ContextCompat
import java.time.LocalDate
import java.time.format.DateTimeFormatter
import kotlin.math.abs

class AlarmActivity : AppCompatActivity() {

    private lateinit var binding: ActivityAlarmBinding
    private var mediaPlayer: MediaPlayer? = null
    private var vibrator: Vibrator? = null
    private var startX = 0f

    // 5분 후 자동 스누즈
    private val autoStopHandler = Handler(Looper.getMainLooper())
    private val AUTO_STOP_DELAY = 5L * 60 * 1000

    override fun onCreate(savedInstanceState: Bundle?) {
        // 중요: 잠금 화면 위 표시 설정을 가장 먼저 적용
        setupLockScreenFlags()
        
        super.onCreate(savedInstanceState)
        
        // ForegroundService가 실행 중이면 먼저 중지
        stopService(Intent(this, AlarmForegroundService::class.java))
        
        // Service 중지 후 약간의 지연을 두어 AudioFocus가 완전히 해제되도록 함
        try {
            Thread.sleep(100)
        } catch (e: InterruptedException) {
            // 무시
        }
        
        enableEdgeToEdge()
        binding = ActivityAlarmBinding.inflate(layoutInflater)
        binding.root.background = ContextCompat.getDrawable(this, R.drawable.bg_alarm_gradient)
        setContentView(binding.root)

        // 추가 윈도우 플래그 설정
        setupWindowFlags()

        val shift = intent.getStringExtra("EXTRA_SHIFT") ?: "근무"
        binding.tvShiftType.text = if (shift == "SNOOZE") "다시 울림 알람" else "[$shift] 근무 알람"

        val now = java.util.Calendar.getInstance()
        val amPm = if (now.get(java.util.Calendar.AM_PM) == java.util.Calendar.AM) "오전" else "오후"
        val hour = now.get(java.util.Calendar.HOUR)
        val hourText = if (hour == 0) 12 else hour
        val min = now.get(java.util.Calendar.MINUTE)
        binding.tvCurrentTime.text = String.format("%s %d:%02d", amPm, hourText, min)

        val today = LocalDate.now()
        val dayOfWeek = today.dayOfWeek.getDisplayName(java.time.format.TextStyle.FULL, java.util.Locale.KOREAN)
        binding.tvDate.text = String.format("%d월 %d일 %s", today.monthValue, today.dayOfMonth, dayOfWeek)

        // 알람 시작 (화면 상태와 무관하게 항상 실행)
        startAlarm()
        
        // 마스터 알람이 꺼져있으면 알람 화면을 즉시 종료
        val prefs = getSharedPreferences("ShiftAlarmPrefs", Context.MODE_PRIVATE)
        if (!ShiftAlarmDefaults.isMasterAlarmEnabled(prefs)) {
            Toast.makeText(this, "전체 알람이 꺼져있습니다.", Toast.LENGTH_SHORT).show()
            finish()
            return
        }
        setupControls()

        // 5분 후 자동 스누즈
        autoStopHandler.postDelayed({
            Toast.makeText(this, "알람이 자동으로 다시 울림 설정되었습니다.", Toast.LENGTH_LONG).show()
            snoozeAlarm()
            stopAlarm()
            finish()
        }, AUTO_STOP_DELAY)
        
        // 키가드(잠금화면) 상태 변화 리스너 등록
        registerKeyguardListener()
    }
    
    /**
     * 잠금 화면 관련 플래그를 super.onCreate 이전에 설정
     */
    private fun setupLockScreenFlags() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
            setShowWhenLocked(true)
            setTurnScreenOn(true)
        }
    }

    private fun setupWindowFlags() {
        // ========================================
        // 알람 화면이 패턴/지문보다 먼저 표시되도록 설정
        // ========================================
        // 중요: requestDismissKeyguard()를 호출하면 패턴/지문이 먼저 뜸
        // 알람 화면을 먼저 띄우려면 FLAG_SHOW_WHEN_LOCKED만 사용해야 함
        
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
            // 1. 가장 먼저: 화면 켜기 + 잠금화면 위에 표시
            setShowWhenLocked(true)
            setTurnScreenOn(true)
        }
        
        // 2. 화면 켜짐 유지
        window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
        
        // 3. 하위 호환성: Android 8.0 이하
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O_MR1) {
            @Suppress("DEPRECATION")
            window.addFlags(
                WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
                WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
            )
        }
        
        // 4. Android 14+ 추가 플래그
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
            window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN)
            window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM)
        }
        
        // 5. Android 10+ 레이아웃
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)
        }
        
        // 6. 전체화면 모드 (모든 기기 공통)
        setFullscreenMode()
    }
    
    /**
     * 전체화면 모드 설정
     */
    private fun isSamsungDevice(): Boolean {
        val manufacturer = Build.MANUFACTURER?.lowercase() ?: ""
        val brand = Build.BRAND?.lowercase() ?: ""
        return manufacturer.contains("samsung") || brand.contains("samsung")
    }
    
    /**
     * 전체화면 모드 설정
     */
    private fun setFullscreenMode() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            // Android 11+ (API 30+): WindowInsetsController 사용
            window.setDecorFitsSystemWindows(false)
            window.insetsController?.let { controller ->
                controller.hide(android.view.WindowInsets.Type.statusBars() or android.view.WindowInsets.Type.navigationBars())
                controller.systemBarsBehavior = android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
            }
        } else {
            // Android 10 이하: systemUiVisibility 사용
            @Suppress("DEPRECATION")
            window.decorView.systemUiVisibility = (
                View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY or
                View.SYSTEM_UI_FLAG_FULLSCREEN or
                View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or
                View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
                View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
                View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
            )
        }
    }

    private fun setupControls() {
        val snoozeInterval = intent.getIntExtra("EXTRA_SNOOZE_INTERVAL", 5)
        binding.tvSnoozeText.text = "다시 울림 (${snoozeInterval}분)"

        binding.btnSnooze.setOnClickListener {
            handleSnooze()
        }

        // Omni-directional Swipe & Tap to Dismiss (Samsung One UI Clock Style)
        var startX = 0f
        var startY = 0f
        var isMoved = false
        val dismissBtn = binding.btnDismiss
        val maxSwipe = dpToPx(80f).toFloat()

        dismissBtn.setOnTouchListener { v, event ->
            when (event.action) {
                MotionEvent.ACTION_DOWN -> {
                    startX = event.rawX
                    startY = event.rawY
                    isMoved = false
                    v.animate().cancel()
                    v.scaleX = 0.96f
                    v.scaleY = 0.96f
                    true
                }
                MotionEvent.ACTION_MOVE -> {
                    val dx = event.rawX - startX
                    val dy = event.rawY - startY
                    val distance = Math.hypot(dx.toDouble(), dy.toDouble()).toFloat()
                    
                    if (distance > 10f) {
                        isMoved = true
                    }

                    val clampedDx = dx.coerceIn(-maxSwipe, maxSwipe)
                    val clampedDy = dy.coerceIn(-maxSwipe, maxSwipe)
                    v.translationX = clampedDx
                    v.translationY = clampedDy

                    val ratio = (distance / maxSwipe).coerceAtMost(1f)
                    v.scaleX = 0.96f + (ratio * 0.18f)
                    v.scaleY = 0.96f + (ratio * 0.18f)
                    binding.pulseCircle.alpha = 0.4f + (ratio * 0.6f)
                    true
                }
                MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
                    val dx = event.rawX - startX
                    val dy = event.rawY - startY
                    val distance = Math.hypot(dx.toDouble(), dy.toDouble()).toFloat()

                    // Trigger dismiss if swiped past threshold or tapped
                    if (!isMoved || distance > maxSwipe * 0.5f) {
                        triggerDismiss()
                    } else {
                        // Spring back reset
                        v.animate()
                            .translationX(0f)
                            .translationY(0f)
                            .scaleX(1f)
                            .scaleY(1f)
                            .setDuration(250)
                            .setInterpolator(android.view.animation.OvershootInterpolator(1.5f))
                            .start()
                    }
                    true
                }
                else -> false
            }
        }

        // Dual Wave Breathing Animation (Samsung Ambient Glow)
        fun startPulse() {
            binding.pulseCircle.scaleX = 0.8f
            binding.pulseCircle.scaleY = 0.8f
            binding.pulseCircle.alpha = 0.3f

            binding.ambientRing.scaleX = 0.9f
            binding.ambientRing.scaleY = 0.9f
            binding.ambientRing.alpha = 0.5f

            binding.pulseCircle.animate()
                .scaleX(1.35f).scaleY(1.35f).alpha(0.8f)
                .setDuration(1600)
                .withEndAction {
                    binding.pulseCircle.animate()
                        .scaleX(0.8f).scaleY(0.8f).alpha(0.3f)
                        .setDuration(1600)
                        .withEndAction { if (!isFinishing) startPulse() }
                        .start()
                }
                .start()

            binding.ambientRing.animate()
                .scaleX(1.15f).scaleY(1.15f).alpha(0.85f)
                .setDuration(1600)
                .withEndAction {
                    binding.ambientRing.animate()
                        .scaleX(0.9f).scaleY(0.9f).alpha(0.5f)
                        .setDuration(1600)
                        .start()
                }
                .start()
        }
        startPulse()
    }

    private fun triggerDismiss() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            (getSystemService(Context.VIBRATOR_SERVICE) as? Vibrator)?.vibrate(
                VibrationEffect.createOneShot(50, VibrationEffect.DEFAULT_AMPLITUDE)
            )
        } else {
            @Suppress("DEPRECATION")
            (getSystemService(Context.VIBRATOR_SERVICE) as? Vibrator)?.vibrate(50)
        }
        Toast.makeText(this, "알람이 해제되었습니다.", Toast.LENGTH_SHORT).show()
        stopAlarm()
        finish()
    }

    private fun handleSnooze() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            (getSystemService(Context.VIBRATOR_SERVICE) as? Vibrator)?.vibrate(
                VibrationEffect.createOneShot(50, VibrationEffect.DEFAULT_AMPLITUDE)
            )
        } else {
            @Suppress("DEPRECATION")
            (getSystemService(Context.VIBRATOR_SERVICE) as? Vibrator)?.vibrate(50)
        }
        val snoozeRepeat = intent.getIntExtra("EXTRA_SNOOZE_REPEAT", 3)
        val text = if (snoozeRepeat == 99) "다시 울림 설정됨" else "다시 울림 (${snoozeRepeat}회 남음)"
        Toast.makeText(this, text, Toast.LENGTH_SHORT).show()
        snoozeAlarm()
        stopAlarm()
        finish()
    }

    private fun dpToPx(dp: Float): Int {
        return (dp * resources.displayMetrics.density).toInt()
    }

    private fun startAlarm() {
        if (mediaPlayer?.isPlaying == true) {
            Log.d("AlarmActivity", "MediaPlayer가 이미 실행 중")
            return
        }

        val soundUriStr = intent.getStringExtra("EXTRA_SOUND")
        val alarmUri = if (!soundUriStr.isNullOrEmpty()) {
            Uri.parse(soundUriStr)
        } else {
            val prefs = getSharedPreferences("ShiftAlarmPrefs", Context.MODE_PRIVATE)
            val globalUriStr = prefs.getString("alarm_uri", null)
            if (globalUriStr != null) Uri.parse(globalUriStr)
            else android.provider.Settings.System.DEFAULT_ALARM_ALERT_URI
        }

        // AudioAttributes 강화: 무음/진동 모드에서도 알람음이 울리도록
        val audioAttrs = AudioAttributes.Builder()
            .setUsage(AudioAttributes.USAGE_ALARM)
            .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
            .setFlags(AudioAttributes.FLAG_AUDIBILITY_ENFORCED)
            .build()

        // AudioManager를 통해 알람 볼륨 설정 및 무음 모드 우회
        val audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
        
        // 무음 모드에서도 알람음이 울리도록 STREAM_ALARM 사용 (벨소리와 독립)
        // 알람 스트림은 다른 스트림과 달리 무음 모드에서도 울림
        val originalRingerMode = audioManager.ringerMode
        
        // 알람 볼륨을 최대로 설정 (사용자가 나중에 조정 가능)
        try {
            val maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_ALARM)
            audioManager.setStreamVolume(AudioManager.STREAM_ALARM, maxVolume, 0)
            Log.d("AlarmActivity", "알람 볼륨 설정: $maxVolume (RingerMode: $originalRingerMode)")
        } catch (e: Exception) {
            Log.w("AlarmActivity", "알람 볼륨 설정 실패", e)
        }

        var mediaPlayerStarted = false

        try {
            mediaPlayer?.release()
            mediaPlayer = MediaPlayer().apply {
                setAudioAttributes(audioAttrs)
                setDataSource(this@AlarmActivity, alarmUri!!)
                isLooping = true
                setVolume(1.0f, 1.0f)  // 최대 볼륨
                prepare()
                start()
            }
            mediaPlayerStarted = true
            Log.d("AlarmActivity", "MediaPlayer 시작 성공 (사용자 지정음)")
        } catch (e: Exception) {
            Log.e("AlarmActivity", "MediaPlayer 시작 실패 (사용자 지정음), fallback 시도", e)
            
            // Fallback 1: 시스템 기본 알람음
            try {
                val fallback = android.provider.Settings.System.DEFAULT_ALARM_ALERT_URI
                mediaPlayer = MediaPlayer().apply {
                    setAudioAttributes(audioAttrs)
                    setDataSource(this@AlarmActivity, fallback)
                    isLooping = true
                    setVolume(1.0f, 1.0f)
                    prepare()
                    start()
                }
                mediaPlayerStarted = true
                Log.d("AlarmActivity", "MediaPlayer 시작 성공 (Fallback 1: 시스템 기본)")
            } catch (e2: Exception) {
                Log.e("AlarmActivity", "Fallback 1 실패", e2)
                
                // Fallback 2: RingtoneManager에서 기본 알람 가져오기
                try {
                    val ringtoneUri = android.media.RingtoneManager.getDefaultUri(android.media.RingtoneManager.TYPE_ALARM)
                    mediaPlayer = MediaPlayer().apply {
                        setAudioAttributes(audioAttrs)
                        setDataSource(this@AlarmActivity, ringtoneUri)
                        isLooping = true
                        setVolume(1.0f, 1.0f)
                        prepare()
                        start()
                    }
                    mediaPlayerStarted = true
                    Log.d("AlarmActivity", "MediaPlayer 시작 성공 (Fallback 2: RingtoneManager)")
                } catch (e3: Exception) {
                    Log.e("AlarmActivity", "모든 MediaPlayer 시작 실패", e3)
                }
            }
        }

        // 진동 시작 (알람음과 독립적으로 - 알람음 실패필도 진동은 울림)
        vibrator = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
        try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                val vibrationEffect = VibrationEffect.createWaveform(longArrayOf(0, 1000, 500, 1000), 0)
                vibrator?.vibrate(vibrationEffect)
            } else {
                @Suppress("DEPRECATION")
                vibrator?.vibrate(longArrayOf(0, 1000, 500, 1000), 0)
            }
            Log.d("AlarmActivity", "진동 시작 성공")
        } catch (e: Exception) {
            Log.e("AlarmActivity", "진동 시작 실패", e)
        }
        
        // 알람음 시작 실패 시 토스트 메시지
        if (!mediaPlayerStarted) {
            Toast.makeText(this, "알람음 재생에 실패했습니다. 진동으로 알려드립니다.", Toast.LENGTH_LONG).show()
        }
    }

    private fun snoozeAlarm() {
        val snoozeMin = intent.getIntExtra("EXTRA_SNOOZE", 5)
        val snoozeRepeat = intent.getIntExtra("EXTRA_SNOOZE_REPEAT", 3)
        val soundUriStr = intent.getStringExtra("EXTRA_SOUND")
        
        if (snoozeRepeat > 0) {
            val nextRepeat = if (snoozeRepeat == 99) 99 else snoozeRepeat - 1
            scheduleSnooze(this, snoozeMin, soundUriStr, nextRepeat)
        } else {
            Toast.makeText(this, "다시 울림 횟수를 모두 소모하여 알람을 종료합니다.", Toast.LENGTH_SHORT).show()
        }
    }

    private fun stopAlarm() {
        stopService(Intent(this, AlarmForegroundService::class.java))

        try {
            mediaPlayer?.let {
                if (it.isPlaying) it.stop()
                it.release()
            }
        } catch (e: Exception) {}
        mediaPlayer = null
        
        try {
            vibrator?.cancel()
        } catch (e: Exception) {}
        vibrator = null

        val nm = getSystemService(Context.NOTIFICATION_SERVICE) as android.app.NotificationManager
        nm.cancel(1)
    }

    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        setIntent(intent)
        val shift = intent.getStringExtra("EXTRA_SHIFT") ?: "근무"
        binding.tvShiftType.text = if (shift == "SNOOZE") "다시 울림 알람" else "[$shift] 근무 알람"
        
        stopAlarm()
        startAlarm()
    }

    override fun onAttachedToWindow() {
        super.onAttachedToWindow()
        // 화면 켜짐 및 잠금 화면 위 표시 재적용
        setupWindowFlags()
    }

    override fun onDestroy() {
        super.onDestroy()
        autoStopHandler.removeCallbacksAndMessages(null)
        stopAlarm()
        unregisterKeyguardListener()
    }

    // ========================================
    // 키가드(잠금화면) 상태 감지 및 알람 해제 처리
    // ========================================
    private var keyguardManager: KeyguardManager? = null
    private var keyguardCallback: KeyguardManager.KeyguardDismissCallback? = null
    
    /**
     * 키가드(잠금화면) 상태 변화를 감지하여 알람을 적절히 처리
     * 안드로이드 버전별로 다른 방식으로 처리
     */
    private fun registerKeyguardListener() {
        keyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as? KeyguardManager
        
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            // Android 8.0+: KeyguardDismissCallback 사용
            keyguardCallback = object : KeyguardManager.KeyguardDismissCallback() {
                override fun onDismissError() {
                    Log.e("AlarmActivity", "Keyguard dismiss error")
                }

                override fun onDismissSucceeded() {
                    Log.d("AlarmActivity", "Keyguard dismissed successfully - 사용자가 패턴/지문으로 해제함")
                    // 패턴/지문 해제 후 알람 계속 울리게 하려면 여기서 아무것도 하지 않음
                    // 알람을 자동으로 멈추려면: stopAlarm(); finish()
                }

                override fun onDismissCancelled() {
                    Log.d("AlarmActivity", "Keyguard dismiss cancelled")
                }
            }
        }
    }
    
    private fun unregisterKeyguardListener() {
        keyguardCallback = null
    }
    
    /**
     * 현재 키가드(잠금화면)가 잠겨있는지 확인
     */
    private fun isKeyguardLocked(): Boolean {
        return keyguardManager?.isKeyguardLocked ?: false
    }
    
    /**
     * 현재 키가드(잠금화면)가 보안 잠금(패턴/PIN/지문)을 사용하는지 확인
     */
    private fun isKeyguardSecure(): Boolean {
        return keyguardManager?.isKeyguardSecure ?: false
    }

    override fun onPause() {
        super.onPause()
        // 홈 버튼이나 다른 앱으로 전환 시 알람 계속 울리도록 함
        // 사용자가 의도적으로 알람을 해제하지 않았으므로
        Log.d("AlarmActivity", "onPause - 알람 계속 유지")
    }

    override fun onStop() {
        super.onStop()
        // 알람 화면이 백그라운드로 갔을 때
        // 잠금화면이 다시 잠기면 알람을 멈추지 않고 계속 유지
        Log.d("AlarmActivity", "onStop - 알람 계속 유지")
    }

    override fun onWindowFocusChanged(hasFocus: Boolean) {
        super.onWindowFocusChanged(hasFocus)
        if (hasFocus) {
            // 알람 화면이 다시 포커스를 받으면 전체화면 모드 재적용
            setFullscreenMode()
            Log.d("AlarmActivity", "Window focus regained")
        }
    }
}
