@file:Suppress("HardCodedStringLiteral")

package eu.gaudian.translator.view.settings

import android.content.Intent
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutVertically
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.SecondaryTabRow
import androidx.compose.material3.Switch
import androidx.compose.material3.Tab
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
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.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.NavController
import androidx.navigation.compose.rememberNavController
import eu.gaudian.translator.R
import eu.gaudian.translator.model.communication.ApiLogEntry
import eu.gaudian.translator.ui.theme.semanticColors
import eu.gaudian.translator.utils.Log
import eu.gaudian.translator.utils.findActivity
import eu.gaudian.translator.view.composable.AppDialog
import eu.gaudian.translator.view.composable.AppIcons
import eu.gaudian.translator.view.composable.AppScaffold
import eu.gaudian.translator.view.composable.AppTopAppBar
import eu.gaudian.translator.viewmodel.SettingsViewModel
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale

@Composable
fun LogsScreen(navController: NavController) {
    val activity = LocalContext.current.findActivity()
    val settingsViewModel: SettingsViewModel = hiltViewModel(viewModelStoreOwner = activity)
    val logsState by settingsViewModel.apiLogs.collectAsStateWithLifecycle(initialValue = emptyList())
    var onlyErrors by remember { mutableStateOf(false) }
    var showStatusCodesDialog by remember { mutableStateOf(false) }
    val listState = rememberLazyListState()

    val displayedLogs by remember(logsState, onlyErrors) {
        derivedStateOf {
            val filtered = if (onlyErrors) {
                logsState.filter { it.isError() }
            } else {
                logsState
            }
            filtered.asReversed() // Show most recent first
        }
    }

    if (showStatusCodesDialog) {
        @Suppress("AssignedValueIsNeverRead")
        StatusCodesDialog(onDismiss = { showStatusCodesDialog = false })
    }

    AppScaffold(
        topBar = {
            AppTopAppBar(
                title = stringResource(R.string.label_logs),
                onNavigateBack = { navController.popBackStack() },
                actions = {
                    TextButton(onClick = {
                        settingsViewModel.clearApiLogs()
                    }) {
                        Text(stringResource(R.string.label_clear))
                    }
                }
            )
        }
    ) { paddingValues ->
        Column(
            modifier = Modifier
                .fillMaxSize()
                .padding(paddingValues)
        ) {
            // ## A more compact and cleaner header for filters and actions
            LogScreenHeader(
                onlyErrors = onlyErrors,
                onFilterChange = { onlyErrors = it },
                onInfoClick = {
                    @Suppress("AssignedValueIsNeverRead")
                    showStatusCodesDialog = true
                }
            )

            if (logsState.isEmpty()) {
                Box(
                    modifier = Modifier.fillMaxSize(),
                    contentAlignment = Alignment.Center
                ) {
                    Text(
                        text = stringResource(R.string.logs_empty),
                        style = MaterialTheme.typography.bodyLarge,
                        color = MaterialTheme.colorScheme.onSurfaceVariant
                    )
                }
            } else {
                LazyColumn(
                    state = listState,
                    modifier = Modifier.fillMaxSize(),
                    verticalArrangement = Arrangement.spacedBy(8.dp),
                    contentPadding = androidx.compose.foundation.layout.PaddingValues(horizontal = 16.dp, vertical = 8.dp)
                ) {
                    items(items = displayedLogs, key = { it.id }) { entry ->
                        LogListItem(entry = entry)
                    }
                }
            }
        }
    }
}

@Composable
private fun LogScreenHeader(
    onlyErrors: Boolean,
    onFilterChange: (Boolean) -> Unit,
    onInfoClick: () -> Unit
) {
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .padding(horizontal = 16.dp, vertical = 8.dp),
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.spacedBy(8.dp)
    ) {
        Text(
            text = stringResource(R.string.only_show_errors),
            style = MaterialTheme.typography.bodyMedium,
            modifier = Modifier.weight(1f)
        )
        Switch(checked = onlyErrors, onCheckedChange = onFilterChange)
        IconButton(onClick = onInfoClick) {
            Icon(
                imageVector = AppIcons.Info,
                contentDescription = stringResource(R.string.title_http_status_codes)
            )
        }
    }
    HorizontalDivider(modifier = Modifier.padding(bottom = 4.dp))
}


