package com.dano.test1.ui

import android.graphics.Color
import android.graphics.Typeface
import android.util.Log
import android.view.View
import android.widget.*
import com.dano.test1.data.ExcelExportService
import com.dano.test1.utils.ViewUtils
import androidx.appcompat.app.AppCompatActivity
import com.dano.test1.LanguageManager
import com.dano.test1.MyApp
import com.dano.test1.R
import com.dano.test1.data.Client
import com.dano.test1.data.HeaderOrderRepository
import com.dano.test1.data.Question
import com.dano.test1.data.Questionnaire
import kotlinx.coroutines.*
import org.json.JSONArray

class DatabaseButtonHandler(
    private val activity: AppCompatActivity,
    private val databaseButton: Button,
    private val onClose: () -> Unit,
    private val languageIDProvider: () -> String = { "GERMAN" }
) {
    private val uiScope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
    private val tag = "DatabaseButtonHandler"

    private val headerRepo = HeaderOrderRepository(activity)
    private val exporter   = ExcelExportService(activity, headerRepo)

    fun setup() {
        val lang = safeLang()
        databaseButton.text = t(lang, "database") ?: "Datenbank"
        databaseButton.setOnClickListener { openDatabaseScreen() }
    }

    // ---------------------------
    // SCREEN 1: Client-Liste
    // ---------------------------
    private fun openDatabaseScreen() {
        activity.setContentView(R.layout.database_screen)

        val lang = safeLang()

        val titleTv: TextView = requireView(R.id.title, "title")
        val table: TableLayout = requireView(R.id.tableClients, "tableClients")
        val progress: ProgressBar = requireView(R.id.progressBar, "progressBar")
        val emptyView: TextView = requireView(R.id.emptyView, "emptyView")
        val backButton: Button = requireView(R.id.backButton, "backButton")
        val btnDownloadHeader: Button = requireView(R.id.btnDownloadHeader, "btnDownloadHeader")

        titleTv.text = t(lang, "database_clients_title") ?: "Datenbank – Clients"
        emptyView.text = t(lang, "no_clients_available") ?: "Keine Clients vorhanden."
        backButton.text = t(lang, "previous") ?: "Zurück"
        btnDownloadHeader.text = t(lang, "download_header") ?: "Download Header"

        backButton.setOnClickListener { onClose() }
        btnDownloadHeader.setOnClickListener { onDownloadHeadersClicked(progress) }

        progress.visibility = View.VISIBLE
        emptyView.visibility = View.GONE
        table.removeAllViews()

        addHeaderRow(table, listOf("#", t(lang, "client_code") ?: "Client-Code"))

        uiScope.launch {
            val clients: List<Client> = withContext(Dispatchers.IO) {
                MyApp.database.clientDao().getAllClients()
            }

            progress.visibility = View.GONE

            if (clients.isEmpty()) {
                emptyView.visibility = View.VISIBLE
                return@launch
            }

            clients.forEachIndexed { index, client ->
                addClickableRow(
                    table = table,
                    cells = listOf((index + 1).toString(), client.clientCode),
                    onClick = { openClientOverviewScreen(client.clientCode) }
                )
            }
        }
    }

    // ---------------------------
    // Export: Header aller Clients als Excel
    // ---------------------------
    private fun onDownloadHeadersClicked(progress: ProgressBar) {
        val lang = safeLang()
        uiScope.launch {
            try {
                progress.visibility = View.VISIBLE
                val savedUri = exporter.exportHeadersForAllClients()
                progress.visibility = View.GONE

                if (savedUri != null) {
                    Toast.makeText(
                        activity,
                        t(lang, "export_success_downloads") ?: "Export erfolgreich: Downloads/ClientHeaders.xlsx",
                        Toast.LENGTH_LONG
                    ).show()
                } else {
                    Toast.makeText(activity, t(lang, "export_failed") ?: "Export fehlgeschlagen.", Toast.LENGTH_LONG).show()
                }
            } catch (e: Exception) {
                progress.visibility = View.GONE
                Log.e(tag, "Download Header Fehler: ${e.message}", e)
                val prefix = t(lang, "error") ?: "Fehler"
                Toast.makeText(activity, "$prefix: ${e.message}", Toast.LENGTH_LONG).show()
            }
        }
    }

    // ---------------------------
    // SCREEN 2: Fragebogen-Übersicht + "header"-Liste
    // ---------------------------
    private fun openClientOverviewScreen(clientCode: String) {
        activity.setContentView(R.layout.client_overview_screen)

        val lang = safeLang()

        val title: TextView = requireView(R.id.titleClientOverview, "titleClientOverview")
        val tableQ: TableLayout = requireView(R.id.tableQuestionnaires, "tableQuestionnaires")
        val progress: ProgressBar = requireView(R.id.progressBarClient, "progressBarClient")
        val emptyView: TextView = requireView(R.id.emptyViewClient, "emptyViewClient")
        val backButton: Button = requireView(R.id.backButtonClient, "backButtonClient")

        val headerLabel: TextView = requireView(R.id.headerLabel, "headerLabel")
        val tableOrdered: TableLayout = requireView(R.id.tableOrdered, "tableOrdered")

        title.text = "${t(lang, "client") ?: "Client"}: $clientCode – ${t(lang, "questionnaires") ?: "Fragebögen"}"
        headerLabel.text = t(lang, "headers") ?: "Header"
        backButton.text = t(lang, "previous") ?: "Zurück"
        backButton.setOnClickListener { openDatabaseScreen() }

        progress.visibility = View.VISIBLE
        emptyView.visibility = View.GONE
        tableQ.removeAllViews()
        tableOrdered.removeAllViews()

        addHeaderRow(
            tableQ,
            listOf("#", t(lang, "questionnaire_id") ?: "Fragebogen-ID", t(lang, "status") ?: "Status")
        )
        addHeaderRow(
            tableOrdered,
            listOf("#", t(lang, "id") ?: "ID", t(lang, "value") ?: "Wert")
        )

        uiScope.launch {
            val result = withContext(Dispatchers.IO) {
                val allQuestionnairesDb = MyApp.database.questionnaireDao().getAll()
                val completedForClient   = MyApp.database.completedQuestionnaireDao().getAllForClient(clientCode)
                val allAnswersForClient  = MyApp.database.answerDao().getAnswersForClient(clientCode)
                Triple(allQuestionnairesDb, completedForClient, allAnswersForClient)
            }

            // IDs aus der JSON-Reihenfolge lesen (alle, die es geben soll)
            val idsFromAssets: List<String> = loadQuestionnaireIdsFromAssets()

            progress.visibility = View.GONE

            val dbQuestionnaires: List<Questionnaire> = result.first
            val completedForClient = result.second
            val allAnswersForClient = result.third

            // Vereinigung: alles was in JSON steht + alles was in der DB existiert
            val allIds: List<String> =
                (idsFromAssets + dbQuestionnaires.map { it.id }).distinct()

            if (allIds.isEmpty()) {
                emptyView.text = t(lang, "no_questionnaires") ?: "Keine Fragebögen vorhanden."
                emptyView.visibility = View.VISIBLE
            }

            val statusMap = completedForClient.associate { it.questionnaireId to it.isDone }
            val questionnaireIdSet = allIds.toSet() // für die zweite Tabelle
            val answerMap = allAnswersForClient.associate { it.questionId to it.answerValue }

            // Tabelle 1 (Status) – JETZT mit allen IDs
            allIds
                .sortedWith(compareBy({ extractQuestionnaireNumber(it) ?: Int.MAX_VALUE }, { it }))
                .forEachIndexed { idx, qid ->
                    val isDone = statusMap[qid] ?: false
                    val statusText = if (isDone) "✓" else "✗"
                    val statusTextColor = if (isDone) 0xFF4CAF50.toInt() else 0xFFF44336.toInt()

                    if (isDone) {
                        addClickableRow(
                            table = tableQ,
                            cells = listOf((idx + 1).toString(), qid, statusText),
                            onClick = { openQuestionnaireDetailScreen(clientCode, qid) },
                            colorOverrides = mapOf(2 to statusTextColor)
                        )
                    } else {
                        addDisabledRow(
                            table = tableQ,
                            cells = listOf((idx + 1).toString(), qid, statusText),
                            colorOverrides = mapOf(2 to statusTextColor)
                        )
                    }
                }

            // Farben
            val lightGreen = 0xFFC8E6C9.toInt()
            val lightRed   = 0xFFFFCDD2.toInt()
            val doneGreen  = 0xFF4CAF50.toInt()
            val notRed     = 0xFFF44336.toInt()

            // Tabelle 2 (Header-Liste)
            val orderedIds = headerRepo.loadOrderedIds()
            orderedIds.forEachIndexed { idx, id ->
                var rowBgColor: Int? = null
                val raw: String
                val cellBgForQuestionnaire: Int?

                if (id == "client_code") {
                    raw = clientCode
                    cellBgForQuestionnaire = null
                } else if (id in questionnaireIdSet) {
                    raw = if (statusMap[id] == true) "Done" else "Not Done"
                    cellBgForQuestionnaire = if (raw == "Done") doneGreen else notRed
                } else {
                    raw = answerMap[id]?.takeIf { it.isNotBlank() } ?: "None"
                    cellBgForQuestionnaire = null
                    rowBgColor = if (raw == "None") lightRed else lightGreen
                }

                val display = localizeHeaderValue(id, raw, lang)

                val cellBgOverrides =
                    if (cellBgForQuestionnaire != null)
                        mapOf(0 to cellBgForQuestionnaire, 1 to cellBgForQuestionnaire, 2 to cellBgForQuestionnaire)
                    else emptyMap()

                addRow(
                    table = tableOrdered,
                    cells = listOf((idx + 1).toString(), id, display),
                    rowBgColor = rowBgColor,
                    cellBgOverrides = cellBgOverrides
                )
            }
        }
    }

    // ---------------------------
    // SCREEN 3: Fragen & Antworten eines Fragebogens
    // ---------------------------
    private fun openQuestionnaireDetailScreen(clientCode: String, questionnaireId: String) {
        activity.setContentView(R.layout.questionnaire_detail_screen)

        val lang = safeLang()

        val title: TextView = requireView(R.id.titleQuestionnaireDetail, "titleQuestionnaireDetail")
        val table: TableLayout = requireView(R.id.tableQA, "tableQA")
        val progress: ProgressBar = requireView(R.id.progressBarQA, "progressBarQA")
        val emptyView: TextView = requireView(R.id.emptyViewQA, "emptyViewQA")
        val backButton: Button = requireView(R.id.backButtonQA, "backButtonQA")

        title.text = "${t(lang, "client") ?: "Client"}: $clientCode – ${t(lang, "questionnaire") ?: "Fragebogen"}: $questionnaireId"
        backButton.text = t(lang, "previous") ?: "Zurück"
        emptyView.text = t(lang, "no_questions_available") ?: "Keine Fragen vorhanden."
        backButton.setOnClickListener { openClientOverviewScreen(clientCode) }

        progress.visibility = View.VISIBLE
        emptyView.visibility = View.GONE
        table.removeAllViews()

        addHeaderRow(table, listOf("#", t(lang, "question") ?: "Frage", t(lang, "answer") ?: "Antwort"))

        uiScope.launch {
            val (questions, answersForClient) = withContext(Dispatchers.IO) {
                val qs = MyApp.database.questionDao().getQuestionsForQuestionnaire(questionnaireId)
                val ans = MyApp.database.answerDao()
                    .getAnswersForClientAndQuestionnaire(clientCode, questionnaireId)
                qs to ans
            }

            progress.visibility = View.GONE

            if (questions.isEmpty()) {
                emptyView.visibility = View.VISIBLE
                return@launch
            }

            val answerMap = answersForClient.associate { it.questionId to it.answerValue }

            questions.forEachIndexed { idx, q: Question ->
                val baseId = q.questionId.substringAfterLast('-', q.questionId)
                val qText = localizeQuestionLabel(q.questionId, q.question, lang)
                val raw = answerMap[q.questionId]?.takeIf { it.isNotBlank() } ?: "—"
                val aText = localizeAnswerValue(baseId, raw, lang)
                addRow(table, listOf((idx + 1).toString(), qText, aText))
            }
        }
    }

    // ---------------------------
    // Hilfen
    // ---------------------------

    private fun safeLang(): String = try { languageIDProvider() } catch (_: Exception) { "GERMAN" }

    private fun stripBrackets(s: String): String {
        val m = Regex("^\\[(.*)]$").matchEntire(s.trim())
        return m?.groupValues?.get(1) ?: s
    }

    private fun t(lang: String, key: String): String? {
        val txt = try { LanguageManager.getText(lang, key) } catch (_: Exception) { null } ?: return null
        val out = stripBrackets(txt).trim()
        return if (out.equals(key, true) || out.isBlank()) null else out
    }

    private fun localizeQuestionLabel(questionId: String, fallbackQuestionText: String?, lang: String): String {
        val field = questionId.substringAfterLast('-', questionId)
        t(lang, field)?.let { return it }
        t(lang, questionId)?.let { return it }
        fallbackQuestionText?.takeIf { it.isNotBlank() }?.let { return it }
        return field.replace('_', ' ').replaceFirstChar { it.titlecase() }
    }

    private fun localizeAnswerValue(fieldId: String, raw: String, lang: String): String {
        if (raw == "—") return raw
        if (raw.matches(Regex("^\\d{1,4}([./-]\\d{1,2}([./-]\\d{1,4})?)?\$"))) return raw
        t(lang, raw)?.let { return it }
        val norm = raw.lowercase().replace(Regex("[^a-z0-9]+"), "_").trim('_')
        if (norm.isNotBlank()) t(lang, norm)?.let { return it }
        if (norm.isNotBlank()) {
            t(lang, "${fieldId}_$norm")?.let { return it }
            t(lang, "${fieldId}-${norm}")?.let { return it }
        }
        return stripBrackets(raw)
    }

    private fun addHeaderRow(table: TableLayout, labels: List<String>) {
        val row = TableRow(activity)
        labels.forEach { label -> row.addView(makeHeaderCell(label)) }
        table.addView(row); addDivider(table)
    }

    private fun addRow(
        table: TableLayout,
        cells: List<String>,
        colorOverrides: Map<Int, Int> = emptyMap(),
        rowBgColor: Int? = null,
        cellBgOverrides: Map<Int, Int> = emptyMap()
    ) {
        val row = TableRow(activity)
        rowBgColor?.let { row.setBackgroundColor(it) }
        cells.forEachIndexed { index, text ->
            val tv = makeBodyCell(text, colorOverrides[index], cellBgOverrides[index]); row.addView(tv)
        }
        table.addView(row); addDivider(table)
    }

    private fun addClickableRow(
        table: TableLayout,
        cells: List<String>,
        onClick: () -> Unit,
        colorOverrides: Map<Int, Int> = emptyMap(),
        cellBgOverrides: Map<Int, Int> = emptyMap()
    ) {
        val row = TableRow(activity).apply {
            isClickable = true
            isFocusable = true
            setBackgroundColor(Color.TRANSPARENT)
            setOnClickListener { onClick() }
        }
        cells.forEachIndexed { index, text ->
            val tv = makeBodyCell(text, colorOverrides[index], cellBgOverrides[index]); row.addView(tv)
        }
        table.addView(row); addDivider(table)
    }

    private fun addDisabledRow(
        table: TableLayout,
        cells: List<String>,
        colorOverrides: Map<Int, Int> = emptyMap(),
        cellBgOverrides: Map<Int, Int> = emptyMap()
    ) {
        val row = TableRow(activity).apply { isClickable = false; isEnabled = false; alpha = 0.6f }
        cells.forEachIndexed { index, text ->
            val tv = makeBodyCell(text, colorOverrides[index], cellBgOverrides[index]); row.addView(tv)
        }
        table.addView(row); addDivider(table)
    }

    private fun addDivider(table: TableLayout) {
        val divider = View(activity)
        val params = TableLayout.LayoutParams(TableLayout.LayoutParams.MATCH_PARENT, dp(1))
        divider.layoutParams = params
        divider.setBackgroundColor(0xFFDDDDDD.toInt())
        table.addView(divider)
    }

    private fun makeHeaderCell(text: String): TextView =
        TextView(activity).apply {
            this.text = text
            setPadding(dp(12), dp(10), dp(12), dp(10))
            textSize = 16f
            setTypeface(typeface, Typeface.BOLD)
        }

    private fun makeBodyCell(
        text: String,
        textColor: Int? = null,
        bgColor: Int? = null
    ): TextView =
        TextView(activity).apply {
            this.text = text
            setPadding(dp(12), dp(10), dp(12), dp(10))
            textSize = 15f
            textColor?.let { setTextColor(it) }
            bgColor?.let { setBackgroundColor(it) }
        }

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

    private fun <T : View> requireView(id: Int, name: String): T {
        val v = activity.findViewById<T>(id)
        if (v == null) {
            val lang = safeLang()
            val prefix = t(lang, "view_missing") ?: "Fehlende View: %s"
            val msg = prefix.replace("%s", name)
            Log.e(tag, msg)
            Toast.makeText(activity, msg, Toast.LENGTH_LONG).show()
            throw IllegalStateException(msg)
        }
        return v
    }

    private fun extractQuestionnaireNumber(id: String): Int? {
        val m = Regex("^questionnaire_(\\d+)").find(id.lowercase())
        return m?.groupValues?.get(1)?.toIntOrNull()
    }

    private fun localizeHeaderValue(id: String, raw: String, lang: String): String {
        if (id == "client_code") return raw

        fun norm(s: String) = s.lowercase().replace(Regex("[^a-z0-9]+"), "_").trim('_')
        val candidates = buildList {
            when (raw) { "Done" -> add("done"); "Not Done" -> add("not_done"); "None" -> add("none") }
            add(raw)
            val n = norm(raw)
            if (n.isNotBlank() && n != raw) add(n)
            if (n.isNotBlank()) { add("${id}_$n"); add("${id}-$n") }
        }
        for (k in candidates) t(lang, k)?.let { return it }
        return stripBrackets(raw)
    }

    /** Lädt alle Fragebogen-IDs aus questionnaire_order.json (file ohne .json). */
    private fun loadQuestionnaireIdsFromAssets(): List<String> = try {
        val input = activity.assets.open("questionnaire_order.json")
        val json = input.bufferedReader().use { it.readText() }
        val arr = JSONArray(json)
        (0 until arr.length()).mapNotNull { i ->
            val obj = arr.optJSONObject(i)
            obj?.optString("file")?.removeSuffix(".json")
        }
    } catch (_: Exception) {
        emptyList()
    }
}
