package com.example.shiftalarm

import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.graphics.Color
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import android.widget.TimePicker
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import com.google.android.material.materialswitch.MaterialSwitch
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import com.example.shiftalarm.databinding.FragmentSettingsAlarmBinding
import kotlinx.coroutines.launch
import org.json.JSONArray
import org.json.JSONObject
import java.time.LocalDate

class FragmentSettingsAlarm : Fragment(), SharedPreferences.OnSharedPreferenceChangeListener {

    private var _binding: FragmentSettingsAlarmBinding? = null
    private val binding get() = _binding!!
    private val PREFS_NAME = "ShiftAlarmPrefs"
    private lateinit var repository: ShiftRepository
    private var customAlarms: MutableList<CustomAlarm> = mutableListOf()
    private val collapsedGroups = mutableSetOf<String>()

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding = FragmentSettingsAlarmBinding.inflate(inflater, container, false)
        repository = ShiftRepository(requireContext())
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        
        val prefs = requireContext().getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
        prefs.registerOnSharedPreferenceChangeListener(this)
        
        setupListeners()
        loadSettings() 
    }
    
    override fun onResume() {
        super.onResume()
        refreshAlarmList()
    }

    override fun onDestroyView() {
        super.onDestroyView()
        val prefs = requireContext().getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
        prefs.unregisterOnSharedPreferenceChangeListener(this)
        _binding = null
    }

    override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
        if (key == "master_alarm_enabled") {
            sharedPreferences?.let {
                updateMasterToggleUI(ShiftAlarmDefaults.isMasterAlarmEnabled(it))
            }
        }
    }

    private fun loadSettings() {
        val prefs = requireContext().getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
        
        // Master Toggle Button State
        updateMasterToggleUI(ShiftAlarmDefaults.isMasterAlarmEnabled(prefs))

        // Migrate and Refresh
        lifecycleScope.launch {
            migrateFromPrefsIfNecessary()
            refreshAlarmList()
        }
    }

    private suspend fun migrateFromPrefsIfNecessary() {
        val prefs = requireContext().getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
        val legacyJson = prefs.getString("custom_alarms", null)
        if (legacyJson != null) {
            try {
                val arr = JSONArray(legacyJson)
                for (i in 0 until arr.length()) {
                    val obj = arr.getJSONObject(i)
                    val alarm = CustomAlarm(
                        time = obj.getString("time"),
                        shiftType = obj.getString("shiftType"),
                        isEnabled = obj.optBoolean("enabled", true),
                        soundUri = obj.optString("soundUri", null),
                        snoozeInterval = obj.optInt("snoozeInterval", 5),
                        snoozeRepeat = obj.optInt("snoozeRepeat", 3)
                    )
                    repository.addCustomAlarm(alarm)
                }
                // Clear legacy data
                prefs.edit().remove("custom_alarms").apply()
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }

    private fun refreshAlarmList() {
        lifecycleScope.launch {
            customAlarms = repository.getAllCustomAlarms().toMutableList()
            if (customAlarms.isEmpty()) {
                // 주간, 석간, 야간 기본 알람 자동 생성
                val defaultAlarms = listOf(
                    CustomAlarm(time = "07:00", shiftType = "주간", isEnabled = true),
                    CustomAlarm(time = "15:00", shiftType = "석간", isEnabled = true),
                    CustomAlarm(time = "23:00", shiftType = "야간", isEnabled = true)
                )
                for (def in defaultAlarms) {
                    repository.addCustomAlarm(def)
                }
                customAlarms = repository.getAllCustomAlarms().toMutableList()
                syncAllAlarms(requireContext())
            }
            refreshUI()
        }
    }

    private val soundTitleCache = mutableMapOf<String?, String>()

    private fun updateMasterToggleUI(isEnabled: Boolean) {
        if (isEnabled) {
            binding.tvMasterStatus.text = "전체 알람 켜짐"
            binding.tvMasterStatus.setTextColor(ContextCompat.getColor(requireContext(), R.color.primary))
            binding.tvMasterStatus.backgroundTintList = android.content.res.ColorStateList.valueOf(Color.parseColor("#E3F2FD"))
        } else {
            binding.tvMasterStatus.text = "전체 알람 꺼짐"
            binding.tvMasterStatus.setTextColor(ContextCompat.getColor(requireContext(), R.color.shift_red))
            binding.tvMasterStatus.backgroundTintList = android.content.res.ColorStateList.valueOf(Color.parseColor("#FFEBEE"))
        }
    }

    private fun setupListeners() {
        val prefs = requireContext().getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)

        binding.tvMasterStatus.setOnClickListener {
            val isEnabled = !ShiftAlarmDefaults.isMasterAlarmEnabled(prefs)
            prefs.edit().putBoolean("master_alarm_enabled", isEnabled).apply()
            updateMasterToggleUI(isEnabled)
            
            val message = if (isEnabled) "전체 알람이 켜졌습니다." else "전체 알람이 꺼졌습니다."
            Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show()
            
            // Resync immediately
             lifecycleScope.launch { syncAllAlarms(requireContext()) }
        }

        binding.btnAddCustomAlarm.setOnClickListener {
            showEditDialog(
                title = "새 알람 추가",
                currentTime = "07:00",
                shiftType = "주간",
                existingAlarm = null,
                isNew = true
            )
        }

        binding.btnTestAlarm.setOnClickListener {
            scheduleTestAlarm(requireContext())
        }
    }
    
    private fun refreshUI() {
        val container = binding.alarmListContainer
        container.removeAllViews()

        if (customAlarms.isEmpty()) {
            val emptyView = TextView(requireContext()).apply {
                text = "등록된 알람이 없습니다.\n아래 [새 알람 추가] 버튼을 눌러 추가해보세요."
                textSize = 14f
                setTextColor(ContextCompat.getColor(context, R.color.text_tertiary))
                gravity = android.view.Gravity.CENTER
                setPadding(0, dpToPx(40f), 0, dpToPx(40f))
            }
            container.addView(emptyView)
            return
        }

        // Group alarms by Shift Type: 주간, 석간, 야간, 주간 맞교대, 야간 맞교대, 기타
        val groups = linkedMapOf<String, MutableList<CustomAlarm>>()
        val displayOrder = listOf("주간", "석간", "야간", "주간 맞교대", "야간 맞교대", "기타")
        
        for (alarm in customAlarms) {
            val category = when(alarm.shiftType) {
                "주간" -> "주간"
                "석간" -> "석간"
                "야간" -> "야간"
                "주간 맞교대", "주맞" -> "주간 맞교대"
                "야간 맞교대", "야맞" -> "야간 맞교대"
                else -> "기타"
            }
            groups.getOrPut(category) { mutableListOf() }.add(alarm)
        }

        for (category in displayOrder) {
            val groupAlarms = groups[category] ?: continue
            if (groupAlarms.isEmpty()) continue

            // 1. Group Header View
            val headerView = layoutInflater.inflate(R.layout.item_alarm_group_header, container, false)
            val ivExpand = headerView.findViewById<ImageView>(R.id.ivExpand)
            val tvGroupName = headerView.findViewById<TextView>(R.id.tvGroupName)
            val tvAlarmCount = headerView.findViewById<TextView>(R.id.tvAlarmCount)
            val groupSwitch = headerView.findViewById<MaterialSwitch>(R.id.groupSwitch)

            tvGroupName.text = "$category 알람"
            tvAlarmCount.text = "${groupAlarms.size}개 알람"

            val allEnabled = groupAlarms.all { it.isEnabled }
            groupSwitch.isChecked = allEnabled

            val isCollapsed = collapsedGroups.contains(category)
            ivExpand.rotation = if (isCollapsed) 0f else 45f

            // Group Switch Toggle (Master On/Off for this group)
            groupSwitch.setOnCheckedChangeListener { _, isChecked ->
                lifecycleScope.launch {
                    for (alarm in groupAlarms) {
                        if (alarm.isEnabled != isChecked) {
                            AlarmSyncManager.toggleAlarm(requireContext(), alarm, isChecked)
                        }
                    }
                    refreshAlarmList()
                }
            }

            // Container for child rows
            val childrenContainer = LinearLayout(requireContext()).apply {
                orientation = LinearLayout.VERTICAL
                visibility = if (isCollapsed) View.GONE else View.VISIBLE
            }

            // Click header to collapse/expand with smooth accordion animation
            headerView.setOnClickListener {
                val willExpand = collapsedGroups.contains(category)
                
                // 1. Smooth accordion expand/collapse transition
                val transition = android.transition.AutoTransition().apply {
                    duration = 250
                    interpolator = android.view.animation.AccelerateDecelerateInterpolator()
                }
                android.transition.TransitionManager.beginDelayedTransition(container, transition)

                // 2. Smooth rotation between '+' (0 deg) and 'x' (45 deg)
                val targetRotation = if (willExpand) 45f else 0f
                ivExpand.animate()
                    .rotation(targetRotation)
                    .setDuration(250)
                    .setInterpolator(androidx.core.view.animation.PathInterpolatorCompat.create(0.22f, 1.0f, 0.36f, 1.0f))
                    .start()

                if (willExpand) {
                    collapsedGroups.remove(category)
                    childrenContainer.visibility = View.VISIBLE
                } else {
                    collapsedGroups.add(category)
                    childrenContainer.visibility = View.GONE
                }
            }

            container.addView(headerView)

            // 2. Add Alarm Rows under Group
            for (alarm in groupAlarms) {
                val item = createAlarmRow(
                    alarm.shiftType,
                    alarm.time,
                    alarm.isEnabled,
                    isCustom = true,
                    snoozeMin = alarm.snoozeInterval,
                    snoozeRepeat = alarm.snoozeRepeat,
                    soundUri = alarm.soundUri
                ) { isToggle, _ ->
                    if (isToggle) {
                        lifecycleScope.launch {
                            val enable = !alarm.isEnabled
                            AlarmSyncManager.toggleAlarm(requireContext(), alarm, enable)
                            refreshAlarmList()
                        }
                    } else {
                        showEditDialog("사용자 알람", alarm.time, alarm.shiftType, existingAlarm = alarm, isNew = false)
                    }
                }
                childrenContainer.addView(item)
            }

            container.addView(childrenContainer)
        }
    }
    
    private fun createAlarmRow(
        shiftName: String, 
        time: String, 
        isEnabled: Boolean, 
        isCustom: Boolean, 
        snoozeMin: Int,
        snoozeRepeat: Int,
        soundUri: String?,
        onAction: (isToggle: Boolean, isLongClick: Boolean) -> Unit
    ): View {
        val view = layoutInflater.inflate(R.layout.item_alarm_unified, binding.alarmListContainer, false)
        view.isFocusable = true
        
        val shiftIndicator = view.findViewById<TextView>(R.id.shiftIndicator)
        val tvTime = view.findViewById<TextView>(R.id.tvTime)
        val tvAmPm = view.findViewById<TextView>(R.id.tvAmPm)
        val tvSummary = view.findViewById<TextView>(R.id.tvSummary)
        val alarmSwitch = view.findViewById<MaterialSwitch>(R.id.alarmSwitch)
        val layoutAlarmSwitch = view.findViewById<View>(R.id.layoutAlarmSwitch)
        
        val shortName = when(shiftName) {
            "주간" -> "주"
            "석간" -> "석"
            "야간" -> "야"
            "주간 맞교대" -> "주맞"
            "야간 맞교대" -> "야맞"
            "기타" -> "기타"
            else -> shiftName.take(1)
        }
        shiftIndicator.text = shortName
        
        val colorRes = when(shiftName) {
            "주간" -> R.color.shift_lemon
            "석간" -> R.color.shift_seok
            "야간" -> R.color.shift_ya
            "주간 맞교대" -> R.color.shift_jumat
            "야간 맞교대" -> R.color.shift_yamat
            else -> R.color.shift_gray
        }
        
        val context = requireContext()
        val color = ContextCompat.getColor(context, colorRes)
        val drawable = ContextCompat.getDrawable(context, R.drawable.bg_shift_stroke_v4) as android.graphics.drawable.GradientDrawable
        drawable.mutate()
        drawable.setStroke(dpToPx(2.5f), color)
        shiftIndicator.background = drawable
        shiftIndicator.setTextColor(color)
        
        try {
            val parts = time.split(":")
            val h24 = parts[0].toInt()
            val m = parts[1].toInt()
            val h12 = if (h24 % 12 == 0) 12 else h24 % 12
            tvTime.text = String.format("%02d:%02d", h12, m)
            tvAmPm.text = if (h24 < 12) "오전" else "오후"
            
            if (!isEnabled) {
                tvTime.setTextColor(ContextCompat.getColor(context, R.color.text_tertiary))
                tvAmPm.setTextColor(ContextCompat.getColor(context, R.color.text_tertiary))
                tvSummary.setTextColor(ContextCompat.getColor(context, R.color.text_tertiary))
                shiftIndicator.alpha = 0.4f
            } else {
                tvTime.setTextColor(ContextCompat.getColor(context, R.color.text_primary))
                tvAmPm.setTextColor(ContextCompat.getColor(context, R.color.text_secondary))
                tvSummary.setTextColor(ContextCompat.getColor(context, R.color.primary))
                shiftIndicator.alpha = 1.0f
            }
        } catch (e: Exception) { tvTime.text = time }

        val tvSoundNameView = view.findViewById<TextView>(R.id.tvSoundName)
        val soundName = getSoundTitle(context, soundUri)
        tvSummary.text = "${snoozeMin}분 간격, ${if(snoozeRepeat == 99) "계속" else snoozeRepeat.toString() + "회"}"
        tvSoundNameView.text = soundName
        
        val rowContents = view.findViewById<View>(R.id.rowContents)
        rowContents.setOnClickListener { onAction(false, false) }
        rowContents.setOnLongClickListener { onAction(false, true); true }
        
        alarmSwitch.isChecked = isEnabled
        layoutAlarmSwitch.setOnClickListener {
            // onAction will handle the data update and re-sync
            onAction(true, false)
        }
        
        return view
    }

    private var currentDialogSoundUri: String? = null
    private var tvSoundNameReference: android.widget.TextView? = null

    /**
     * 새 알람 추가 시 기본음으로 시스템 알람음 설정
     * 무음 문제 해결을 위해 반드시 시스템 기본 알람음을 반환
     */
    private fun getDefaultAlarmUri(context: Context): String {
        // 1. 시스템 기본 알람음 (가장 우선)
        val defaultUri = android.provider.Settings.System.DEFAULT_ALARM_ALERT_URI
        if (defaultUri != null) {
            Log.d("ShiftAlarm", "시스템 기본 알람음 URI: $defaultUri")
            return defaultUri.toString()
        }
        
        // 2. RingtoneManager에서 알람 타입 기본값 가져오기
        val fallbackUri = android.media.RingtoneManager.getDefaultUri(android.media.RingtoneManager.TYPE_ALARM)
        if (fallbackUri != null) {
            Log.d("ShiftAlarm", "Fallback 알람음 URI: $fallbackUri")
            return fallbackUri.toString()
        }
        
        // 3. 마지막 fallback: 알림음이라도 사용
        val notificationUri = android.media.RingtoneManager.getDefaultUri(android.media.RingtoneManager.TYPE_NOTIFICATION)
        if (notificationUri != null) {
            Log.w("ShiftAlarm", "알람음 없음, 알림음 사용: $notificationUri")
            return notificationUri.toString()
        }
        
        // 4. 최후의 수단: 벨소리
        val ringtoneUri = android.media.RingtoneManager.getDefaultUri(android.media.RingtoneManager.TYPE_RINGTONE)
        if (ringtoneUri != null) {
            Log.w("ShiftAlarm", "알림음 없음, 벨소리 사용: $ringtoneUri")
            return ringtoneUri.toString()
        }
        
        // 이 경우는 거의 없지만, 안전장치
        Log.e("ShiftAlarm", "어떤 기본 소리도 찾을 수 없음")
        return ""
    }

    private fun showEditDialog(
        title: String, currentTime: String, shiftType: String, existingAlarm: CustomAlarm?, isNew: Boolean
    ) {
        val dialogView = layoutInflater.inflate(R.layout.dialog_alarm_edit_spinner, null)
        val dialog = AlertDialog.Builder(requireContext(), android.R.style.Theme_DeviceDefault_Light_NoActionBar_Fullscreen).setView(dialogView).create()
        dialog.window?.setBackgroundDrawableResource(android.R.color.transparent)
        dialog.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
        
        val tvTitle = dialogView.findViewById<TextView>(R.id.dialogTitle)
        val timePicker = dialogView.findViewById<TimePicker>(R.id.timePicker)
        val tvSoundName = dialogView.findViewById<TextView>(R.id.tvSoundName)
        tvSoundNameReference = tvSoundName
        
        val btnSelectSound = dialogView.findViewById<View>(R.id.btnSelectSound)
        val btnDelete = dialogView.findViewById<Button>(R.id.btnDelete)
        val btnCancel = dialogView.findViewById<View>(R.id.btnCancel)
        val btnSave = dialogView.findViewById<View>(R.id.btnSave)

        // Initialize Values
        var selectedSnooze = existingAlarm?.snoozeInterval ?: 5
        var selectedRepeat = existingAlarm?.snoozeRepeat ?: 3
        
        // 새 알람 생성 시 기본적으로 시스템 알람음 설정 (무음 문제 해결)
        // 기존 알람 수정 시에도 soundUri가 비어있거나 null이면 기본값으로 설정
        val existingUri = existingAlarm?.soundUri
        val isExistingUriEmpty = existingUri.isNullOrEmpty() || existingUri == "null"
        
        currentDialogSoundUri = if (isNew || isExistingUriEmpty) {
            // 새 알람 또는 기존 알람의 소리가 설정되지 않은 경우: 반드시 기본 알람음으로 설정
            val defaultUri = getDefaultAlarmUri(requireContext())
            Log.d("ShiftAlarm", "기본 알람음 설정: $defaultUri (isNew=$isNew, isExistingUriEmpty=$isExistingUriEmpty)")
            defaultUri
        } else {
            // 기존 알람 수정: 기존 값 유지
            existingUri
        }
        
        // soundUri가 비어있는 경우 최종 안전장치
        if (currentDialogSoundUri.isNullOrEmpty()) {
            currentDialogSoundUri = getDefaultAlarmUri(requireContext())
            Log.w("ShiftAlarm", "soundUri가 비어있어 기본값으로 재설정: $currentDialogSoundUri")
        }
        
        // 새 알람 추가 시 또는 볼륨이 0인 경우 시스템 알람 스트림 볼륨을 최대치로 설정
        try {
            val audioManager = requireContext().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 (isNew || currVol == 0) {
                audioManager.setStreamVolume(android.media.AudioManager.STREAM_ALARM, maxVol, 0)
                Log.d("ShiftAlarm", "알람 스트림 볼륨 최대치($maxVol)로 초기화 완료")
            }
        } catch (e: Exception) {
            Log.w("ShiftAlarm", "알람 볼륨 설정 실패", e)
        }

        fun updateSoundName(uriStr: String?) {
            if (uriStr.isNullOrEmpty() || uriStr == "null") {
                tvSoundName.text = "기본 알람음"
            } else {
                try {
                    val uri = android.net.Uri.parse(uriStr)
                    val ringtone = android.media.RingtoneManager.getRingtone(requireContext(), uri)
                    val title = ringtone?.getTitle(requireContext()) ?: "알람음"
                    tvSoundName.text = title
                } catch (e: Exception) {
                    tvSoundName.text = "알람음"
                }
            }
        }
        updateSoundName(currentDialogSoundUri)

        // Snooze Interval Buttons
        val snoozeButtons = listOf(
            dialogView.findViewById<TextView>(R.id.snooze5),
            dialogView.findViewById<TextView>(R.id.snooze10),
            dialogView.findViewById<TextView>(R.id.snooze15),
            dialogView.findViewById<TextView>(R.id.snooze30)
        )
        val snoozeValues = listOf(5, 10, 15, 30)
        fun updateSnoozeUI() {
            snoozeButtons.forEachIndexed { i, btn ->
                val isSelected = snoozeValues[i] == selectedSnooze
                btn.setBackgroundResource(if (isSelected) R.drawable.bg_pill_rect_selected else R.drawable.bg_pill_rect_unselected)
                btn.setTextColor(if (isSelected) ContextCompat.getColor(requireContext(), R.color.white) else ContextCompat.getColor(requireContext(), R.color.text_secondary))
            }
        }
        updateSnoozeUI()
        snoozeButtons.forEachIndexed { i, btn -> btn.setOnClickListener { selectedSnooze = snoozeValues[i]; updateSnoozeUI() } }

        // Repeat Count Buttons
        val repeatButtons = listOf(
            dialogView.findViewById<TextView>(R.id.repeat3),
            dialogView.findViewById<TextView>(R.id.repeat5),
            dialogView.findViewById<TextView>(R.id.repeatForever)
        )
        val repeatValues = listOf(3, 5, 99)
        fun updateRepeatUI() {
            repeatButtons.forEachIndexed { i, btn ->
                val isSelected = repeatValues[i] == selectedRepeat
                btn.setBackgroundResource(if (isSelected) R.drawable.bg_pill_rect_selected else R.drawable.bg_pill_rect_unselected)
                btn.setTextColor(if (isSelected) ContextCompat.getColor(requireContext(), R.color.white) else ContextCompat.getColor(requireContext(), R.color.text_secondary))
            }
        }
        updateRepeatUI()
        repeatButtons.forEachIndexed { i, btn ->
            btn.setOnClickListener {
                selectedRepeat = repeatValues[i]
                updateRepeatUI()
            }
        }
        // Pre-Alarm Buttons
        var selectedPreAlarm = 15
        val preAlarmButtons = listOf(
            dialogView.findViewById<TextView>(R.id.preAlarmOff),
            dialogView.findViewById<TextView>(R.id.preAlarm5),
            dialogView.findViewById<TextView>(R.id.preAlarm10),
            dialogView.findViewById<TextView>(R.id.preAlarm15),
            dialogView.findViewById<TextView>(R.id.preAlarm30)
        )
        val preAlarmValues = listOf(0, 5, 10, 15, 30)
        fun updatePreAlarmUI() {
            preAlarmButtons.forEachIndexed { i, btn ->
                val isSelected = preAlarmValues[i] == selectedPreAlarm
                btn.setBackgroundResource(if (isSelected) R.drawable.bg_pill_rect_selected else R.drawable.bg_pill_rect_unselected)
                btn.setTextColor(if (isSelected) ContextCompat.getColor(requireContext(), R.color.white) else ContextCompat.getColor(requireContext(), R.color.text_secondary))
            }
        }
        updatePreAlarmUI()
        preAlarmButtons.forEachIndexed { i, btn -> btn.setOnClickListener { selectedPreAlarm = preAlarmValues[i]; updatePreAlarmUI() } }

        val cardShift = dialogView.findViewById<View>(R.id.cardShiftSelector)
        var currentShift = when(shiftType) {
            "주", "주간" -> "주간"
            "석", "석간" -> "석간"
            "야", "야간" -> "야간"
            "주맞", "주간 맞교대" -> "주간 맞교대"
            "야맞", "야간 맞교대" -> "야간 맞교대"
            else -> "기타"
        }
        cardShift.visibility = View.VISIBLE
        val shiftBtns = listOf(
            dialogView.findViewById<TextView>(R.id.btnShiftJu),
            dialogView.findViewById<TextView>(R.id.btnShiftSeok),
            dialogView.findViewById<TextView>(R.id.btnShiftYa),
            dialogView.findViewById<TextView>(R.id.btnShiftJuMat),
            dialogView.findViewById<TextView>(R.id.btnShiftYaMat),
            dialogView.findViewById<TextView>(R.id.btnShiftEtc)
        )
        val shiftTypes = listOf("주간", "석간", "야간", "주간 맞교대", "야간 맞교대", "기타")
        fun updateShiftUI() {
            shiftBtns.forEachIndexed { i, btn ->
                val isSelected = shiftTypes[i] == currentShift
                val colorRes = when(shiftTypes[i]) {
                    "주간" -> R.color.shift_lemon
                    "석간" -> R.color.shift_seok
                    "야간" -> R.color.shift_ya
                    "주간 맞교대" -> R.color.shift_jumat
                    "야간 맞교대" -> R.color.shift_yamat
                    else -> R.color.shift_gray
                }
                val color = ContextCompat.getColor(requireContext(), colorRes)
                if (isSelected) {
                    val d = ContextCompat.getDrawable(requireContext(), R.drawable.bg_shift_circle_v4) as android.graphics.drawable.GradientDrawable
                    d.mutate()
                    d.setColor(color)
                    btn.background = d
                    btn.setTextColor(if (shiftTypes[i] == "야간") ContextCompat.getColor(requireContext(), R.color.white) else ContextCompat.getColor(requireContext(), R.color.black))
                } else {
                    val d = ContextCompat.getDrawable(requireContext(), R.drawable.bg_shift_stroke_v4) as android.graphics.drawable.GradientDrawable
                    d.mutate()
                    d.setStroke(dpToPx(1.5f), color)
                    btn.background = d
                    btn.setTextColor(color)
                }
            }
        }
        updateShiftUI()
        shiftBtns.forEachIndexed { i, btn -> btn.setOnClickListener { currentShift = shiftTypes[i]; updateShiftUI() } }

        tvTitle.text = if (isNew) "새 알람 추가" else "$shiftType 알람 수정"
        timePicker.setIs24HourView(false)
        val parts = currentTime.split(":")
        if (android.os.Build.VERSION.SDK_INT >= 23) {
            timePicker.hour = parts[0].toInt(); timePicker.minute = parts[1].toInt()
        } else {
            @Suppress("DEPRECATION")
            timePicker.currentHour = parts[0].toInt()
            @Suppress("DEPRECATION")
            timePicker.currentMinute = parts[1].toInt()
        }

        btnSelectSound.setOnClickListener {
            val intent = Intent(android.media.RingtoneManager.ACTION_RINGTONE_PICKER).apply {
                putExtra(android.media.RingtoneManager.EXTRA_RINGTONE_TYPE, android.media.RingtoneManager.TYPE_ALARM)
                putExtra(android.media.RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, if (currentDialogSoundUri != null) android.net.Uri.parse(currentDialogSoundUri) else null as android.net.Uri?)
                // 무음 선택 방지: 시스템 알람음만 선택 가능
                putExtra(android.media.RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, false)
            }
            startActivityForResult(intent, 100)
        }

        if (!isNew) {
            btnDelete.visibility = View.VISIBLE
            btnDelete.setOnClickListener { 
                lifecycleScope.launch {
                    existingAlarm?.let { 
                        // AlarmSyncManager를 사용하여 동기화된 삭제 수행
                        // DB 삭제 전 AlarmManager 취소가 보장됨
                        val result = AlarmSyncManager.deleteAlarm(requireContext(), it)
                        if (result.isSuccess) {
                            Log.d("ShiftAlarm", "알람 삭제 동기화 성공: ID=${it.id}")
                        } else {
                            Log.e("ShiftAlarm", "알람 삭제 동기화 실패", result.exceptionOrNull())
                            Toast.makeText(requireContext(), "알람 삭제 중 오류가 발생했습니다.", Toast.LENGTH_SHORT).show()
                        }
                    }
                    refreshAlarmList()
                    dialog.dismiss()
                }
            }
        }

        btnCancel.setOnClickListener { dialog.dismiss() }
        btnSave.setOnClickListener {
            @Suppress("DEPRECATION")
            val h = if (android.os.Build.VERSION.SDK_INT >= 23) timePicker.hour else timePicker.currentHour
            @Suppress("DEPRECATION")
            val m = if (android.os.Build.VERSION.SDK_INT >= 23) timePicker.minute else timePicker.currentMinute
            val time = String.format("%02d:%02d", h, m)
            
            lifecycleScope.launch {
                if (isNew) {
                    val newAlarm = CustomAlarm(
                        time = time,
                        shiftType = currentShift,
                        isEnabled = true,
                        soundUri = currentDialogSoundUri,
                        snoozeInterval = selectedSnooze,
                        snoozeRepeat = selectedRepeat
                    )
                    // AlarmSyncManager를 사용하여 동기화된 추가 수행
                    val result = AlarmSyncManager.addAlarm(requireContext(), newAlarm)
                    if (result.isSuccess) {
                        Log.d("ShiftAlarm", "새 알람 추가 동기화 성공")
                        Toast.makeText(requireContext(), "알람이 추가되었습니다.", Toast.LENGTH_SHORT).show()
                    } else {
                        Log.e("ShiftAlarm", "새 알람 추가 동기화 실패", result.exceptionOrNull())
                        Toast.makeText(requireContext(), "알람 추가 중 오류가 발생했습니다.", Toast.LENGTH_SHORT).show()
                    }
                } else {
                    val updated = existingAlarm!!.copy(
                        time = time,
                        shiftType = currentShift,
                        soundUri = currentDialogSoundUri,
                        snoozeInterval = selectedSnooze,
                        snoozeRepeat = selectedRepeat
                    )
                    // AlarmSyncManager를 사용하여 동기화된 수정 수행
                    val result = AlarmSyncManager.updateAlarm(requireContext(), updated)
                    if (result.isSuccess) {
                        Log.d("ShiftAlarm", "알람 수정 동기화 성공: ID=${updated.id}")
                        Toast.makeText(requireContext(), "알람이 수정되었습니다.", Toast.LENGTH_SHORT).show()
                    } else {
                        Log.e("ShiftAlarm", "알람 수정 동기화 실패", result.exceptionOrNull())
                        Toast.makeText(requireContext(), "알람 수정 중 오류가 발생했습니다.", Toast.LENGTH_SHORT).show()
                    }
                }
                refreshAlarmList()
                dialog.dismiss()
            }
        }
        dialog.setOnDismissListener { tvSoundNameReference = null }
        dialog.show()
    }

    private fun dpToPx(dp: Float): Int {
        return (dp * resources.displayMetrics.density).toInt()
    }
    
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: android.content.Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (resultCode == androidx.appcompat.app.AppCompatActivity.RESULT_OK) {
            val uri = data?.getParcelableExtra<android.net.Uri>(android.media.RingtoneManager.EXTRA_RINGTONE_PICKED_URI)
            if (uri != null) {
                currentDialogSoundUri = uri.toString()
                try {
                    val ringtone = android.media.RingtoneManager.getRingtone(requireContext(), uri)
                    tvSoundNameReference?.text = ringtone.getTitle(requireContext())
                } catch(e: Exception) {
                    tvSoundNameReference?.text = "사용자 지정음"
                }
            }
        }
    }
    private fun getSoundTitle(context: Context, uriStr: String?): String {
        if (soundTitleCache.containsKey(uriStr)) return soundTitleCache[uriStr]!!
        
        // uriStr이 null이거나 비어있거나 "null" 문자열인 경우 기본음으로 처리
        val title = if (uriStr.isNullOrEmpty() || uriStr == "null") {
            "기본 알람음"
        } else {
            try {
                val uri = android.net.Uri.parse(uriStr)
                val ringtone = android.media.RingtoneManager.getRingtone(context, uri)
                ringtone?.getTitle(context) ?: "알람음"
            } catch (e: Exception) {
                "알람음"
            }
        }
        soundTitleCache[uriStr] = title
        return title
    }
}
