package com.dano.test1.ui

import android.content.Context
import android.content.res.ColorStateList
import android.graphics.Color
import android.graphics.drawable.GradientDrawable
import android.os.Handler
import android.os.Looper
import android.util.TypedValue
import android.view.Gravity
import android.view.View
import android.widget.*
import com.dano.test1.LanguageManager
import com.dano.test1.MainActivity
import com.dano.test1.R
import com.dano.test1.network.DatabaseUploader
import com.dano.test1.network.LoginManager
import com.dano.test1.network.NetworkUtils
import com.dano.test1.network.TokenStore
import com.dano.test1.questionnaire.GlobalValues
import com.dano.test1.questionnaire.QuestionItem
import com.dano.test1.questionnaire.QuestionnaireBase
import com.dano.test1.questionnaire.QuestionnaireAllInOne
import com.dano.test1.questionnaire.QuestionnaireGeneric
import com.google.android.material.button.MaterialButton
import org.json.JSONArray
import org.json.JSONObject
import java.io.File
import java.util.concurrent.TimeUnit
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.dano.test1.utils.ViewUtils


var RHS_POINTS: Int? = null

class HandlerOpeningScreen(private val activity: MainActivity) {

    private var languageID: String = "GERMAN"
    private lateinit var editText: EditText
    private lateinit var coachEditText: EditText
    private lateinit var spinner: Spinner
    private lateinit var textView: TextView
    private lateinit var buttonContainer: LinearLayout
    private lateinit var buttonLoad: Button
    private lateinit var saveButton: Button
    private lateinit var uploadButton: Button
    private lateinit var downloadButton: Button
    private lateinit var statusSession: TextView
    private lateinit var statusOnline: TextView
    private val SESSION_WARN_AFTER_MS = 12 * 60 * 60 * 1000L // 12h
    private var sessionLongWarnedOnce = false

    private val dynamicButtons = mutableListOf<Button>()
    private val questionnaireFiles = mutableMapOf<Button, String>()

    private data class CardParts(
        val title: TextView,
        val subtitle: TextView,
        val chip: TextView
    )
    private val cardParts = mutableMapOf<Button, CardParts>()

    private val buttonPoints: MutableMap<String, Int> = mutableMapOf()
    private var questionnaireEntries: List<QuestionItem.QuestionnaireEntry> = emptyList()

    private var uiFreeze: Boolean = false

    private val uiHandler = Handler(Looper.getMainLooper())
    private val statusTicker = object : Runnable {
        override fun run() {
            updateStatusStrip()
            uiHandler.postDelayed(this, 60_000)
        }
    }

    private val STROKE_ENABLED  = Color.parseColor("#8C79F2")
    private val STROKE_DISABLED = Color.parseColor("#D8D3F5")

    private fun t(id: String) = LanguageManager.getText(languageID, id)

    fun init() {
        activity.setContentView(R.layout.opening_screen)

        // <<< NEU: bei jedem Öffnen des Screens zurücksetzen,
        // damit der Toast pro Besuch einmal angezeigt wird
        sessionLongWarnedOnce = false

        bindViews()
        loadQuestionnaireOrder()
        createQuestionnaireButtons()
        restorePreviousClientCode()
        lockCoachCodeField()
        setupLanguageSpinner()
        setupLoadButton()
        setupSaveButton()
        setupUploadButton()
        setupDownloadButton()

        uiHandler.removeCallbacks(statusTicker)
        updateStatusStrip()
        uiHandler.post(statusTicker)

        val pathExists = File("/data/data/com.dano.test1/databases/questionnaire_database").exists()
        updateMainButtonsState(pathExists)
        updateDownloadButtonState(pathExists)

        if (pathExists && !editText.text.isNullOrBlank()) buttonLoad.performClick()

        uiHandler.removeCallbacks(statusTicker)
        updateStatusStrip()
        applySessionAgeHighlight(System.currentTimeMillis() - TokenStore.getLoginTimestamp(activity))
        uiHandler.post(statusTicker)
    }