@Suppress("HardCodedStringLiteral")
@Composable
private fun LogListItem(entry: ApiLogEntry) {
    var expanded by remember { mutableStateOf(false) }
    val timeFormat = remember { SimpleDateFormat("HH:mm:ss", Locale.getDefault()) }

    Card(
        modifier = Modifier.fillMaxWidth(),
        onClick = {
            expanded = !expanded
        },
        elevation = CardDefaults.cardElevation(defaultElevation = if (expanded) 4.dp else 2.dp)
    ) {
        Column(
            modifier = Modifier.padding(horizontal = 16.dp, vertical = 12.dp)
        ) {
            // ## This is the collapsed, scannable view
            Row(
                verticalAlignment = Alignment.CenterVertically,
                horizontalArrangement = Arrangement.spacedBy(12.dp)
            ) {
                StatusIndicator(entry = entry)
                Column(modifier = Modifier.weight(1f)) {
                    Text(
                        text = "${entry.method} ${entry.endpoint}",
                        style = MaterialTheme.typography.bodyLarge,
                        fontWeight = FontWeight.Bold
                    )
                    Text(
                        text = entry.providerKey,
                        style = MaterialTheme.typography.bodySmall,
                        color = MaterialTheme.colorScheme.onSurfaceVariant
                    )
                }
                Text(
                    text = timeFormat.format(Date(entry.timestamp)),
                    style = MaterialTheme.typography.bodyMedium,
                    color = MaterialTheme.colorScheme.onSurfaceVariant
                )
            }

            // ## This is the expanded, detailed view
            AnimatedVisibility(
                visible = expanded,
                enter = slideInVertically(initialOffsetY = { -it / 2 }) + fadeIn(animationSpec = tween(300)),
                exit = slideOutVertically(targetOffsetY = { -it / 2 }) + fadeOut(animationSpec = tween(300))
            ) {
                LogDetails(entry = entry)
            }
        }
    }
}

@Composable
private fun StatusIndicator(entry: ApiLogEntry) {
    val isHttpSuccess = entry.responseCode != null && entry.responseCode in 200..299
    val isParseOk = entry.parseErrorMessage.isNullOrBlank() && entry.errorMessage.isNullOrBlank()
    val color = when {
        isHttpSuccess && isParseOk -> MaterialTheme.semanticColors.success
        entry.responseCode != null && entry.responseCode in 400..499 -> Color(0xFFF57C00) // Orange 700
        else -> MaterialTheme.colorScheme.error // Red for 5xx or network errors
    }
    Box(
        modifier = Modifier
            .size(12.dp)
            .clip(CircleShape)
            .background(color)
    )
}

@Suppress("HardCodedStringLiteral")
@Composable
private fun LogDetails(entry: ApiLogEntry) {
    Log.d("LogListItem", "LogDetails: $entry")

    val fullDateFormat = remember { SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()) }
    var tabIndex by remember { mutableIntStateOf(0) }
    val tabs = listOf(stringResource(R.string.logs_request_json), stringResource(R.string.logs_response_json))

    Column {
        Spacer(Modifier.height(16.dp))
        HorizontalDivider()
        Spacer(Modifier.height(16.dp))

        // ## Detailed meta-information
        DetailRow(label = stringResource(R.string.logs_time), value = fullDateFormat.format(Date(entry.timestamp)))
        DetailRow(label = stringResource(R.string.label_status), value = "${entry.responseCode ?: stringResource(R.string.na)} ${entry.responseMessage ?: ""}".trim())
        entry.model?.let { DetailRow(label = stringResource(R.string.model), value = it) }
        entry.durationMs?.let { DetailRow(label = stringResource(R.string.duration), value = "$it ${stringResource(R.string.ms)}") }
        entry.exceptionType?.let { DetailRow(label = stringResource(R.string.exception), value = it, valueColor = MaterialTheme.colorScheme.error) }
        entry.isTimeout?.let { if (it) DetailRow(label = stringResource(R.string.timeout), value = stringResource(R.string.label_yes), valueColor = MaterialTheme.colorScheme.error) }
        entry.errorMessage?.let {
            DetailRow(label = stringResource(R.string.cd_error), value = it, valueColor = MaterialTheme.colorScheme.error)
        }
        entry.parseErrorMessage?.let {
            DetailRow(label = stringResource(R.string.parse_error), value = it, valueColor = MaterialTheme.colorScheme.error)
        }

        Spacer(Modifier.height(16.dp))

        SecondaryTabRow(selectedTabIndex = tabIndex, containerColor = Color.Transparent) {
            tabs.forEachIndexed { index, title ->
                Tab(
                    text = { Text(title) },
                    selected = tabIndex == index,
                    onClick = { tabIndex = index }
                )
            }
        }
        Card(
            modifier = Modifier
                .fillMaxWidth()
                .padding(top = 8.dp),
            colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surfaceVariant)
        ) {
            Text(
                text = when (tabIndex) {
                    0 -> entry.requestJson ?: stringResource(R.string.not_available)
                    else -> entry.responseJson ?: stringResource(R.string.not_available)
                },
                modifier = Modifier.padding(12.dp),
                fontFamily = FontFamily.Monospace,
                fontSize = 12.sp
            )
        }

        Spacer(Modifier.height(8.dp))
        ShareLogRow(entry = entry)
    }
}

