package com.example.shiftalarm import android.content.Context import android.content.Intent import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.ArrayAdapter import android.widget.Toast import androidx.fragment.app.Fragment import com.example.shiftalarm.databinding.FragmentSettingsBasicBinding import java.io.BufferedInputStream import java.io.File import java.io.FileOutputStream import java.net.HttpURLConnection import android.app.ProgressDialog import android.net.Uri import android.os.Build import androidx.core.content.FileProvider import androidx.lifecycle.lifecycleScope import kotlinx.coroutines.launch import android.provider.Settings import androidx.core.content.ContextCompat class FragmentSettingsBasic : Fragment() { private var _binding: FragmentSettingsBasicBinding? = null private val binding get() = _binding!! private val PREFS_NAME = "ShiftAlarmPrefs" private var isUserInteraction = false override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { _binding = FragmentSettingsBasicBinding.inflate(inflater, container, false) return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) loadSettings() setupListeners() } private fun loadSettings() { val prefs = requireContext().getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) // Factory Spinner setupFactorySpinner(prefs) // Team Spinner setupTeamSpinner(prefs) // Version Info try { val pInfo = requireContext().packageManager.getPackageInfo(requireContext().packageName, 0) binding.versionInfo.text = "Ver. ${pInfo.versionName} | 제작자: 산적이얌" } catch (e: Exception) { binding.versionInfo.text = "Ver. Unknown | 제작자: 산적이얌" } // Show/Hide Exact Alarm based on version if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { binding.btnExactAlarm.visibility = View.VISIBLE binding.dividerExact.visibility = View.VISIBLE } else { binding.btnExactAlarm.visibility = View.GONE binding.dividerExact.visibility = View.GONE } } private fun setupFactorySpinner(prefs: android.content.SharedPreferences) { val savedFactory = prefs.getString("selected_factory", "Jeonju") val factoryIndex = if (savedFactory == "Nonsan") 1 else 0 binding.factorySpinner.setSelection(factoryIndex) binding.factorySpinner.setOnTouchListener { _, _ -> isUserInteraction = true false } binding.factorySpinner.onItemSelectedListener = object : android.widget.AdapterView.OnItemSelectedListener { override fun onItemSelected(parent: android.widget.AdapterView<*>?, view: View?, position: Int, id: Long) { if (!isUserInteraction) return val isNonsan = position == 1 val factory = if (isNonsan) "Nonsan" else "Jeonju" val currentFactory = prefs.getString("selected_factory", "Jeonju") if (factory == currentFactory) { // Just update team spinner without resetting times if same factory updateTeamSpinner(isNonsan) return } // Save immediately val editor = prefs.edit() editor.putString("selected_factory", factory) editor.apply() // CRUCIAL: Re-sync all alarms for the new factory lifecycleScope.launch { syncAllAlarms(requireContext()) Toast.makeText(requireContext(), "공장 설정이 변경되었습니다.", Toast.LENGTH_SHORT).show() } // Update Team Spinner logic updateTeamSpinner(isNonsan) } override fun onNothingSelected(parent: android.widget.AdapterView<*>?) {} } } private fun updateTeamSpinner(isNonsan: Boolean) { val currentSelection = binding.teamSpinner.selectedItemPosition val teamOptions = if (isNonsan) { arrayOf("A반", "B반", "C반") } else { arrayOf("A반", "B반", "C반", "D반") } val adapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item, teamOptions) adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) binding.teamSpinner.adapter = adapter if (currentSelection < teamOptions.size) { binding.teamSpinner.setSelection(currentSelection) } else { binding.teamSpinner.setSelection(0) if (isUserInteraction) { Toast.makeText(requireContext(), "논산 회사는 D반이 없습니다. A반으로 설정됩니다.", Toast.LENGTH_SHORT).show() val prefs = requireContext().getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) prefs.edit().putString("selected_team", "A").apply() } } } private fun setupTeamSpinner(prefs: android.content.SharedPreferences) { val savedFactory = prefs.getString("selected_factory", "Jeonju") val isNonsan = savedFactory == "Nonsan" updateTeamSpinner(isNonsan) val savedTeam = prefs.getString("selected_team", "A") val teamIndex = when (savedTeam) { "A" -> 0 "B" -> 1 "C" -> 2 "D" -> if (isNonsan) 0 else 3 else -> 0 } binding.teamSpinner.setSelection(teamIndex) binding.teamSpinner.setOnTouchListener { _, _ -> isUserInteraction = true false } binding.teamSpinner.onItemSelectedListener = object : android.widget.AdapterView.OnItemSelectedListener { override fun onItemSelected(parent: android.widget.AdapterView<*>?, view: View?, position: Int, id: Long) { if (!isUserInteraction) return val selectedTeam = when(position) { 0 -> "A" 1 -> "B" 2 -> "C" 3 -> "D" else -> "A" } prefs.edit().putString("selected_team", selectedTeam).apply() // CRUCIAL: Re-sync all alarms for the new team lifecycleScope.launch { syncAllAlarms(requireContext()) Toast.makeText(requireContext(), "${selectedTeam}반으로 알람이 재설정되었습니다.", Toast.LENGTH_SHORT).show() } } override fun onNothingSelected(parent: android.widget.AdapterView<*>?) {} } } override fun onResume() { super.onResume() updatePermissionStatuses() } private fun updatePermissionStatuses() { val context = requireContext() // 1. 배터리 (Battery) val isBatteryIgnored = AlarmPermissionUtil.getBatteryOptimizationStatus(context) binding.tvBatteryStatus.text = if (isBatteryIgnored) "[설정 완료: 절전 예외]" else "클릭하여 '제한 없음'으로 설정하세요" binding.tvBatteryStatus.setTextColor(ContextCompat.getColor(context, if (isBatteryIgnored) R.color.primary else R.color.shift_red)) // 2. 정확한 알람 (Exact Alarm) - Android 12+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { val isExactGranted = AlarmPermissionUtil.getExactAlarmStatus(context) binding.tvExactStatus.text = if (isExactGranted) "[설정 완료: 정밀 알람]" else "필수: 클릭하여 권한을 허용하세요" binding.tvExactStatus.setTextColor(ContextCompat.getColor(context, if (isExactGranted) R.color.primary else R.color.shift_red)) } else { binding.btnExactAlarm.visibility = View.GONE binding.dividerExact.visibility = View.GONE } // 3. 다른 앱 위에 표시 (Overlay) val isOverlayGranted = AlarmPermissionUtil.getOverlayStatus(context) binding.tvOverlayStatus.text = if (isOverlayGranted) "[설정 완료: 화면 우위]" else "필수: 알람창 노출을 위해 허용하세요" binding.tvOverlayStatus.setTextColor(ContextCompat.getColor(context, if (isOverlayGranted) R.color.primary else R.color.shift_red)) // 4. 전체화면 알림 (Full Screen Intent) - Android 14+ if (Build.VERSION.SDK_INT >= 34) { val isFullScreenGranted = AlarmPermissionUtil.getFullScreenIntentStatus(context) binding.tvFullScreenStatus.text = if (isFullScreenGranted) "[설정 완료: 전체화면]" else "필수: 안드로이드 14 이상 필수 설정" binding.tvFullScreenStatus.setTextColor(ContextCompat.getColor(context, if (isFullScreenGranted) R.color.primary else R.color.shift_red)) binding.btnFullScreenIntent.visibility = View.VISIBLE } else { binding.btnFullScreenIntent.visibility = View.GONE } } private fun setupListeners() { val prefs = requireContext().getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) binding.btnBatteryOptimize.setOnClickListener { AlarmPermissionUtil.requestBatteryOptimization(requireContext()) } binding.btnExactAlarm.setOnClickListener { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { val intent = Intent(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM).apply { data = Uri.parse("package:${requireContext().packageName}") } startActivity(intent) } } binding.btnOverlayPermission.setOnClickListener { AlarmPermissionUtil.requestOverlayPermission(requireContext()) } binding.btnFullScreenIntent.setOnClickListener { AlarmPermissionUtil.requestFullScreenIntentPermission(requireContext()) } binding.btnPermissionSettings.setOnClickListener { val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply { data = Uri.parse("package:${requireContext().packageName}") } startActivity(intent) } binding.btnCheckUpdate.setOnClickListener { checkUpdate() } } private fun checkUpdate() { AppUpdateManager.checkUpdate(requireActivity(), silent = false) } override fun onDestroyView() { super.onDestroyView() _binding = null } }