    private fun bindViews() {
        editText = activity.findViewById(R.id.editText)
        coachEditText = activity.findViewById(R.id.coachEditText)
        spinner = activity.findViewById(R.id.string_spinner1)
        textView = activity.findViewById(R.id.textView)
        buttonContainer = activity.findViewById(R.id.buttonContainer)
        buttonLoad = activity.findViewById(R.id.loadButton)
        saveButton = activity.findViewById(R.id.saveButton)
        uploadButton = activity.findViewById(R.id.uploadButton)

        downloadButton = activity.findViewById(R.id.downloadButton)
        downloadButton.visibility = View.GONE

        statusSession = activity.findViewById(R.id.statusSession)
        statusOnline = activity.findViewById(R.id.statusOnline)
        val tag = editText.tag as? String ?: ""
        editText.hint = t(tag)
        val coachTag = coachEditText.tag as? String ?: ""
        coachEditText.hint = t(coachTag)
        textView.text = t("example_text")
    }

    private fun loadQuestionnaireOrder() {
        try {
            val inputStream = activity.assets.open("questionnaire_order.json")
            val json = inputStream.bufferedReader().use { it.readText() }
            val jsonArray = JSONArray(json)
            questionnaireEntries = (0 until jsonArray.length()).map { i ->
                val obj = jsonArray.getJSONObject(i)
                val file = obj.getString("file")
                val conditionObj = obj.optJSONObject("condition")
                val condition = parseCondition(conditionObj)
                val showPoints = obj.optBoolean("showPoints", false)
                QuestionItem.QuestionnaireEntry(file, condition, showPoints)
            }
        } catch (_: Exception) {
            questionnaireEntries = emptyList()
        }
    }

    private fun parseCondition(conditionObj: JSONObject?): QuestionItem.Condition? {
        if (conditionObj == null) return null
        if (conditionObj.has("anyOf")) {
            val arr = conditionObj.optJSONArray("anyOf") ?: JSONArray()
            val conditions = mutableListOf<QuestionItem.Condition>()
            for (i in 0 until arr.length()) {
                val sub = arr.optJSONObject(i)
                parseCondition(sub)?.let { conditions.add(it) }
            }
            return QuestionItem.Condition.AnyOf(conditions)
        }
        if (conditionObj.has("alwaysAvailable") && conditionObj.optBoolean("alwaysAvailable", false)) {
            return QuestionItem.Condition.AlwaysAvailable
        }
        val requiresList = mutableListOf<String>()
        if (conditionObj.has("requiresCompleted")) {
            val reqArr = conditionObj.optJSONArray("requiresCompleted")
            if (reqArr != null) {
                for (i in 0 until reqArr.length()) requiresList.add(reqArr.optString(i))
            } else {
                conditionObj.optString("requiresCompleted")?.let { if (it.isNotBlank()) requiresList.add(it) }
            }
        }
        val questionnaire = conditionObj.optString("questionnaire", null)
        val questionId = conditionObj.optString("questionId", null)
        val operator = conditionObj.optString("operator", null)
        val value = conditionObj.optString("value", null)
        val hasQuestionCheck =
            !questionnaire.isNullOrBlank() && !questionId.isNullOrBlank() && !operator.isNullOrBlank() && value != null
        return when {
            requiresList.isNotEmpty() && hasQuestionCheck ->
                QuestionItem.Condition.Combined(requiresList, QuestionItem.Condition.QuestionCondition(questionnaire!!, questionId!!, operator!!, value!!))
            hasQuestionCheck ->
                QuestionItem.Condition.QuestionCondition(questionnaire!!, questionId!!, operator!!, value!!)
            requiresList.isNotEmpty() ->
                QuestionItem.Condition.RequiresCompleted(requiresList)
            else -> null
        }
    }

