package com.aryan.reader.desktop

import androidx.compose.foundation.Canvas
import androidx.compose.foundation.Image
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.ColumnScope
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Switch
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.BlendMode
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.ColorMatrix
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.ImageShader
import androidx.compose.ui.graphics.ShaderBrush
import androidx.compose.ui.graphics.TileMode
import androidx.compose.ui.graphics.isSpecified
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import com.aryan.reader.shared.BuiltInPdfReaderThemes
import com.aryan.reader.shared.PdfDisplayMode
import com.aryan.reader.shared.ReaderTheme
import com.aryan.reader.shared.reader.ReaderSettings

internal enum class DesktopPdfInspectorTab(val title: String) {
    VIEW("View"),
    MARKUP("Markup"),
    ASSIST("Assist")
}

internal data class DesktopPdfThemeStyle(
    val theme: ReaderTheme,
    val viewerBackgroundColor: Color,
    val pageBackgroundColor: Color,
    val colorFilter: ColorFilter?,
    val textureBitmap: ImageBitmap?,
    val textureAlpha: Float,
    val textureBlendMode: BlendMode
)

@Composable
internal fun DesktopPdfThemedPageImage(
    bitmap: ImageBitmap,
    contentDescription: String,
    themeStyle: DesktopPdfThemeStyle,
    modifier: Modifier = Modifier
) {
    Box(modifier = modifier.background(themeStyle.pageBackgroundColor)) {
        Image(
            bitmap = bitmap,
            contentDescription = contentDescription,
            colorFilter = themeStyle.colorFilter,
            modifier = Modifier.fillMaxSize()
        )
        val textureBitmap = themeStyle.textureBitmap
        if (textureBitmap != null && themeStyle.textureAlpha > 0f) {
            Canvas(modifier = Modifier.fillMaxSize()) {
                drawRect(
                    brush = ShaderBrush(ImageShader(textureBitmap, TileMode.Repeated, TileMode.Repeated)),
                    size = size,
                    blendMode = themeStyle.textureBlendMode,
                    alpha = themeStyle.textureAlpha
                )
            }
        }
    }
}

internal fun ReaderSettings?.toDesktopPdfReaderSettings(): ReaderSettings {
    val defaults = ReaderSettings(themeId = "no_theme")
    val settings = this ?: defaults
    val themeId = settings.themeId
    val hasPdfTheme = BuiltInPdfReaderThemes.any { it.id == themeId }
    val hasCustomColors = settings.backgroundColorArgb != null && settings.textColorArgb != null
    return settings.copy(
        themeId = when {
            themeId == null -> "no_theme"
            hasPdfTheme || hasCustomColors -> themeId
            else -> "no_theme"
        }
    )
}

internal fun ReaderSettings.toDesktopPdfThemeStyle(displayMode: PdfDisplayMode): DesktopPdfThemeStyle {
    val theme = toDesktopPdfTheme()
    val pageBackground = desktopPdfPageBackgroundColor(theme, displayMode)
    val isDarkTexture = theme.isDark || theme.id == "reverse"
    return DesktopPdfThemeStyle(
        theme = theme,
        viewerBackgroundColor = pageBackground,
        pageBackgroundColor = pageBackground,
        colorFilter = theme.toDesktopPdfColorFilter(),
        textureBitmap = DesktopReaderTextures.imageBitmapFor(textureId),
        textureAlpha = if (textureId == null) 0f else textureAlpha.coerceIn(0f, 1f),
        textureBlendMode = if (isDarkTexture) BlendMode.Screen else BlendMode.Multiply
    )
}

private fun ReaderSettings.toDesktopPdfTheme(): ReaderTheme {
    BuiltInPdfReaderThemes.firstOrNull { it.id == themeId }?.let { return it }
    val background = backgroundColorArgb?.toComposeColor()
    val text = textColorArgb?.toComposeColor()
    return if (background != null && text != null) {
        ReaderTheme(
            id = themeId ?: "desktop_pdf_custom",
            name = "Custom",
            backgroundColor = background,
            textColor = text,
            isDark = darkMode,
            textureId = textureId,
            isCustom = true
        )
    } else {
        BuiltInPdfReaderThemes.first()
    }
}

private fun ReaderTheme.toDesktopPdfColorFilter(): ColorFilter? {
    return when (id) {
        "no_theme", "system" -> null
        "reverse" -> {
            val colorMatrix = floatArrayOf(
                -1f, 0f, 0f, 0f, 255f,
                0f, -1f, 0f, 0f, 255f,
                0f, 0f, -1f, 0f, 255f,
                0f, 0f, 0f, 1f, 0f
            )
            ColorFilter.colorMatrix(ColorMatrix(colorMatrix))
        }
        else -> {
            if (!backgroundColor.isSpecified || !textColor.isSpecified) return null
            val bgR = backgroundColor.red * 255f
            val bgG = backgroundColor.green * 255f
            val bgB = backgroundColor.blue * 255f
            val fgR = textColor.red * 255f
            val fgG = textColor.green * 255f
            val fgB = textColor.blue * 255f
            val dr = (bgR - fgR) / 255f
            val dg = (bgG - fgG) / 255f
            val db = (bgB - fgB) / 255f
            val lumR = 0.2126f
            val lumG = 0.7152f
            val lumB = 0.0722f
            val colorMatrix = floatArrayOf(
                dr * lumR, dr * lumG, dr * lumB, 0f, fgR,
                dg * lumR, dg * lumG, dg * lumB, 0f, fgG,
                db * lumR, db * lumG, db * lumB, 0f, fgB,
                0f, 0f, 0f, 1f, 0f
            )
            ColorFilter.colorMatrix(ColorMatrix(colorMatrix))
        }
    }
}

@Composable
internal fun DesktopPdfInspectorSection(
    title: String,
    content: @Composable ColumnScope.() -> Unit
) {
    Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
        Text(title, style = MaterialTheme.typography.titleSmall, fontWeight = FontWeight.SemiBold)
        content()
    }
}

@Composable
internal fun DesktopPdfVisualOptionSwitch(
    title: String,
    description: String,
    checked: Boolean,
    onCheckedChange: (Boolean) -> Unit
) {
    Row(
        modifier = Modifier.fillMaxWidth(),
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.spacedBy(10.dp)
    ) {
        Column(modifier = Modifier.weight(1f), verticalArrangement = Arrangement.spacedBy(2.dp)) {
            Text(title, style = MaterialTheme.typography.bodyMedium, fontWeight = FontWeight.Medium)
            Text(
                description,
                style = MaterialTheme.typography.bodySmall,
                color = MaterialTheme.colorScheme.onSurfaceVariant
            )
        }
        Switch(checked = checked, onCheckedChange = onCheckedChange)
    }
}

private fun Long.toComposeColor(): Color {
    return Color(this and 0xFFFFFFFFL)
}
