package com.seven.ikar.kotlin.feature.update

import androidx.compose.foundation.border
import androidx.compose.foundation.verticalScroll
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.WindowInsetsSides
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeDrawing
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.material3.Button
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import com.seven.ikar.kotlin.core.update.AppUpdateInstallerEvent
import com.seven.ikar.kotlin.ui.IkarScreenSurface
import com.seven.ikar.kotlin.ui.IkarSimpleHeader
import com.seven.ikar.kotlin.ui.theme.TelegramBorder
import com.seven.ikar.kotlin.ui.theme.TelegramInkMuted
import java.text.DecimalFormat
import java.time.OffsetDateTime
import java.time.ZoneId
import java.time.format.DateTimeFormatter

@Composable
fun AppUpdateScreen(
    state: AppUpdateUiState,
    onBackClick: () -> Unit,
    onRefreshClick: () -> Unit,
    onInstallClick: () -> Unit,
    onGrantPermissionClick: () -> Unit
) {
    IkarScreenSurface(modifier = Modifier.fillMaxSize()) {
        Column(
            modifier = Modifier
                .fillMaxSize()
                .windowInsetsPadding(WindowInsets.safeDrawing.only(WindowInsetsSides.Top))
        ) {
            Column(
                modifier = Modifier.padding(start = 18.dp, top = 16.dp, end = 18.dp, bottom = 12.dp)
            ) {
                IkarSimpleHeader(
                    title = "Обновление приложения",
                    onBackClick = onBackClick
                )
            }

            Column(
                modifier = Modifier
                    .weight(1f)
                    .verticalScroll(rememberScrollState())
                    .padding(horizontal = 18.dp),
                verticalArrangement = Arrangement.spacedBy(12.dp)
            ) {
                UpdatePanel {
                    Text(
                        text = state.statusTitle,
                        style = MaterialTheme.typography.headlineMedium,
                        color = MaterialTheme.colorScheme.primary,
                        fontWeight = FontWeight.SemiBold
                    )
                    Spacer(modifier = Modifier.height(6.dp))
                    Text(
                        text = state.statusDetail,
                        style = MaterialTheme.typography.bodyMedium,
                        color = TelegramInkMuted
                    )
                }

                if (state.isChecking || state.isSubmitting) {
                    LinearProgressIndicator(modifier = Modifier.fillMaxWidth())
                }

                UpdatePanel {
                    Text(
                        text = "Текущая установка",
                        style = MaterialTheme.typography.titleLarge,
                        fontWeight = FontWeight.SemiBold
                    )
                    Spacer(modifier = Modifier.height(8.dp))
                    UpdateFieldRow(
                        title = "Версия Икар",
                        value = "${state.currentVersionName} (${state.currentVersionCode})"
                    )
                    UpdateFieldRow(
                        title = "Разрешение Android",
                        value = if (state.canRequestPackageInstalls) "Включено" else "Нужно включить"
                    )
                    state.latestManifest?.let { manifest ->
                        UpdateFieldRow(
                            title = "Последний релиз Argus",
                            value = "${manifest.release.version} (${manifest.release.androidVersionCode ?: "?"})"
                        )
                    }
                }

                UpdatePanel {
                    Text(
                        text = "Как работает установка",
                        style = MaterialTheme.typography.titleLarge,
                        fontWeight = FontWeight.SemiBold
                    )
                    Spacer(modifier = Modifier.height(6.dp))
                    Text(
                        text = "Икар скачивает APK из Argus, проверяет имя пакета и код версии, затем передаёт файл системному установщику Android. Переключатель в настройках Android только разрешает запуск установки, но не устанавливает обновление сам.",
                        style = MaterialTheme.typography.bodyMedium,
                        color = TelegramInkMuted
                    )
                }

                state.availableUpdate?.let { update ->
                    UpdatePanel {
                        Text(
                            text = "Доступное обновление",
                            style = MaterialTheme.typography.titleLarge,
                            fontWeight = FontWeight.SemiBold
                        )
                        Spacer(modifier = Modifier.height(8.dp))
                        UpdateFieldRow(
                            title = "Версия",
                            value = "${update.manifest.release.version} (${update.manifest.release.androidVersionCode ?: "?"})"
                        )
                        UpdateFieldRow(
                            title = "Размер APK",
                            value = formatBytes(update.manifest.release.packageSizeBytes)
                        )
                        UpdateFieldRow(
                            title = "Опубликовано",
                            value = formatPublishedAt(update.manifest.release.publishedAt)
                        )
                        update.manifest.release.notes?.takeIf { it.isNotBlank() }?.let { notes ->
                            Spacer(modifier = Modifier.height(8.dp))
                            Text(
                                text = "Что нового",
                                style = MaterialTheme.typography.titleMedium,
                                fontWeight = FontWeight.SemiBold
                            )
                            Text(
                                text = notes,
                                style = MaterialTheme.typography.bodyMedium,
                                color = TelegramInkMuted
                            )
                        }
                    }
                }

                state.lastInstallerEvent?.let { event ->
                    UpdatePanel {
                        Text(
                            text = "Последний статус установки",
                            style = MaterialTheme.typography.titleLarge,
                            fontWeight = FontWeight.SemiBold
                        )
                        Spacer(modifier = Modifier.height(8.dp))
                        UpdateFieldRow(title = "Состояние", value = humanInstallerState(event))
                        event.releaseVersion?.let { UpdateFieldRow(title = "Версия", value = it) }
                        event.versionCode?.let { UpdateFieldRow(title = "Код версии", value = it.toString()) }
                        event.detail?.let {
                            Spacer(modifier = Modifier.height(6.dp))
                            Text(
                                text = it,
                                style = MaterialTheme.typography.bodyMedium,
                                color = TelegramInkMuted
                            )
                        }
                        Spacer(modifier = Modifier.height(6.dp))
                        Text(
                            text = formatInstallerTime(event),
                            style = MaterialTheme.typography.bodySmall,
                            color = TelegramInkMuted
                        )
                    }
                }

                Spacer(modifier = Modifier.height(8.dp))
            }

            UpdateActionBar(
                state = state,
                onRefreshClick = onRefreshClick,
                onInstallClick = onInstallClick,
                onGrantPermissionClick = onGrantPermissionClick
            )
        }
    }
}