    private fun createQuestionnaireButtons() {
        buttonContainer.removeAllViews()
        dynamicButtons.clear()
        questionnaireFiles.clear()
        cardParts.clear()
        val vMargin = dp(8)
        val startEnabled = mutableListOf<Button>()
        questionnaireEntries.forEachIndexed { index, entry ->
            val row = FrameLayout(activity).apply {
                layoutParams = LinearLayout.LayoutParams(
                    LinearLayout.LayoutParams.MATCH_PARENT,
                    LinearLayout.LayoutParams.WRAP_CONTENT
                ).also { it.setMargins(0, vMargin, 0, vMargin) }
            }
            val btn = MaterialButton(activity).apply {
                layoutParams = FrameLayout.LayoutParams(
                    FrameLayout.LayoutParams.MATCH_PARENT,
                    dp(84)
                )
                text = ""
                isAllCaps = false
                setMinimumWidth(0)
                setMinimumHeight(0)
                cornerRadius = dp(22)
                strokeWidth = dp(1)
                strokeColor = ColorStateList.valueOf(STROKE_DISABLED)
                backgroundTintList = ColorStateList.valueOf(Color.WHITE)
                rippleColor = ColorStateList.valueOf(Color.parseColor("#22000000"))
                gravity = Gravity.START or Gravity.CENTER_VERTICAL
                setPadding(dp(20), 0, dp(20), 0)
                id = View.generateViewId()
                setOnClickListener {
                    GlobalValues.LAST_CLIENT_CODE = GlobalValues.LOADED_CLIENT_CODE
                    val fileName = questionnaireFiles[this] ?: return@setOnClickListener
                    val variant = AbTestSettingsStore.effectiveVariant(activity)
                    val questionnaire: QuestionnaireBase<*> = if (variant == "B") {
                        QuestionnaireAllInOne(fileName)
                    } else {
                        QuestionnaireGeneric(fileName)
                    }
                    startQuestionnaire(questionnaire)
                    applySetButtonsEnabled(dynamicButtons.filter { it == this }, allowCompleted = false, force = false)
                }
            }
            val textColumn = LinearLayout(activity).apply {
                orientation = LinearLayout.VERTICAL
                layoutParams = FrameLayout.LayoutParams(
                    FrameLayout.LayoutParams.WRAP_CONTENT,
                    FrameLayout.LayoutParams.WRAP_CONTENT,
                    Gravity.START or Gravity.CENTER_VERTICAL
                ).also { it.marginStart = dp(24) }
            }
            val tvTitle = TextView(activity).apply {
                setTextSize(TypedValue.COMPLEX_UNIT_SP, 18f)
                setTextColor(Color.parseColor("#2F2A49"))
                setPadding(0, dp(6), 0, dp(2))
            }
            val tvSubtitle = TextView(activity).apply {
                setTextSize(TypedValue.COMPLEX_UNIT_SP, 13f)
                setTextColor(Color.parseColor("#7B7794"))
                visibility = View.GONE
            }
            textColumn.addView(tvTitle)
            textColumn.addView(tvSubtitle)
            val chip = TextView(activity).apply {
                setPadding(dp(14), dp(8), dp(14), dp(8))
                setTextColor(Color.WHITE)
                text = t("start")
                setBackgroundResource(R.drawable.bg_chip_amber)
                setTextSize(TypedValue.COMPLEX_UNIT_SP, 14f)
                layoutParams = FrameLayout.LayoutParams(
                    FrameLayout.LayoutParams.WRAP_CONTENT,
                    FrameLayout.LayoutParams.WRAP_CONTENT,
                    Gravity.END or Gravity.CENTER_VERTICAL
                ).also { it.marginEnd = dp(16) }
            }
            row.addView(btn)
            row.addView(textColumn)
            row.addView(chip)
            buttonContainer.addView(row)
            dynamicButtons.add(btn)
            questionnaireFiles[btn] = entry.file
            cardParts[btn] = CardParts(tvTitle, tvSubtitle, chip)

            // Fallback-Titel lokalisieren
            tvTitle.text = "${t("questionnaire")} ${index + 1}"

            if (entry.condition is QuestionItem.Condition.AlwaysAvailable) startEnabled.add(btn)
        }
        applyUpdateButtonTexts(force = false)
        applySetButtonsEnabled(startEnabled, allowCompleted = false, force = false)
    }

    private fun restorePreviousClientCode() {
        // Coach-Code (Username) setzen und Feld sperren – aber NICHT mehr zurückkehren
        val username = TokenStore.getUsername(activity)
        if (!username.isNullOrBlank()) {
            coachEditText.setText(username)
            lockCoachCodeField()
        }

        // Hier den zuletzt verwendeten Client-Code einsetzen
        GlobalValues.LAST_CLIENT_CODE?.let {
            editText.setText(it)
            GlobalValues.LOADED_CLIENT_CODE = it
        }
    }


