package com.swoosh.microblog.ui.stats

import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
import com.swoosh.microblog.data.model.FeedPost
import com.swoosh.microblog.data.model.GhostTagFull
import com.swoosh.microblog.data.model.OverallStats
import com.swoosh.microblog.data.repository.MemberRepository
import com.swoosh.microblog.data.repository.MemberStats
import com.swoosh.microblog.data.repository.PostRepository
import com.swoosh.microblog.data.repository.TagRepository
import kotlinx.coroutines.async
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch

class StatsViewModel(application: Application) : AndroidViewModel(application) {

    private val repository = PostRepository(application)
    private val memberRepository = MemberRepository(application)
    private val tagRepository = TagRepository(application)

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

    init {
        loadStats()
    }

    fun loadStats() {
        viewModelScope.launch {
            _uiState.update { it.copy(isLoading = true) }

            try {
                // Launch posts, members, and tags fetches in parallel
                val postsDeferred = async {
                    val localPosts = repository.getAllLocalPostsList()
                    val remotePosts = mutableListOf<FeedPost>()
                    var page = 1
                    var hasMore = true
                    while (hasMore) {
                        val result = repository.fetchPosts(page = page, limit = 50)
                        result.fold(
                            onSuccess = { response ->
                                remotePosts.addAll(response.posts.map { ghost ->
                                    FeedPost(
                                        ghostId = ghost.id,
                                        title = ghost.title ?: "",
                                        textContent = ghost.plaintext ?: ghost.html?.replace(Regex("<[^>]*>"), "") ?: "",
                                        htmlContent = ghost.html,
                                        imageUrl = ghost.feature_image,
                                        linkUrl = null,
                                        linkTitle = null,
                                        linkDescription = null,
                                        linkImageUrl = null,
                                        tags = ghost.tags?.map { it.name } ?: emptyList(),
                                        status = ghost.status ?: "draft",
                                        publishedAt = ghost.published_at,
                                        createdAt = ghost.created_at,
                                        updatedAt = ghost.updated_at,
                                        isLocal = false
                                    )
                                })
                                hasMore = response.meta?.pagination?.next != null
                                page++
                            },
                            onFailure = {
                                hasMore = false
                            }
                        )
                        if (page > 20) break
                    }
                    val localGhostIds = localPosts.mapNotNull { it.ghostId }.toSet()
                    val uniqueRemotePosts = remotePosts.filter { it.ghostId !in localGhostIds }
                    Pair(localPosts, uniqueRemotePosts)
                }

                val membersDeferred = async {
                    try {
                        val membersResult = memberRepository.fetchAllMembers()
                        membersResult.getOrNull()?.let { members ->
                            memberRepository.getMemberStats(members)
                        }
                    } catch (e: Exception) {
                        null
                    }
                }

                val tagsDeferred = async {
                    try {
                        tagRepository.fetchTags().getOrNull()
                            ?.sortedByDescending { it.count?.posts ?: 0 }
                            ?: emptyList()
                    } catch (e: Exception) {
                        emptyList()
                    }
                }

                val (localPosts, uniqueRemotePosts) = postsDeferred.await()
                val memberStats = membersDeferred.await()
                val tagStats = tagsDeferred.await()

                val stats = OverallStats.calculate(localPosts, uniqueRemotePosts)

                // Count posts without any tags
                val totalPosts = localPosts.size + uniqueRemotePosts.size
                val postsWithTags = uniqueRemotePosts.count { it.tags.isNotEmpty() }
                val postsWithoutTags = totalPosts - postsWithTags

                // Most used tag
                val mostUsedTag = tagStats.firstOrNull()

                _uiState.update {
                    it.copy(
                        stats = stats,
                        memberStats = memberStats,
                        tagStats = tagStats,
                        mostUsedTag = mostUsedTag,
                        postsWithoutTags = postsWithoutTags,
                        isLoading = false
                    )
                }
            } catch (e: Exception) {
                _uiState.update { it.copy(isLoading = false, error = e.message) }
            }
        }
    }
}

data class StatsUiState(
    val stats: OverallStats = OverallStats(),
    val memberStats: MemberStats? = null,
    val tagStats: List<GhostTagFull> = emptyList(),
    val mostUsedTag: GhostTagFull? = null,
    val postsWithoutTags: Int = 0,
    val isLoading: Boolean = false,
    val error: String? = null
)