@Composable
private fun DetailRow(label: String, value: String, valueColor: Color = Color.Unspecified) {
    Row(modifier = Modifier.fillMaxWidth()) {
        Text(
            text = "$label:",
            style = MaterialTheme.typography.bodyMedium,
            fontWeight = FontWeight.SemiBold,
            modifier = Modifier.weight(0.3f)
        )
        Text(
            text = value,
            style = MaterialTheme.typography.bodyMedium,
            color = valueColor,
            modifier = Modifier.weight(0.7f)
        )
    }
    Spacer(Modifier.height(4.dp))
}

@Composable
private fun StatusCodesDialog(onDismiss: () -> Unit) {
    AppDialog(
        onDismissRequest = onDismiss,
        title = { Text(stringResource(R.string.title_http_status_codes)) },
        content = { StatusCodeInfo() },
    )
}

@Composable
private fun ShareLogRow(entry: ApiLogEntry) {
    Row(
        modifier = Modifier.fillMaxWidth(),
        horizontalArrangement = Arrangement.End
    ) {
        val context = LocalContext.current
        val logsEmail = stringResource(R.string.logs_email_subject)
        val logsLabelId = stringResource(R.string.logs_label_id)
        val logsLabelTimestamp = stringResource(R.string.logs_label_timestamp)
        val logsLabelProvider = stringResource(R.string.logs_label_provider)
        val logsLabelEndpoint = stringResource(R.string.logs_label_endpoint)
        val logsLabelModel = stringResource(R.string.logs_label_model)
        val logsLabelStatus = stringResource(R.string.logs_label_status)
        val logsLabelDuration = stringResource(R.string.logs_label_duration)
        val logsLabelException = stringResource(R.string.logs_label_exception)
        val logsLabelTimeoutYes = stringResource(R.string.logs_label_timeout_yes)
        val logsLabelParseError = stringResource(R.string.logs_label_parse_error)
        val logsLabelError = stringResource(R.string.logs_label_error)
        val logsRequestSection = stringResource(R.string.logs_request_section)
        val logsResponseSection = stringResource(R.string.logs_response_section)
        val ms = stringResource(R.string.ms)
        val notAvailable = stringResource(R.string.not_available)
        val emailLog = stringResource(R.string.email_log)
        val share = stringResource(R.string.share)
        
        TextButton(onClick = {
            val subject = (logsEmail + " " + entry.id)
            val body = buildString {
                @Suppress("HardCodedStringLiteral") val ts = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(Date(entry.timestamp))
                appendLine(logsLabelId.format(entry.id))
                appendLine(logsLabelTimestamp.format(ts))
                appendLine(logsLabelProvider.format(entry.providerKey))
                appendLine(logsLabelEndpoint.format(entry.method, entry.endpoint))
                appendLine(logsLabelModel.format(entry.model ?: "-"))
                appendLine(logsLabelStatus.format((entry.responseCode ?: "-").toString(), entry.responseMessage ?: ""))
                entry.durationMs?.let { appendLine(logsLabelDuration.format(it.toString(), ms)) }
                entry.exceptionType?.let { appendLine(logsLabelException.format(it)) }
                if (entry.isTimeout == true) appendLine(logsLabelTimeoutYes)
                if (!entry.parseErrorMessage.isNullOrBlank()) appendLine(logsLabelParseError.format(entry.parseErrorMessage))
                if (!entry.errorMessage.isNullOrBlank()) appendLine(logsLabelError.format(entry.errorMessage))
                appendLine("\n$logsRequestSection\n${entry.requestJson ?: notAvailable}")
                appendLine("\n$logsResponseSection\n${entry.responseJson ?: notAvailable}")
            }
            val intent = Intent(Intent.ACTION_SEND).apply {
                type = "message/rfc822"
                putExtra(Intent.EXTRA_EMAIL, arrayOf("play@gaudian.eu"))
                putExtra(Intent.EXTRA_SUBJECT, subject)
                putExtra(Intent.EXTRA_TEXT, body)
            }
            try {
                context.startActivity(Intent.createChooser(intent, emailLog))
            } catch (_: Exception) {
                // Fallback to plain text share if no email clients
                val fallbackIntent = Intent(Intent.ACTION_SEND).apply {
                    type = "text/plain"
                    putExtra(Intent.EXTRA_SUBJECT, subject)
                    putExtra(Intent.EXTRA_TEXT, body)
                }
                context.startActivity(Intent.createChooser(fallbackIntent, share))
            }
        }) {
            Text(emailLog)
        }
    }
}

