package com.bytelyst.platform.ui

import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowDownward
import androidx.compose.material.icons.filled.ArrowUpward
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.CheckCircle
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.filled.RadioButtonUnchecked
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import com.bytelyst.platform.*
import com.bytelyst.platform.BLSurveyClient.ActiveSurvey
import com.bytelyst.platform.BLSurveyClient.Question
import com.bytelyst.platform.BLSurveyClient.QuestionOption
import com.bytelyst.platform.BLSurveyClient.SurveyAnswer
import com.bytelyst.platform.BLSurveyClient.SurveyIncentive
import com.bytelyst.platform.BLSurveyClient.QuestionType
import kotlinx.coroutines.launch
import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.JsonPrimitive

/**
 * Survey Modal — Jetpack Compose component for displaying and completing surveys.
 * Part of ByteLystPlatformSDK.
 */
@Composable
fun SurveyModal(
    client: BLSurveyClient,
    modifier: Modifier = Modifier
) {
    val scope = rememberCoroutineScope()
    var survey by remember { mutableStateOf<ActiveSurvey?>(null) }
    var currentQuestionIndex by remember { mutableIntStateOf(0) }
    var answers by remember { mutableStateOf<Map<String, SurveyAnswer>>(emptyMap()) }
    var isComplete by remember { mutableStateOf(false) }
    var showCompletion by remember { mutableStateOf(false) }
    var showDialog by remember { mutableStateOf(false) }

    // Question state
    var selectedOption by remember { mutableStateOf<String?>(null) }
    var selectedOptions by remember { mutableStateOf<Set<String>>(emptySet()) }
    var ratingValue by remember { mutableIntStateOf(0) }
    var textAnswer by remember { mutableStateOf("") }
    var rankingOrder by remember { mutableStateOf<List<String>>(emptyList()) }

    LaunchedEffect(client) {
        // Check for active survey
        val result = client.getActiveSurvey()
        result.onSuccess { response ->
            response?.let {
                survey = it
                showDialog = true
            }
        }

        // Start polling
        client.startPolling(60000L) { newSurvey ->
            if (newSurvey != null && survey == null) {
                survey = newSurvey
                showDialog = true
            }
        }
    }

    fun doResetSurvey() {
        survey = null
        currentQuestionIndex = 0
        answers = emptyMap()
        isComplete = false
        showCompletion = false
        resetQuestionState(
            onSelectedOption = { selectedOption = it },
            onSelectedOptions = { selectedOptions = it },
            onRating = { ratingValue = it },
            onText = { textAnswer = it },
            onRanking = { rankingOrder = it }
        )
    }

    if (showDialog) {
        when {
            showCompletion -> {
                CompletionDialog(
                    survey = survey,
                    onDismiss = {
                        scope.launch {
                            survey?.let { client.dismissSurvey(it.id) }
                        }
                        showDialog = false
                        doResetSurvey()
                    }
                )
            }
            survey != null && currentQuestionIndex < survey!!.questions.size -> {
                val question = survey!!.questions[currentQuestionIndex]
                QuestionDialog(
                    survey = survey!!,
                    question = question,
                    questionIndex = currentQuestionIndex,
                    totalQuestions = survey!!.questions.size,
                    selectedOption = selectedOption,
                    selectedOptions = selectedOptions,
                    ratingValue = ratingValue,
                    textAnswer = textAnswer,
                    rankingOrder = rankingOrder,
                    onSelectedOptionChange = { selectedOption = it },
                    onSelectedOptionsChange = { selectedOptions = it },
                    onRatingChange = { ratingValue = it },
                    onTextChange = { textAnswer = it },
                    onRankingChange = { rankingOrder = it },
                    onSubmit = {
                        scope.launch {
                            submitAnswer(
                                client = client,
                                survey = survey!!,
                                question = question,
                                selectedOption = selectedOption,
                                selectedOptions = selectedOptions,
                                ratingValue = ratingValue,
                                textAnswer = textAnswer,
                                rankingOrder = rankingOrder,
                                onSuccess = { newIndex, newAnswers ->
                                    currentQuestionIndex = newIndex
                                    answers = newAnswers
                                    resetQuestionState(
                                        onSelectedOption = { selectedOption = it },
                                        onSelectedOptions = { selectedOptions = it },
                                        onRating = { ratingValue = it },
                                        onText = { textAnswer = it },
                                        onRanking = { rankingOrder = it }
                                    )

                                    if (currentQuestionIndex >= survey!!.questions.size) {
                                        scope.launch {
                                            completeSurvey(client, survey!!.id) { success, _ ->
                                                if (success) {
                                                    isComplete = true
                                                    showCompletion = true
                                                }
                                            }
                                        }
                                    }
                                }
                            )
                        }
                    },
                    onSkip = {
                        if (!question.required) {
                            scope.launch {
                                skipQuestion(client, survey!!, question.id) { newIndex ->
                                    currentQuestionIndex = newIndex
                                    resetQuestionState(
                                        onSelectedOption = { selectedOption = it },
                                        onSelectedOptions = { selectedOptions = it },
                                        onRating = { ratingValue = it },
                                        onText = { textAnswer = it },
                                        onRanking = { rankingOrder = it }
                                    )

                                    if (currentQuestionIndex >= survey!!.questions.size) {
                                        scope.launch {
                                            completeSurvey(client, survey!!.id) { success, _ ->
                                                if (success) {
                                                    isComplete = true
                                                    showCompletion = true
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    onDismiss = {
                        scope.launch {
                            survey?.let { client.dismissSurvey(it.id) }
                        }
                        showDialog = false
                        doResetSurvey()
                    }
                )
            }
        }
    }
}

private suspend fun submitAnswer(
    client: BLSurveyClient,
    survey: ActiveSurvey,
    question: Question,
    selectedOption: String?,
    selectedOptions: Set<String>,
    ratingValue: Int,
    textAnswer: String,
    rankingOrder: List<String>,
    onSuccess: (Int, Map<String, SurveyAnswer>) -> Unit
) {
    val qType = question.type.toQuestionType()
    val answer: SurveyAnswer = when (qType) {
        QuestionType.SINGLE_CHOICE, QuestionType.DROPDOWN -> {
            selectedOption?.let {
                SurveyAnswer(type = "single_choice", value = JsonObject(mapOf("value" to JsonPrimitive(it))))
            } ?: return
        }
        QuestionType.MULTIPLE_CHOICE -> {
            SurveyAnswer(type = "multiple_choice", value = JsonObject(mapOf("values" to JsonArray(selectedOptions.map { JsonPrimitive(it) }))))
        }
        QuestionType.RATING, QuestionType.SCALE, QuestionType.NPS -> {
            SurveyAnswer(type = "rating", value = JsonObject(mapOf("value" to JsonPrimitive(ratingValue))))
        }
        QuestionType.TEXT_SHORT, QuestionType.TEXT_LONG -> {
            SurveyAnswer(type = "text", value = JsonObject(mapOf("value" to JsonPrimitive(textAnswer))))
        }
        QuestionType.RANKING -> {
            SurveyAnswer(type = "ranking", value = JsonObject(mapOf("order" to JsonArray(rankingOrder.map { JsonPrimitive(it) }))))
        }
        null -> return
    }

    val result = client.submitAnswer(survey.id, question.id, answer)
    result.onSuccess { response ->
        onSuccess(response.currentQuestionIndex, response.answers)
    }
}

private suspend fun skipQuestion(
    client: BLSurveyClient,
    survey: ActiveSurvey,
    questionId: String,
    onSuccess: (Int) -> Unit
) {
    val answer = SurveyAnswer(type = "skipped", value = JsonObject(emptyMap()))
    val result = client.submitAnswer(survey.id, questionId, answer)
    result.onSuccess { response ->
        onSuccess(response.currentQuestionIndex)
    }
}

private suspend fun completeSurvey(
    client: BLSurveyClient,
    surveyId: String,
    onComplete: (Boolean, Boolean) -> Unit
) {
    val result = client.completeSurvey(surveyId)
    result.onSuccess { completion ->
        onComplete(completion.success, completion.incentiveClaimed)
    }
}

private fun resetQuestionState(
    onSelectedOption: (String?) -> Unit,
    onSelectedOptions: (Set<String>) -> Unit,
    onRating: (Int) -> Unit,
    onText: (String) -> Unit,
    onRanking: (List<String>) -> Unit
) {
    onSelectedOption(null)
    onSelectedOptions(emptySet())
    onRating(0)
    onText("")
    onRanking(emptyList())
}

@Composable
private fun QuestionDialog(
    survey: ActiveSurvey,
    question: Question,
    questionIndex: Int,
    totalQuestions: Int,
    selectedOption: String?,
    selectedOptions: Set<String>,
    ratingValue: Int,
    textAnswer: String,
    rankingOrder: List<String>,
    onSelectedOptionChange: (String?) -> Unit,
    onSelectedOptionsChange: (Set<String>) -> Unit,
    onRatingChange: (Int) -> Unit,
    onTextChange: (String) -> Unit,
    onRankingChange: (List<String>) -> Unit,
    onSubmit: () -> Unit,
    onSkip: () -> Unit,
    onDismiss: () -> Unit
) {
    Dialog(onDismissRequest = onDismiss) {
        Surface(
            modifier = Modifier
                .fillMaxWidth()
                .padding(16.dp),
            shape = RoundedCornerShape(16.dp),
            color = MaterialTheme.colorScheme.surface
        ) {
            Column(
                modifier = Modifier
                    .padding(24.dp)
                    .verticalScroll(rememberScrollState()),
                verticalArrangement = Arrangement.spacedBy(16.dp)
            ) {
                // Progress
                LinearProgressIndicator(
                    progress = { (questionIndex + 1) / totalQuestions.toFloat() },
                    modifier = Modifier.fillMaxWidth()
                )
                Text(
                    text = "Question ${questionIndex + 1} of $totalQuestions",
                    style = MaterialTheme.typography.labelSmall,
                    color = MaterialTheme.colorScheme.onSurfaceVariant,
                    modifier = Modifier.fillMaxWidth(),
                    textAlign = TextAlign.Center
                )

                // Question text
                Text(
                    text = question.text,
                    style = MaterialTheme.typography.titleMedium
                )
                question.description?.let {
                    Text(
                        text = it,
                        style = MaterialTheme.typography.bodyMedium,
                        color = MaterialTheme.colorScheme.onSurfaceVariant
                    )
                }
                if (question.required) {
                    Text(
                        text = "Required",
                        style = MaterialTheme.typography.labelSmall,
                        color = MaterialTheme.colorScheme.error
                    )
                }

                // Question input
                val qType = question.type.toQuestionType()
                when (qType) {
                    QuestionType.SINGLE_CHOICE, QuestionType.DROPDOWN -> {
                        SingleChoiceInput(
                            options = question.options ?: emptyList(),
                            selected = selectedOption,
                            onSelect = onSelectedOptionChange
                        )
                    }
                    QuestionType.MULTIPLE_CHOICE -> {
                        MultipleChoiceInput(
                            options = question.options ?: emptyList(),
                            selected = selectedOptions,
                            onSelect = onSelectedOptionsChange
                        )
                    }
                    QuestionType.RATING, QuestionType.SCALE, QuestionType.NPS -> {
                        RatingInput(
                            minValue = question.minValue ?: if (qType == QuestionType.NPS) 0 else 1,
                            maxValue = question.maxValue ?: if (qType == QuestionType.NPS) 10 else 5,
                            rating = ratingValue,
                            onRatingChange = onRatingChange
                        )
                    }
                    QuestionType.TEXT_SHORT, QuestionType.TEXT_LONG -> {
                        TextAnswerInput(
                            text = textAnswer,
                            isLong = qType == QuestionType.TEXT_LONG,
                            maxLength = question.maxLength,
                            onTextChange = onTextChange
                        )
                    }
                    QuestionType.RANKING -> {
                        RankingInput(
                            options = question.options ?: emptyList(),
                            order = rankingOrder,
                            onOrderChange = onRankingChange
                        )
                    }
                    null -> { /* unknown type */ }
                }

                // Buttons
                Row(
                    modifier = Modifier.fillMaxWidth(),
                    horizontalArrangement = Arrangement.SpaceBetween,
                    verticalAlignment = Alignment.CenterVertically
                ) {
                    if (!question.required) {
                        TextButton(onClick = onSkip) {
                            Text("Skip")
                        }
                    } else {
                        Spacer(modifier = Modifier.width(1.dp))
                    }

                    val canSubmit = when (qType) {
                        QuestionType.SINGLE_CHOICE, QuestionType.DROPDOWN -> selectedOption != null
                        QuestionType.MULTIPLE_CHOICE -> selectedOptions.isNotEmpty()
                        QuestionType.RATING, QuestionType.SCALE, QuestionType.NPS -> ratingValue > 0
                        QuestionType.TEXT_SHORT, QuestionType.TEXT_LONG -> textAnswer.isNotBlank()
                        QuestionType.RANKING -> rankingOrder.size == (question.options?.size ?: 0)
                        null -> false
                    }

                    val isLast = questionIndex == totalQuestions - 1
                    Button(
                        onClick = onSubmit,
                        enabled = canSubmit
                    ) {
                        Text(if (isLast) "Complete" else "Next")
                    }
                }
            }
        }
    }
}

@Composable
private fun SingleChoiceInput(
    options: List<QuestionOption>,
    selected: String?,
    onSelect: (String?) -> Unit
) {
    Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
        options.forEach { option ->
            Row(
                modifier = Modifier
                    .fillMaxWidth()
                    .clip(RoundedCornerShape(8.dp))
                    .background(
                        if (selected == option.id) MaterialTheme.colorScheme.primaryContainer
                        else MaterialTheme.colorScheme.surfaceVariant
                    )
                    .clickable { onSelect(option.id) }
                    .padding(12.dp),
                horizontalArrangement = Arrangement.spacedBy(8.dp),
                verticalAlignment = Alignment.CenterVertically
            ) {
                Text(text = option.emoji ?: "")
                Text(
                    text = option.text,
                    modifier = Modifier.weight(1f)
                )
                Icon(
                    imageVector = if (selected == option.id) Icons.Default.CheckCircle else Icons.Default.RadioButtonUnchecked,
                    contentDescription = null,
                    tint = if (selected == option.id) MaterialTheme.colorScheme.primary
                    else MaterialTheme.colorScheme.onSurfaceVariant
                )
            }
        }
    }
}

@Composable
private fun MultipleChoiceInput(
    options: List<QuestionOption>,
    selected: Set<String>,
    onSelect: (Set<String>) -> Unit
) {
    Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
        options.forEach { option ->
            val isSelected = selected.contains(option.id)
            Row(
                modifier = Modifier
                    .fillMaxWidth()
                    .clip(RoundedCornerShape(8.dp))
                    .background(
                        if (isSelected) MaterialTheme.colorScheme.primaryContainer
                        else MaterialTheme.colorScheme.surfaceVariant
                    )
                    .clickable {
                        val newSet = if (isSelected) selected - option.id else selected + option.id
                        onSelect(newSet)
                    }
                    .padding(12.dp),
                horizontalArrangement = Arrangement.spacedBy(8.dp),
                verticalAlignment = Alignment.CenterVertically
            ) {
                Text(text = option.emoji ?: "")
                Text(
                    text = option.text,
                    modifier = Modifier.weight(1f)
                )
                Checkbox(
                    checked = isSelected,
                    onCheckedChange = {
                        val newSet = if (it) selected + option.id else selected - option.id
                        onSelect(newSet)
                    }
                )
            }
        }
    }
}

@Composable
private fun RatingInput(
    minValue: Int,
    maxValue: Int,
    rating: Int,
    onRatingChange: (Int) -> Unit
) {
    Column(
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.spacedBy(8.dp)
    ) {
        Row(
            horizontalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            (minValue..maxValue).forEach { value ->
                Button(
                    onClick = { onRatingChange(value) },
                    shape = CircleShape,
                    colors = ButtonDefaults.buttonColors(
                        containerColor = if (rating == value) MaterialTheme.colorScheme.primary
                        else MaterialTheme.colorScheme.surfaceVariant,
                        contentColor = if (rating == value) MaterialTheme.colorScheme.onPrimary
                        else MaterialTheme.colorScheme.onSurfaceVariant
                    ),
                    modifier = Modifier.size(44.dp)
                ) {
                    Text("$value")
                }
            }
        }
        Row(
            modifier = Modifier.fillMaxWidth(),
            horizontalArrangement = Arrangement.SpaceBetween
        ) {
            Text(
                text = if (maxValue == 10) "Not likely" else "Low",
                style = MaterialTheme.typography.labelSmall,
                color = MaterialTheme.colorScheme.onSurfaceVariant
            )
            Text(
                text = if (maxValue == 10) "Very likely" else "High",
                style = MaterialTheme.typography.labelSmall,
                color = MaterialTheme.colorScheme.onSurfaceVariant
            )
        }
    }
}

@Composable
private fun TextAnswerInput(
    text: String,
    isLong: Boolean,
    maxLength: Int?,
    onTextChange: (String) -> Unit
) {
    Column {
        if (isLong) {
            OutlinedTextField(
                value = text,
                onValueChange = { newText ->
                    maxLength?.let {
                        if (newText.length <= it) onTextChange(newText)
                    } ?: onTextChange(newText)
                },
                modifier = Modifier
                    .fillMaxWidth()
                    .heightIn(min = 120.dp),
                maxLines = 6,
                keyboardOptions = KeyboardOptions.Default
            )
        } else {
            OutlinedTextField(
                value = text,
                onValueChange = { newText ->
                    maxLength?.let {
                        if (newText.length <= it) onTextChange(newText)
                    } ?: onTextChange(newText)
                },
                modifier = Modifier.fillMaxWidth(),
                singleLine = true,
                keyboardOptions = KeyboardOptions.Default
            )
        }
        maxLength?.let {
            Text(
                text = "${text.length}/$it",
                style = MaterialTheme.typography.labelSmall,
                color = if (text.length > it) MaterialTheme.colorScheme.error
                else MaterialTheme.colorScheme.onSurfaceVariant,
                modifier = Modifier.align(Alignment.End)
            )
        }
    }
}

@Composable
private fun RankingInput(
    options: List<QuestionOption>,
    order: List<String>,
    onOrderChange: (List<String>) -> Unit
) {
    Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
        options.forEach { option ->
            val rank = order.indexOf(option.id).let { if (it >= 0) it + 1 else null }
            val isRanked = rank != null

            Row(
                modifier = Modifier
                    .fillMaxWidth()
                    .clip(RoundedCornerShape(8.dp))
                    .background(MaterialTheme.colorScheme.surfaceVariant)
                    .padding(12.dp),
                horizontalArrangement = Arrangement.spacedBy(8.dp),
                verticalAlignment = Alignment.CenterVertically
            ) {
                // Rank badge
                Box(
                    modifier = Modifier
                        .size(28.dp)
                        .clip(CircleShape)
                        .background(
                            if (isRanked) MaterialTheme.colorScheme.primary
                            else MaterialTheme.colorScheme.surface
                        ),
                    contentAlignment = Alignment.Center
                ) {
                    Text(
                        text = rank?.toString() ?: "-",
                        style = MaterialTheme.typography.labelSmall,
                        color = if (isRanked) MaterialTheme.colorScheme.onPrimary
                        else MaterialTheme.colorScheme.onSurfaceVariant
                    )
                }

                Text(
                    text = option.text,
                    modifier = Modifier.weight(1f)
                )

                // Controls
                Row(horizontalArrangement = Arrangement.spacedBy(4.dp)) {
                    IconButton(
                        onClick = {
                            val idx = order.indexOf(option.id)
                            if (idx > 0) {
                                val newOrder = order.toMutableList()
                                newOrder.swap(idx, idx - 1)
                                onOrderChange(newOrder)
                            }
                        },
                        enabled = isRanked && rank!! > 1,
                        modifier = Modifier.size(32.dp)
                    ) {
                        Icon(Icons.Default.ArrowUpward, null, modifier = Modifier.size(16.dp))
                    }

                    IconButton(
                        onClick = {
                            val idx = order.indexOf(option.id)
                            if (idx < order.size - 1) {
                                val newOrder = order.toMutableList()
                                newOrder.swap(idx, idx + 1)
                                onOrderChange(newOrder)
                            }
                        },
                        enabled = isRanked && rank!! < order.size,
                        modifier = Modifier.size(32.dp)
                    ) {
                        Icon(Icons.Default.ArrowDownward, null, modifier = Modifier.size(16.dp))
                    }

                    IconButton(
                        onClick = {
                            if (!isRanked) {
                                onOrderChange(order + option.id)
                            }
                        },
                        enabled = !isRanked,
                        modifier = Modifier.size(32.dp)
                    ) {
                        Icon(Icons.Default.Check, null, modifier = Modifier.size(16.dp))
                    }
                }
            }
        }
    }
}

private fun String.toQuestionType(): QuestionType? =
    QuestionType.entries.firstOrNull { it.name.equals(this, ignoreCase = true) }

private fun MutableList<String>.swap(i: Int, j: Int) {
    val temp = this[i]
    this[i] = this[j]
    this[j] = temp
}

@Composable
private fun CompletionDialog(
    survey: ActiveSurvey?,
    onDismiss: () -> Unit
) {
    Dialog(onDismissRequest = onDismiss) {
        Surface(
            modifier = Modifier
                .fillMaxWidth()
                .padding(16.dp),
            shape = RoundedCornerShape(16.dp),
            color = MaterialTheme.colorScheme.surface
        ) {
            Column(
                modifier = Modifier.padding(24.dp),
                horizontalAlignment = Alignment.CenterHorizontally,
                verticalArrangement = Arrangement.spacedBy(16.dp)
            ) {
                Icon(
                    imageVector = Icons.Default.CheckCircle,
                    contentDescription = null,
                    modifier = Modifier.size(64.dp),
                    tint = Color(0xFF4CAF50)
                )

                Text(
                    text = "Thank You!",
                    style = MaterialTheme.typography.headlineSmall
                )

                Text(
                    text = "Your feedback helps us improve.",
                    style = MaterialTheme.typography.bodyMedium,
                    color = MaterialTheme.colorScheme.onSurfaceVariant,
                    textAlign = TextAlign.Center
                )

                survey?.incentive?.let { incentive: SurveyIncentive ->
                    Card(
                        colors = CardDefaults.cardColors(
                            containerColor = Color(0xFFE8F5E9)
                        )
                    ) {
                        Row(
                            modifier = Modifier.padding(16.dp),
                            horizontalArrangement = Arrangement.spacedBy(8.dp),
                            verticalAlignment = Alignment.CenterVertically
                        ) {
                            Icon(
                                imageVector = Icons.Default.Check,
                                contentDescription = null,
                                tint = Color(0xFF4CAF50)
                            )
                            Text(
                                text = "You've earned ${incentive.amount} ${if (incentive.type == "pro_days") "Pro Days" else "Credits"}!",
                                style = MaterialTheme.typography.titleSmall,
                                color = Color(0xFF2E7D32)
                            )
                        }
                    }
                }

                Button(
                    onClick = onDismiss,
                    modifier = Modifier.fillMaxWidth()
                ) {
                    Text("Close")
                }
            }
        }
    }
}
