package com.anypreta.bountyboard.ui.profile

import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.LocationOn
import androidx.compose.material.icons.outlined.Phone
import androidx.compose.material.icons.outlined.Link
import androidx.compose.material3.Icon
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.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.compose.viewModel
import com.anypreta.bountyboard.data.AppContainer
import com.anypreta.bountyboard.data.model.UserCard
import com.anypreta.bountyboard.data.net.CreateConversationBody
import com.anypreta.bountyboard.di.LocalAppContainer
import com.anypreta.bountyboard.di.containerVMFactory
import com.anypreta.bountyboard.ui.components.BBAvatar
import com.anypreta.bountyboard.ui.components.BBBadge
import com.anypreta.bountyboard.ui.components.BBButton
import com.anypreta.bountyboard.ui.components.BBButtonStyle
import com.anypreta.bountyboard.ui.components.BBCard
import com.anypreta.bountyboard.ui.components.Hairline
import com.anypreta.bountyboard.ui.components.ScreenState
import com.anypreta.bountyboard.ui.components.SectionLabel
import com.anypreta.bountyboard.ui.theme.BB
import com.anypreta.bountyboard.ui.theme.Fraunces
import kotlinx.coroutines.launch

class PublicProfileViewModel(
    private val container: AppContainer,
    private val userId: String,
) : ViewModel() {

    var loading by mutableStateOf(true)
        private set
    var error by mutableStateOf<String?>(null)
        private set
    var card by mutableStateOf<UserCard?>(null)
        private set

    init {
        load()
    }

    fun load() {
        loading = true; error = null
        viewModelScope.launch {
            try {
                card = container.repo.call { userCard(userId) }.card
            } catch (e: Exception) {
                error = e.message
            } finally {
                loading = false
            }
        }
    }

    fun startDm(onDone: (String) -> Unit) {
        viewModelScope.launch {
            try {
                val r = container.repo.call {
                    createConversation(CreateConversationBody(kind = "dm", participantIds = listOf(userId)))
                }
                onDone(r.conversation.id)
            } catch (e: Exception) {
                error = e.message
            }
        }
    }
}

@OptIn(ExperimentalLayoutApi::class)
@Composable
fun PublicProfileScreen(userId: String, onOpenConversation: (String) -> Unit) {
    val container = LocalAppContainer.current
    val vm: PublicProfileViewModel = viewModel(
        key = "pubprofile_$userId",
        factory = containerVMFactory(container) { PublicProfileViewModel(it, userId) },
    )
    val p = BB.colors
    val uriHandler = LocalUriHandler.current

    ScreenState(loading = vm.loading, error = vm.error, onRetry = { vm.load() }) {
        val card = vm.card ?: return@ScreenState

        Column(
            Modifier
                .fillMaxWidth()
                .verticalScroll(rememberScrollState())
                .padding(16.dp),
            verticalArrangement = Arrangement.spacedBy(14.dp),
        ) {
            Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.spacedBy(10.dp)) {
                BBAvatar(card.name, card.avatarFileId, size = 96.dp)
                Text(
                    card.name,
                    fontFamily = Fraunces,
                    style = MaterialTheme.typography.headlineMedium,
                    color = p.text,
                    textAlign = TextAlign.Center,
                )
                FlowRow(horizontalArrangement = Arrangement.spacedBy(6.dp), verticalArrangement = Arrangement.spacedBy(6.dp)) {
                    if (card.roles.admin) BBBadge("Admin", color = p.accent)
                    if (card.roles.consultant) BBBadge("Consultant", color = p.ok)
                    if (card.roles.developer) BBBadge("Developer", color = p.muted)
                }
                BBButton(
                    "Message",
                    onClick = { vm.startDm { onOpenConversation(it) } },
                    style = BBButtonStyle.Primary,
                )
            }

            if (!card.bio.isNullOrBlank()) {
                BBCard(modifier = Modifier.fillMaxWidth()) {
                    Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
                        SectionLabel("About")
                        Text(card.bio!!, style = MaterialTheme.typography.bodyMedium, color = p.text)
                    }
                }
            }

            val contact = card.contact
            val hasContact = contact != null && (!contact.phone.isNullOrBlank() || !contact.location.isNullOrBlank() || !contact.links.isNullOrEmpty())
            if (hasContact) {
                BBCard(modifier = Modifier.fillMaxWidth()) {
                    Column(verticalArrangement = Arrangement.spacedBy(10.dp)) {
                        SectionLabel("Contact")
                        contact?.phone?.takeIf { it.isNotBlank() }?.let {
                            Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp)) {
                                Icon(Icons.Outlined.Phone, null, tint = p.muted, modifier = Modifier.size(16.dp))
                                Text(it, style = MaterialTheme.typography.bodyMedium, color = p.text)
                            }
                        }
                        contact?.location?.takeIf { it.isNotBlank() }?.let {
                            Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp)) {
                                Icon(Icons.Outlined.LocationOn, null, tint = p.muted, modifier = Modifier.size(16.dp))
                                Text(it, style = MaterialTheme.typography.bodyMedium, color = p.text)
                            }
                        }
                        contact?.links?.filter { it.isNotBlank() }?.forEach { link ->
                            Row(
                                verticalAlignment = Alignment.CenterVertically,
                                horizontalArrangement = Arrangement.spacedBy(8.dp),
                                modifier = Modifier.clickable { uriHandler.openUri(link) },
                            ) {
                                Icon(Icons.Outlined.Link, null, tint = p.accent, modifier = Modifier.size(16.dp))
                                Text(link, style = MaterialTheme.typography.bodyMedium, color = p.accent, maxLines = 1)
                            }
                        }
                    }
                }
            }

            val extra = card.extra?.filterValues { it != null }
            if (!extra.isNullOrEmpty()) {
                BBCard(modifier = Modifier.fillMaxWidth()) {
                    Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
                        SectionLabel("Details")
                        extra.entries.forEachIndexed { i, (k, v) ->
                            if (i > 0) Hairline()
                            Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) {
                                Text(k, style = MaterialTheme.typography.labelSmall, color = p.muted)
                                Text(v.toString(), style = MaterialTheme.typography.bodyMedium, color = p.text)
                            }
                        }
                    }
                }
            }

            Spacer(Modifier.height(32.dp))
        }
    }
}