    private fun setupLanguageSpinner() {
        val languages = listOf("GERMAN", "ENGLISH", "FRENCH", "ROMANIAN", "ARABIC", "POLISH", "TURKISH", "UKRAINIAN", "RUSSIAN", "SPANISH")
        val adapter = ArrayAdapter(activity, android.R.layout.simple_spinner_item, languages).apply {
            setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
        }
        spinner.adapter = adapter
        spinner.setSelection(languages.indexOf(languageID))
        spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
            override fun onItemSelected(parent: AdapterView<*>, view: View?, position: Int, id: Long) {
                languageID = languages[position]
                applyUpdateButtonTexts(force = false)
                val hintTag = editText.tag as? String ?: ""
                editText.hint = t(hintTag)
                val coachTag = coachEditText.tag as? String ?: ""
                coachEditText.hint = t(coachTag)
            }
            override fun onNothingSelected(parent: AdapterView<*>) {}
        }
    }

    private fun setupLoadButton() {
        LoadButtonHandler(
            activity = activity,
            loadButton = buttonLoad,
            editText = editText,
            languageIDProvider = { languageID },
            questionnaireEntriesProvider = { questionnaireEntries },
            dynamicButtonsProvider = { dynamicButtons },
            buttonPoints = buttonPoints,
            updateButtonTexts = { applyUpdateButtonTexts(force = false) },
            setButtonsEnabled = { list -> applySetButtonsEnabled(list, allowCompleted = true, force = false) },
            updateMainButtonsState = { updateMainButtonsState(it) },
        ).setup()
    }

    private fun applyUpdateButtonTexts(force: Boolean) {
        if (uiFreeze && !force) return
        updateStatusStrip()
        questionnaireFiles.forEach { (button, fileName) ->
            val entry = questionnaireEntries.firstOrNull { it.file == fileName }
            val key = fileName.substringAfter("questionnaire_").substringAfter("_").removeSuffix(".json")
            val titleText = t(key)
            val parts = cardParts[button] ?: return@forEach
            parts.title.text = titleText
            val points = buttonPoints.entries.firstOrNull { fileName.contains(it.key, ignoreCase = true) }?.value
            val completed = isCompleted(button)
            val enabled = button.isEnabled
            val locked = !enabled && !completed
            setClickableStroke(button, enabled)
            if (locked) {
                setLockedAppearance(button, true)
                parts.title.setTextColor(Color.WHITE)
                parts.subtitle.setTextColor(Color.parseColor("#E0E0E0"))
            } else {
                setLockedAppearance(button, false)
                parts.title.setTextColor(Color.parseColor("#2F2A49"))
                parts.subtitle.setTextColor(Color.parseColor("#7B7794"))
                applyTintForButton(button, points, emphasize = enabled)
            }
            if (entry?.showPoints == true && points != null) {
                parts.subtitle.visibility = View.VISIBLE
                parts.subtitle.text = "${t("points")}: $points"
            } else {
                parts.subtitle.visibility = View.GONE
                parts.subtitle.text = ""
            }
            when {
                completed -> {
                    parts.chip.text = t("done")
                    parts.chip.setBackgroundResource(R.drawable.bg_chip_green)
                    parts.chip.setTextColor(Color.WHITE)
                }
                enabled -> {
                    parts.chip.text = t("start")
                    parts.chip.setBackgroundResource(R.drawable.bg_chip_amber)
                    parts.chip.setTextColor(Color.WHITE)
                }
                else -> {
                    parts.chip.text = t("locked")
                    parts.chip.setBackgroundResource(R.drawable.bg_chip_grey)
                    parts.chip.setTextColor(Color.parseColor("#2F2A49"))
                }
            }
        }
        buttonLoad.text     = t("load")
        saveButton.text     = t("save")
        uploadButton.text   = t("upload")
        downloadButton.text = t("download")
        val hintTag = editText.tag as? String ?: ""
        editText.hint = t(hintTag)
        val coachTag = coachEditText.tag as? String ?: ""
        coachEditText.hint = t(coachTag)
        textView.text = t("example_text")
    }

    private fun applySetButtonsEnabled(enabledButtons: List<Button>, allowCompleted: Boolean, force: Boolean) {
        if (uiFreeze && !force) return
        questionnaireFiles.keys.forEach { button ->
            val completed = isCompleted(button)
            val isAllowed = enabledButtons.contains(button)
            val shouldEnable = if (allowCompleted) isAllowed else isAllowed && !completed
            val locked = !shouldEnable && !completed
            button.isEnabled = shouldEnable
            button.alpha = if (completed || shouldEnable) 1.0f else 0.6f
            setClickableStroke(button, shouldEnable)
            cardParts[button]?.let { parts ->
                if (locked) {
                    setLockedAppearance(button, true)
                    parts.title.setTextColor(Color.WHITE)
                    parts.subtitle.setTextColor(Color.parseColor("#E0E0E0"))
                } else {
                    setLockedAppearance(button, false)
                    parts.title.setTextColor(Color.parseColor("#2F2A49"))
                    parts.subtitle.setTextColor(Color.parseColor("#7B7794"))
                    applyTintForButton(button, getPointsForButton(button), emphasize = shouldEnable)
                }
                when {
                    completed -> {
                        parts.chip.text = t("done")
                        parts.chip.setBackgroundResource(R.drawable.bg_chip_green)
                        parts.chip.setTextColor(Color.WHITE)
                    }
                    shouldEnable -> {
                        parts.chip.text = t("start")
                        parts.chip.setBackgroundResource(R.drawable.bg_chip_amber)
                        parts.chip.setTextColor(Color.WHITE)
                    }
                    else -> {
                        parts.chip.text = t("locked")
                        parts.chip.setBackgroundResource(R.drawable.bg_chip_grey)
                        parts.chip.setTextColor(Color.parseColor("#2F2A49"))
                    }
                }
            }
        }
    }

    private fun startQuestionnaire(questionnaire: QuestionnaireBase<*>) {
        activity.startQuestionnaire(questionnaire, languageID)
    }

    fun onBackPressed(): Boolean = false

    private fun setupSaveButton() {
        SaveButtonHandler(
            activity = activity,
            saveButton = saveButton,
            editText = editText,
            languageIDProvider = { languageID }
        ).setup()
    }

    private fun setupUploadButton() {
        uploadButton.text = t("upload")
        uploadButton.setOnClickListener {
            // ZUERST bestätigen lassen
            confirmUpload {
                // === dein bestehender Upload-Code unverändert ===
                val existingToken = TokenStore.getToken(activity)
                val ageMs = System.currentTimeMillis() - TokenStore.getLoginTimestamp(activity)
                val isFresh = !existingToken.isNullOrBlank() && ageMs < 23 * 60 * 60 * 1000

                if (isFresh) {
                    GlobalValues.LAST_CLIENT_CODE = editText.text.toString().trim()
                    DatabaseUploader.uploadDatabaseWithToken(activity, existingToken!!)
                    return@confirmUpload
                }

                val username = TokenStore.getUsername(activity)?.trim().orEmpty()
                if (username.isBlank()) {
                    Toast.makeText(activity, t("login_required"), Toast.LENGTH_LONG).show()
                    return@confirmUpload
                }

                val password = when (username) {
                    "user01" -> "pw1"
                    "user02" -> "pw2"
                    else -> {
                        Toast.makeText(activity, t("login_required"), Toast.LENGTH_LONG).show()
                        return@confirmUpload
                    }
                }

                LoginManager.loginUserWithCredentials(
                    context = activity,
                    username = username,
                    password = password,
                    onSuccess = { freshToken ->
                        GlobalValues.LAST_CLIENT_CODE = editText.text.toString().trim()
                        DatabaseUploader.uploadDatabaseWithToken(activity, freshToken)
                    },
                    onError = { msg ->
                        Toast.makeText(activity, t("login_failed_with_reason").replace("{reason}", msg), Toast.LENGTH_LONG).show()
                    }
                )
            }
        }
    }

    private fun setupDownloadButton() {
        downloadButton.text = t("download")

        // Bei Setup gleich den aktuellen Zustand anwenden
        val hasDb = File("/data/data/com.dano.test1/databases/questionnaire_database").exists()
        updateDownloadButtonState(hasDb)

        downloadButton.setOnClickListener {
            // Falls der Button (später) deaktiviert ist, passiert einfach nichts
            if (!downloadButton.isEnabled) return@setOnClickListener
            Toast.makeText(activity, t("login_required"), Toast.LENGTH_SHORT).show()
        }
    }

    private fun updateMainButtonsState(isDatabaseAvailable: Boolean) {
        listOf(buttonLoad, saveButton).forEach { b ->
            b.isEnabled = isDatabaseAvailable
            b.alpha = if (isDatabaseAvailable) 1.0f else 0.5f
        }
        // Der Download-Button wird separat gesteuert
    }

    private fun updateDownloadButtonState(isDatabaseAvailable: Boolean) {
        val mb = downloadButton as? MaterialButton
        if (isDatabaseAvailable) {
            downloadButton.isEnabled = false
            downloadButton.alpha = 0.5f
            mb?.apply {
                strokeWidth = dp(1)
                strokeColor = ColorStateList.valueOf(STROKE_DISABLED)
                backgroundTintList = ColorStateList.valueOf(Color.parseColor("#F5F5F5"))
                rippleColor = ColorStateList.valueOf(Color.parseColor("#00000000"))
            }
        } else {
            downloadButton.isEnabled = true
            downloadButton.alpha = 1.0f
            mb?.apply {
                strokeWidth = dp(2)
                strokeColor = ColorStateList.valueOf(STROKE_ENABLED)
                backgroundTintList = ColorStateList.valueOf(Color.WHITE)
                rippleColor = ColorStateList.valueOf(Color.parseColor("#22000000"))
            }
        }
    }

    private fun dp(v: Int): Int = ViewUtils.dp(activity, v)

    private fun isCompleted(button: Button): Boolean {
        val fileName = questionnaireFiles[button] ?: return false
        return buttonPoints.keys.any { k ->
            fileName.contains(k, ignoreCase = true) || k.contains(fileName, ignoreCase = true)
        }
    }

    private fun getPointsForButton(button: Button): Int? {
        val fileName = questionnaireFiles[button] ?: return null
        return buttonPoints.entries.firstOrNull { (k, _) ->
            fileName.contains(k, ignoreCase = true) || k.contains(fileName, ignoreCase = true)
        }?.value
    }

    private fun setLockedAppearance(button: Button, locked: Boolean) {
        val mb = button as? MaterialButton ?: return
        if (locked) {
            mb.backgroundTintList = ColorStateList.valueOf(Color.BLACK)
            mb.strokeColor = ColorStateList.valueOf(STROKE_DISABLED)
        } else {
            mb.backgroundTintList = ColorStateList.valueOf(Color.WHITE)
            mb.strokeColor = ColorStateList.valueOf(if (button.isEnabled) STROKE_ENABLED else STROKE_DISABLED)
        }
    }

    private fun resetTint(button: Button) {
        val mb = button as? MaterialButton ?: return
        mb.backgroundTintList = ColorStateList.valueOf(Color.WHITE)
        mb.strokeColor = ColorStateList.valueOf(STROKE_DISABLED)
    }

    private fun applyTintForButton(button: Button, points: Int?, emphasize: Boolean) {
        val file = questionnaireFiles[button] ?: return
        val entry = questionnaireEntries.firstOrNull { it.file == file }
        if (entry?.showPoints != true) {
            val mb = button as? MaterialButton ?: return
            mb.backgroundTintList = ColorStateList.valueOf(if (emphasize) Color.parseColor("#F1EEFF") else Color.WHITE)
            mb.strokeColor = ColorStateList.valueOf(if (emphasize) STROKE_ENABLED else STROKE_DISABLED)
            return
        }
        setScoreTint(button, points, emphasize)
    }

    private fun setClickableStroke(button: Button, enabled: Boolean) {
        val mb = button as? MaterialButton ?: return
        mb.strokeWidth = if (enabled) dp(2) else dp(1)
        mb.strokeColor = ColorStateList.valueOf(if (enabled) STROKE_ENABLED else STROKE_DISABLED)
    }

    private fun setScoreTint(button: Button, points: Int?, emphasize: Boolean) {
        val mb = button as? MaterialButton ?: return
        val bg = when {
            points == null && emphasize -> Color.parseColor("#F1EEFF")
            points == null -> Color.parseColor("#FFFFFF")
            points in 0..12 && emphasize -> Color.parseColor("#C8E6C9")
            points in 0..12 -> Color.parseColor("#E8F5E9")
            points in 13..36 && emphasize -> Color.parseColor("#FFE0B2")
            points in 13..36 -> Color.parseColor("#FFF8E1")
            points >= 37 && emphasize -> Color.parseColor("#FFCDD2")
            else -> Color.parseColor("#FFEBEE")
        }
        mb.backgroundTintList = ColorStateList.valueOf(bg)
        mb.strokeColor = ColorStateList.valueOf(if (emphasize) STROKE_ENABLED else STROKE_DISABLED)
    }

    private fun updateStatusStrip() {
        val ts = TokenStore.getLoginTimestamp(activity)
        val ageMs = if (ts > 0L) (System.currentTimeMillis() - ts) else 0L
        val h = TimeUnit.MILLISECONDS.toHours(ageMs)
        val m = TimeUnit.MILLISECONDS.toMinutes(ageMs) - h * 60
        if (ts > 0L) {
            // ⚠️ anhängen, wenn >12h, der eigentliche Hinweis/Styling kommt aus applySessionAgeHighlight()
            val warn = if (ageMs >= SESSION_WARN_AFTER_MS) "  ⚠️" else ""
            statusSession.text = "${t("session_label")}: ${h}${t("hours_short")} ${m}${t("minutes_short")}$warn"
        } else {
            statusSession.text = t("session_dash")
        }
        val online = NetworkUtils.isOnline(activity)
        statusOnline.text = if (online) t("online") else t("offline")
        statusOnline.setTextColor(if (online) Color.parseColor("#2E7D32") else Color.parseColor("#C62828"))

        // <<< NEU: hier jeweils prüfen/markieren
        applySessionAgeHighlight(ageMs)
    }

    fun refreshHeaderStatusLive() {
        applyUpdateButtonTexts(force = true)
    }

    private fun lockCoachCodeField() {
        ViewUtils.lockEditField(coachEditText)
    }

    private fun applySessionAgeHighlight(ageMs: Long) {
        val isOld = ageMs >= SESSION_WARN_AFTER_MS
        if (isOld) {
            statusSession.setTextColor(Color.parseColor("#C62828"))
            statusSession.setBackgroundColor(Color.parseColor("#FFF3CD"))
            statusSession.setPadding(dp(8), dp(4), dp(8), dp(4))
            if (!sessionLongWarnedOnce) {
                showRedToast(activity, t("session_over_12"))
                sessionLongWarnedOnce = true
            }
        } else {
            statusSession.setTextColor(Color.parseColor("#2F2A49"))
            statusSession.setBackgroundColor(Color.TRANSPARENT)
            statusSession.setPadding(0, 0, 0, 0)
        }
    }



    private fun showRedToast(ctx: Context, message: String) {
        val tv = TextView(ctx).apply {
            text = message
            setTextColor(Color.WHITE)
            textSize = 16f
            setPadding(32, 20, 32, 20)
            background = GradientDrawable().apply {
                shape = GradientDrawable.RECTANGLE
                cornerRadius = 24f
                setColor(Color.parseColor("#D32F2F")) // kräftiges Rot
            }
        }
        Toast(ctx).apply {
            duration = Toast.LENGTH_LONG
            view = tv
            setGravity(Gravity.TOP or Gravity.CENTER_HORIZONTAL, 0, 120)
        }.show()
    }

    private fun confirmUpload(onConfirm: () -> Unit) {
        MaterialAlertDialogBuilder(activity)
            .setTitle(t("start_upload"))
            .setMessage(t("ask_before_upload"))
            .setPositiveButton(t("ok")) { d, _ ->
                d.dismiss()
                onConfirm()
            }
            .setNegativeButton(t("cancel")) { d, _ ->
                d.dismiss()
            }
            .show()
    }


}