@Composable
private fun UpdateActionBar(
    state: AppUpdateUiState,
    onRefreshClick: () -> Unit,
    onInstallClick: () -> Unit,
    onGrantPermissionClick: () -> Unit
) {
    Surface(
        color = MaterialTheme.colorScheme.surface,
        shape = RectangleShape,
        shadowElevation = 8.dp
    ) {
        Column(
            modifier = Modifier
                .fillMaxWidth()
                .navigationBarsPadding()
                .padding(horizontal = 18.dp, vertical = 12.dp),
            verticalArrangement = Arrangement.spacedBy(10.dp)
        ) {
            when {
                state.availableUpdate != null && !state.canRequestPackageInstalls -> {
                    Button(
                        onClick = onGrantPermissionClick,
                        modifier = Modifier.fillMaxWidth(),
                        enabled = !state.isChecking && !state.isSubmitting
                    ) {
                        Text("Открыть разрешение Android")
                    }
                    OutlinedButton(
                        onClick = onRefreshClick,
                        modifier = Modifier.fillMaxWidth(),
                        enabled = !state.isChecking && !state.isSubmitting
                    ) {
                        Text("Проверить ещё раз")
                    }
                }

                state.availableUpdate != null -> {
                    Button(
                        onClick = onInstallClick,
                        modifier = Modifier.fillMaxWidth(),
                        enabled = !state.isChecking && !state.isSubmitting
                    ) {
                        if (state.isSubmitting) {
                            CircularProgressIndicator(modifier = Modifier.size(18.dp), strokeWidth = 2.dp)
                        } else {
                            Text("Скачать и установить")
                        }
                    }
                    OutlinedButton(
                        onClick = onRefreshClick,
                        modifier = Modifier.fillMaxWidth(),
                        enabled = !state.isChecking && !state.isSubmitting
                    ) {
                        Text("Проверить заново")
                    }
                }

                else -> {
                    Button(
                        onClick = onRefreshClick,
                        modifier = Modifier.fillMaxWidth(),
                        enabled = !state.isChecking && !state.isSubmitting
                    ) {
                        if (state.isChecking) {
                            CircularProgressIndicator(modifier = Modifier.size(18.dp), strokeWidth = 2.dp)
                        } else if (state.canRequestPackageInstalls) {
                            Text("Проверить обновление")
                        } else {
                            Text("Открыть разрешение установки APK")
                        }
                    }
                }
            }
        }
    }
}

@Composable
private fun UpdatePanel(
    modifier: Modifier = Modifier,
    padding: PaddingValues = PaddingValues(16.dp),
    content: @Composable ColumnScope.() -> Unit
) {
    Surface(
        modifier = modifier
            .fillMaxWidth()
            .border(1.dp, TelegramBorder, RectangleShape),
        shape = RectangleShape,
        color = MaterialTheme.colorScheme.surface,
        shadowElevation = 0.dp
    ) {
        Column(
            modifier = Modifier.padding(padding),
            content = content
        )
    }
}

@Composable
private fun UpdateFieldRow(
    title: String,
    value: String
) {
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .padding(vertical = 5.dp),
        horizontalArrangement = Arrangement.spacedBy(12.dp),
        verticalAlignment = Alignment.CenterVertically
    ) {
        Text(
            text = title,
            modifier = Modifier.weight(1f),
            style = MaterialTheme.typography.bodyMedium,
            color = TelegramInkMuted
        )
        Text(
            text = value,
            style = MaterialTheme.typography.titleMedium,
            maxLines = 1,
            overflow = TextOverflow.Ellipsis
        )
    }
}

private fun humanInstallerState(event: AppUpdateInstallerEvent): String =
    when (event.state) {
        "submitted" -> "Запрос передан в Android"
        "approval_required" -> "Нужно подтверждение пользователя"
        "installed" -> "Обновление установлено"
        "failed" -> "Установка завершилась ошибкой"
        else -> event.state
    }

private fun formatPublishedAt(value: String): String =
    runCatching {
        OffsetDateTime.parse(value)
            .atZoneSameInstant(ZoneId.systemDefault())
            .format(DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm"))
    }.getOrElse { value }

private fun formatInstallerTime(event: AppUpdateInstallerEvent): String =
    runCatching {
        java.time.Instant.ofEpochMilli(event.updatedAtEpochMillis)
            .atZone(ZoneId.systemDefault())
            .format(DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss"))
    }.getOrElse { event.updatedAtEpochMillis.toString() }

private fun formatBytes(value: Long): String {
    if (value <= 0) {
        return "0 Б"
    }

    val units = listOf("Б", "КБ", "МБ", "ГБ")
    var size = value.toDouble()
    var unitIndex = 0
    while (size >= 1024 && unitIndex < units.lastIndex) {
        size /= 1024
        unitIndex++
    }
    return "${DecimalFormat("#,##0.#").format(size).replace(',', '.')} ${units[unitIndex]}"
}