// Helper extension function
private fun ApiLogEntry.isError(): Boolean {
    val isHttpError = responseCode != null && responseCode !in 200..299
    val hasErrorMessage = !errorMessage.isNullOrBlank()
    val hasParseError = !parseErrorMessage.isNullOrBlank()
    return isHttpError || hasErrorMessage || hasParseError
}

@Preview(showBackground = true)
@Composable
private fun LogsScreenPreview() {
    LogsScreen(navController = rememberNavController())
}

@Preview(showBackground = true)
@Composable
private fun LogListItemPreview() {
    val entry = ApiLogEntry(
        id = "123",
        timestamp = System.currentTimeMillis(),
        providerKey = "DeepL",
        endpoint = "/v2/translate",
        method = "POST",
        model = "deepl-pro",
        requestJson = """{"text": ["Hello, world!"], "target_lang": "DE"}""",
        responseCode = 200,
        responseMessage = "OK",
        responseJson = """{"translations": [{"detected_source_language": "EN", "text": "Hallo, Welt!"}]}""",
        errorMessage = null
    )
    Column(modifier = Modifier.padding(16.dp)) {
        LogListItem(entry = entry)
    }
}

@Preview(showBackground = true)
@Composable
private fun LogListItemErrorPreview() {
    val entry = ApiLogEntry(
        id = "456",
        timestamp = System.currentTimeMillis(),
        providerKey = "OpenAI",
        endpoint = "/v1/chat/completions",
        method = "POST",
        model = "gpt-4",
        requestJson = """{"model": "gpt-4", "messages": [{"role": "user", "content": "Say this is a test!"}]}""",
        responseCode = 401,
        responseMessage = "Unauthorized",
        responseJson = """{"error": {"message": "Incorrect API key provided.", "type": "invalid_request_error"}}""",
        errorMessage = "HTTP 401 Unauthorized"
    )
    Column(modifier = Modifier.padding(16.dp)) {
        LogListItem(entry = entry)
    }
}

@Composable
fun StatusCodeInfo() {
    val items = listOf(
        stringResource(R.string.text_200_ok) to stringResource(R.string.the_request_was_successful),
        stringResource(R.string.text_400_bad_request) to stringResource(R.string.the_server_could_not_understand_the_request),
        stringResource(R.string.text_401_unauthorized) to stringResource(R.string.text_authentication_is_required_and_has_failed),
        stringResource(R.string.text_403_forbidden) to stringResource(R.string.the_server_understood_the_request_but_is_refusing_to_authorize_it),
        stringResource(R.string.text_404_not_found) to stringResource(R.string.the_requested_resource_could_not_be_found),
        stringResource(R.string.text_429_too_many_requests) to stringResource(R.string.text_too_many_requests),
        stringResource(R.string.text_500_internal_server_error) to stringResource(R.string.text_an_unexpected_condition_was_encountered_on_the_server)
    )

    LazyColumn(
        modifier = Modifier
            .padding(8.dp)
            .heightIn(max = 500.dp)
    ) {
        items(items) { (code, description) ->
            Row(modifier = Modifier.padding(vertical = 4.dp)) {
                Text(
                    text = code,
                    style = MaterialTheme.typography.bodyMedium,
                    fontWeight = FontWeight.Bold,
                    modifier = Modifier.width(120.dp)
                )
                Text(
                    text = description,
                    style = MaterialTheme.typography.bodyMedium
                )
            }
        }
    }
}