package app.closer.ui.home

import android.util.Log
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.navigationBarsPadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeDrawingPadding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.HourglassEmpty
import androidx.compose.material.icons.filled.LocalFireDepartment
import androidx.compose.material.icons.filled.NotificationsNone
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
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.layout.ContentScale
import coil.compose.AsyncImage
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import app.closer.core.navigation.AppRoute
import app.closer.data.remote.FirestoreAnswerDataSource
import app.closer.domain.repository.AuthRepository
import app.closer.domain.repository.CoupleRepository
import app.closer.domain.repository.UserRepository
import app.closer.ui.components.ErrorState
import app.closer.ui.components.LoadingState
import app.closer.ui.theme.CloserPalette
import app.closer.ui.theme.closerBackgroundBrush
import app.closer.ui.theme.closerCardColor
import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.functions.FirebaseFunctions
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import kotlinx.coroutines.tasks.await

data class PartnerHomeUiState(
    val isLoading: Boolean = true,
    val error: String? = null,
    val partnerName: String? = null,
    val partnerPhotoUrl: String? = null,
    val streakCount: Int = 0,
    val hasPartnerAnsweredToday: Boolean = false,
    val coupleId: String? = null,
    val dailyQuestionId: String? = null,
    val isSendingReminder: Boolean = false,
    val reminderSentEvent: Boolean = false,
    val reminderError: String? = null,
)

@HiltViewModel
class PartnerHomeViewModel @Inject constructor(
    private val authRepository: AuthRepository,
    private val coupleRepository: CoupleRepository,
    private val userRepository: UserRepository,
    private val answerDataSource: FirestoreAnswerDataSource,
    private val db: FirebaseFirestore,
    private val functions: FirebaseFunctions,
) : ViewModel() {

    private val _uiState = MutableStateFlow(PartnerHomeUiState())
    val uiState: StateFlow<PartnerHomeUiState> = _uiState.asStateFlow()

    private var partnerAnswerListener: com.google.firebase.firestore.ListenerRegistration? = null

    init {
        load()
    }

    private fun load() {
        viewModelScope.launch {
            val uid = authRepository.currentUserId
            if (uid == null) {
                _uiState.update { it.copy(isLoading = false, error = "Not signed in.") }
                return@launch
            }
            runCatching {
                val couple = coupleRepository.getCoupleForUser(uid)
                if (couple == null) {
                    _uiState.update { it.copy(isLoading = false, error = "No partner linked yet.") }
                    return@launch
                }
                val partnerId = couple.userIds.firstOrNull { it != uid }
                val partner = partnerId?.let { pid ->
                    runCatching { userRepository.getUser(pid) }
                        .onFailure { Log.w(TAG, "Could not load partner", it) }
                        .getOrNull()
                }
                val partnerName = partner?.displayName
                val partnerPhotoUrl = partner?.photoUrl
                val dailyAssignment = runCatching {
                    answerDataSource.getDailyQuestionAssignment(couple.id)
                }.getOrNull()

                _uiState.update {
                    it.copy(
                        isLoading = false,
                        partnerName = partnerName,
                        partnerPhotoUrl = partnerPhotoUrl,
                        streakCount = couple.streakCount,
                        coupleId = couple.id,
                        dailyQuestionId = dailyAssignment?.questionId,
                    )
                }
                observePartnerAnswer(couple.id, couple.userIds, dailyAssignment?.questionId)
            }.onFailure { e ->
                Log.e(TAG, "Load failed", e)
                _uiState.update { it.copy(isLoading = false, error = "Could not load partner info.") }
            }
        }
    }

    private fun observePartnerAnswer(coupleId: String, userIds: List<String>, questionId: String?) {
        partnerAnswerListener?.remove()
        val uid = authRepository.currentUserId ?: return
        val partnerId = userIds.firstOrNull { it != uid } ?: return
        val qId = questionId ?: return
        val today = FirestoreAnswerDataSource.todayLocalDateString()
        partnerAnswerListener = db.collection("couples").document(coupleId)
            .collection("daily_question").document(today)
            .collection("answers").document(partnerId)
            .addSnapshotListener { snapshot, error ->
                if (error != null) {
                    Log.w(TAG, "Partner answer listener error", error)
                    return@addSnapshotListener
                }
                _uiState.update { it.copy(hasPartnerAnsweredToday = snapshot?.exists() == true) }
            }
    }

    fun sendReminder() {
        if (_uiState.value.isSendingReminder) return
        _uiState.update { it.copy(isSendingReminder = true, reminderError = null) }
        viewModelScope.launch {
            runCatching {
                functions.getHttpsCallable("sendGentleReminderCallable").call().await()
            }.onSuccess {
                _uiState.update { it.copy(isSendingReminder = false, reminderSentEvent = true) }
            }.onFailure { e ->
                Log.w(TAG, "Reminder failed", e)
                _uiState.update { it.copy(isSendingReminder = false, reminderError = "Could not send reminder.") }
            }
        }
    }

    fun consumeReminderSentEvent() = _uiState.update { it.copy(reminderSentEvent = false) }
    fun consumeReminderError() = _uiState.update { it.copy(reminderError = null) }

    override fun onCleared() {
        super.onCleared()
        partnerAnswerListener?.remove()
    }

    private companion object {
        const val TAG = "PartnerHomeVM"
    }
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun PartnerHomeScreen(
    onNavigate: (String) -> Unit = {},
    viewModel: PartnerHomeViewModel = hiltViewModel()
) {
    val state by viewModel.uiState.collectAsState()
    val snackbar = remember { SnackbarHostState() }

    LaunchedEffect(state.reminderSentEvent) {
        if (state.reminderSentEvent) {
            snackbar.showSnackbar("Reminder sent to ${state.partnerName ?: "your partner"}.")
            viewModel.consumeReminderSentEvent()
        }
    }
    LaunchedEffect(state.reminderError) {
        state.reminderError?.let {
            snackbar.showSnackbar(it)
            viewModel.consumeReminderError()
        }
    }

    Scaffold(
        snackbarHost = { SnackbarHost(snackbar) },
        containerColor = Color.Transparent,
        modifier = Modifier.background(closerBackgroundBrush()),
        topBar = {
            TopAppBar(
                title = {
                    Text(
                        text = state.partnerName ?: "Your Partner",
                        fontWeight = FontWeight.SemiBold,
                        maxLines = 1,
                        overflow = TextOverflow.Ellipsis,
                        color = MaterialTheme.colorScheme.onSurface
                    )
                },
                navigationIcon = {
                    IconButton(onClick = { onNavigate("back") }) {
                        Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "Back")
                    }
                },
                colors = TopAppBarDefaults.topAppBarColors(containerColor = Color.Transparent)
            )
        }
    ) { padding ->
        when {
            state.isLoading -> LoadingState(modifier = Modifier.fillMaxSize().padding(padding))
            state.error != null -> ErrorState(
                message = state.error!!,
                modifier = Modifier.fillMaxSize().padding(padding)
            )
            else -> PartnerHomeContent(
                state = state,
                onSendReminder = viewModel::sendReminder,
                onNavigate = onNavigate,
                modifier = Modifier.padding(padding)
            )
        }
    }
}

