package com.anypreta.bountyboard.ui.auth

import android.annotation.SuppressLint
import android.net.Uri
import android.webkit.CookieManager
import android.webkit.WebResourceRequest
import android.webkit.WebView
import android.webkit.WebViewClient
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.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Close
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
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.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import androidx.lifecycle.viewmodel.compose.viewModel
import com.anypreta.bountyboard.di.LocalAppContainer
import com.anypreta.bountyboard.di.containerVMFactory
import com.anypreta.bountyboard.ui.components.DiamondBrand
import com.anypreta.bountyboard.ui.components.Hairline
import com.anypreta.bountyboard.ui.components.MessageBox
import com.anypreta.bountyboard.ui.theme.BB

/**
 * OIDC SSO via the server's browser redirect flow (GET /api/v1/auth/oidc/login →
 * IdP → /api/v1/auth/oidc/callback sets the session cookies → 302 home). We host
 * it in a WebView, detect the final redirect back to our own host, then import the
 * session cookies from the WebView's CookieManager into the app's OkHttp cookie jar
 * and establish the session via /auth/me.
 */
@SuppressLint("SetJavaScriptEnabled")
@Composable
fun OidcWebViewScreen(onDone: (Boolean) -> Unit) {
    val container = LocalAppContainer.current
    val vm: AuthViewModel = viewModel(factory = containerVMFactory(container) { AuthViewModel(it) })
    val p = BB.colors

    val baseUrl = container.baseUrl.value
    val host = remember(baseUrl) { Uri.parse(baseUrl).host ?: "" }
    val startUrl = baseUrl.trimEnd('/') + "/api/v1/auth/oidc/login"

    var progress by remember { mutableStateOf(true) }
    var handled by remember { mutableStateOf(false) }
    var failure by remember { mutableStateOf<String?>(null) }

    fun complete(success: Boolean, reason: String? = null) {
        if (handled) return
        handled = true
        if (success) {
            // Pull cookies the server set in the WebView into the OkHttp jar.
            CookieManager.getInstance().flush()
            val header = CookieManager.getInstance().getCookie(baseUrl)
            container.cookieJar.importCookieHeader(host, header)
            if (container.cookieJar.cookieValue(host, "bb_session") != null) {
                vm.completeOidc { ok ->
                    if (ok) onDone(true) else { handled = false; failure = "SSO sign-in could not be completed." }
                }
            } else {
                handled = false
                failure = "Single sign-on isn't configured on this server."
            }
        } else {
            failure = reason ?: "Single sign-on was cancelled or failed."
        }
    }

    Column(Modifier.fillMaxSize()) {
        Row(
            Modifier.fillMaxWidth().padding(horizontal = 12.dp, vertical = 8.dp),
            verticalAlignment = Alignment.CenterVertically,
            horizontalArrangement = Arrangement.SpaceBetween,
        ) {
            DiamondBrand("Single sign-on")
            IconButton(onClick = { onDone(false) }) {
                Icon(Icons.Outlined.Close, "Cancel", tint = p.text)
            }
        }
        Hairline()
        if (progress) {
            LinearProgressIndicator(Modifier.fillMaxWidth(), color = p.accent, trackColor = p.surface2)
        }
        failure?.let {
            Box(Modifier.padding(16.dp)) { MessageBox(it) }
        }

        AndroidView(
            modifier = Modifier.fillMaxSize(),
            factory = { ctx ->
                CookieManager.getInstance().setAcceptCookie(true)
                WebView(ctx).apply {
                    CookieManager.getInstance().setAcceptThirdPartyCookies(this, true)
                    settings.javaScriptEnabled = true
                    settings.domStorageEnabled = true
                    webViewClient = object : WebViewClient() {
                        override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean {
                            val url = request.url
                            // The final redirect lands back on our host, OUTSIDE the oidc endpoints.
                            if (url.host == host && !(url.path ?: "").startsWith("/api/v1/auth/oidc")) {
                                val full = url.toString()
                                val isError = full.contains("error", ignoreCase = true) ||
                                    (url.path ?: "").startsWith("/login")
                                complete(!isError, if (isError) "Single sign-on was rejected." else null)
                                return true
                            }
                            return false
                        }

                        override fun onPageStarted(view: WebView?, url: String?, favicon: android.graphics.Bitmap?) {
                            progress = true
                        }

                        override fun onPageFinished(view: WebView?, url: String?) {
                            progress = false
                        }
                    }
                    loadUrl(startUrl)
                }
            },
        )
    }
}