@Composable
private fun PartnerHomeContent(
    state: PartnerHomeUiState,
    onSendReminder: () -> Unit,
    onNavigate: (String) -> Unit,
    modifier: Modifier = Modifier
) {
    Column(
        modifier = modifier
            .fillMaxSize()
            .safeDrawingPadding()
            .navigationBarsPadding()
            .verticalScroll(rememberScrollState())
            .padding(horizontal = 20.dp, vertical = 12.dp),
        verticalArrangement = Arrangement.spacedBy(16.dp)
    ) {
        PartnerIdentityCard(name = state.partnerName, photoUrl = state.partnerPhotoUrl, streakCount = state.streakCount)

        PartnerActivityCard(
            partnerName = state.partnerName,
            hasAnsweredToday = state.hasPartnerAnsweredToday,
            isSendingReminder = state.isSendingReminder,
            onSendReminder = onSendReminder
        )

        if (state.dailyQuestionId != null) {
            Button(
                onClick = { onNavigate(AppRoute.DAILY_QUESTION) },
                modifier = Modifier.fillMaxWidth(),
                shape = RoundedCornerShape(16.dp),
                colors = ButtonDefaults.buttonColors(
                    containerColor = CloserPalette.PurpleDeep,
                    contentColor = Color.White
                )
            ) {
                Text("View today's question", fontWeight = FontWeight.SemiBold)
            }
        }

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

@Composable
private fun PartnerIdentityCard(
    name: String?,
    photoUrl: String?,
    streakCount: Int,
    modifier: Modifier = Modifier
) {
    Surface(
        modifier = modifier.fillMaxWidth(),
        shape = RoundedCornerShape(24.dp),
        color = closerCardColor(alpha = 0.9f),
        shadowElevation = 2.dp
    ) {
        Row(
            modifier = Modifier.padding(20.dp),
            horizontalArrangement = Arrangement.spacedBy(16.dp),
            verticalAlignment = Alignment.CenterVertically
        ) {
            if (!photoUrl.isNullOrBlank()) {
                AsyncImage(
                    model = photoUrl,
                    contentDescription = name,
                    contentScale = ContentScale.Crop,
                    modifier = Modifier
                        .size(56.dp)
                        .clip(CircleShape)
                )
            } else {
                Surface(
                    shape = CircleShape,
                    color = CloserPalette.PurpleDeep.copy(alpha = 0.14f),
                    modifier = Modifier.size(56.dp)
                ) {
                    Box(contentAlignment = Alignment.Center) {
                        Text(
                            text = (name?.firstOrNull()?.uppercaseChar() ?: '?').toString(),
                            style = MaterialTheme.typography.headlineMedium.copy(
                                fontWeight = FontWeight.SemiBold,
                                fontSize = 24.sp
                            ),
                            color = CloserPalette.PurpleDeep
                        )
                    }
                }
            }

            Column(verticalArrangement = Arrangement.spacedBy(3.dp)) {
                Text(
                    text = name ?: "Your partner",
                    style = MaterialTheme.typography.titleLarge.copy(fontWeight = FontWeight.SemiBold),
                    color = MaterialTheme.colorScheme.onSurface,
                    maxLines = 1,
                    overflow = TextOverflow.Ellipsis
                )
                Row(
                    horizontalArrangement = Arrangement.spacedBy(5.dp),
                    verticalAlignment = Alignment.CenterVertically
                ) {
                    Icon(
                        imageVector = Icons.Filled.LocalFireDepartment,
                        contentDescription = null,
                        tint = CloserPalette.PinkAccentDeep,
                        modifier = Modifier.size(15.dp)
                    )
                    Text(
                        text = when (streakCount) {
                            0 -> "Start your little ritual together"
                            1 -> "1 day showing up"
                            else -> "$streakCount days showing up"
                        },
                        style = MaterialTheme.typography.bodyMedium,
                        color = MaterialTheme.colorScheme.onSurfaceVariant
                    )
                }
            }
        }
    }
}

@Composable
private fun PartnerActivityCard(
    partnerName: String?,
    hasAnsweredToday: Boolean,
    isSendingReminder: Boolean,
    onSendReminder: () -> Unit,
    modifier: Modifier = Modifier
) {
    val firstName = partnerName?.substringBefore(" ") ?: "Your partner"

    Surface(
        modifier = modifier.fillMaxWidth(),
        shape = RoundedCornerShape(24.dp),
        color = closerCardColor(alpha = 0.9f),
        shadowElevation = 2.dp
    ) {
        Column(
            modifier = Modifier.padding(20.dp),
            verticalArrangement = Arrangement.spacedBy(14.dp)
        ) {
            Text(
                text = "Today",
                style = MaterialTheme.typography.labelLarge.copy(fontWeight = FontWeight.SemiBold),
                color = MaterialTheme.colorScheme.onSurfaceVariant
            )

            Row(
                horizontalArrangement = Arrangement.spacedBy(12.dp),
                verticalAlignment = Alignment.CenterVertically
            ) {
                Surface(
                    shape = CircleShape,
                    color = if (hasAnsweredToday) {
                        CloserPalette.PurpleDeep.copy(alpha = 0.12f)
                    } else {
                        MaterialTheme.colorScheme.surfaceVariant
                    },
                    modifier = Modifier.size(40.dp)
                ) {
                    Box(contentAlignment = Alignment.Center) {
                        Icon(
                            imageVector = if (hasAnsweredToday) Icons.Filled.Check else Icons.Filled.HourglassEmpty,
                            contentDescription = null,
                            tint = if (hasAnsweredToday) CloserPalette.PurpleDeep else MaterialTheme.colorScheme.onSurfaceVariant,
                            modifier = Modifier.size(20.dp)
                        )
                    }
                }
                Column(verticalArrangement = Arrangement.spacedBy(2.dp)) {
                    Text(
                        text = if (hasAnsweredToday) "$firstName answered" else "$firstName hasn't answered yet",
                        style = MaterialTheme.typography.bodyLarge.copy(fontWeight = FontWeight.SemiBold),
                        color = MaterialTheme.colorScheme.onSurface
                    )
                    Text(
                        text = if (hasAnsweredToday) "Today's question is complete" else "Waiting for today's question",
                        style = MaterialTheme.typography.bodySmall,
                        color = MaterialTheme.colorScheme.onSurfaceVariant
                    )
                }
            }

            if (!hasAnsweredToday) {
                Button(
                    onClick = onSendReminder,
                    enabled = !isSendingReminder,
                    modifier = Modifier.fillMaxWidth(),
                    shape = RoundedCornerShape(12.dp),
                    colors = ButtonDefaults.buttonColors(
                        containerColor = CloserPalette.PurpleDeep.copy(alpha = 0.1f),
                        contentColor = CloserPalette.PurpleDeep,
                        disabledContainerColor = CloserPalette.PurpleDeep.copy(alpha = 0.06f),
                        disabledContentColor = CloserPalette.PurpleDeep.copy(alpha = 0.4f)
                    )
                ) {
                    Icon(
                        Icons.Filled.NotificationsNone,
                        contentDescription = null,
                        modifier = Modifier.size(16.dp)
                    )
                    Spacer(Modifier.size(6.dp))
                    Text(
                        text = if (isSendingReminder) "Sending…" else "Send a gentle nudge",
                        fontWeight = FontWeight.SemiBold
                    )
                }
            }
        }
    }
}
