package com.placeholder.sherpai2.ui.explore

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.placeholder.sherpai2.data.local.dao.ImageDao
import com.placeholder.sherpai2.data.local.dao.ImageTagDao
import com.placeholder.sherpai2.data.local.dao.PersonDao
import com.placeholder.sherpai2.data.local.dao.TagDao
import com.placeholder.sherpai2.data.local.entity.ImageEntity
import com.placeholder.sherpai2.data.repository.FaceRecognitionRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import java.util.Calendar
import javax.inject.Inject

@HiltViewModel
class ExploreViewModel @Inject constructor(
    private val imageDao: ImageDao,
    private val tagDao: TagDao,
    private val imageTagDao: ImageTagDao,
    private val personDao: PersonDao,
    private val faceRecognitionRepository: FaceRecognitionRepository
) : ViewModel() {

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

    sealed class ExploreUiState {
        object Loading : ExploreUiState()
        data class Success(
            val smartAlbums: List<SmartAlbum>
        ) : ExploreUiState()
        data class Error(val message: String) : ExploreUiState()
    }

    init {
        loadExploreData()
    }

    fun loadExploreData() {
        viewModelScope.launch {
            try {
                _uiState.value = ExploreUiState.Loading

                val smartAlbums = buildSmartAlbums()

                _uiState.value = ExploreUiState.Success(
                    smartAlbums = smartAlbums
                )

            } catch (e: Exception) {
                _uiState.value = ExploreUiState.Error(
                    e.message ?: "Failed to load explore data"
                )
            }
        }
    }

    private suspend fun buildSmartAlbums(): List<SmartAlbum> {
        val albums = mutableListOf<SmartAlbum>()

        // Time-based albums
        albums.add(SmartAlbum.TimeRange.Today)
        albums.add(SmartAlbum.TimeRange.ThisWeek)
        albums.add(SmartAlbum.TimeRange.ThisMonth)
        albums.add(SmartAlbum.TimeRange.LastYear)

        // Face-based albums (from system tags)
        val groupPhotoTag = tagDao.getByValue("group_photo")
        if (groupPhotoTag != null) {
            val count = tagDao.getTagUsageCount(groupPhotoTag.tagId)
            if (count > 0) {
                albums.add(SmartAlbum.Tagged("group_photo", "Group Photos", count))
            }
        }

        val selfieTag = tagDao.getByValue("selfie")
        if (selfieTag != null) {
            val count = tagDao.getTagUsageCount(selfieTag.tagId)
            if (count > 0) {
                albums.add(SmartAlbum.Tagged("selfie", "Selfies", count))
            }
        }

        val coupleTag = tagDao.getByValue("couple")
        if (coupleTag != null) {
            val count = tagDao.getTagUsageCount(coupleTag.tagId)
            if (count > 0) {
                albums.add(SmartAlbum.Tagged("couple", "Couples", count))
            }
        }

        // Relationship albums
        val familyTag = tagDao.getByValue("family")
        if (familyTag != null) {
            val count = tagDao.getTagUsageCount(familyTag.tagId)
            if (count > 0) {
                albums.add(SmartAlbum.Tagged("family", "Family Moments", count))
            }
        }

        val friendTag = tagDao.getByValue("friend")
        if (friendTag != null) {
            val count = tagDao.getTagUsageCount(friendTag.tagId)
            if (count > 0) {
                albums.add(SmartAlbum.Tagged("friend", "With Friends", count))
            }
        }

        val colleagueTag = tagDao.getByValue("colleague")
        if (colleagueTag != null) {
            val count = tagDao.getTagUsageCount(colleagueTag.tagId)
            if (count > 0) {
                albums.add(SmartAlbum.Tagged("colleague", "Work Events", count))
            }
        }

        // Time of day albums
        val morningTag = tagDao.getByValue("morning")
        if (morningTag != null) {
            val count = tagDao.getTagUsageCount(morningTag.tagId)
            if (count > 0) {
                albums.add(SmartAlbum.Tagged("morning", "Morning Moments", count))
            }
        }

        val eveningTag = tagDao.getByValue("evening")
        if (eveningTag != null) {
            val count = tagDao.getTagUsageCount(eveningTag.tagId)
            if (count > 0) {
                albums.add(SmartAlbum.Tagged("evening", "Golden Hour", count))
            }
        }

        val nightTag = tagDao.getByValue("night")
        if (nightTag != null) {
            val count = tagDao.getTagUsageCount(nightTag.tagId)
            if (count > 0) {
                albums.add(SmartAlbum.Tagged("night", "Night Life", count))
            }
        }

        // Scene albums
        val outdoorTag = tagDao.getByValue("outdoor")
        if (outdoorTag != null) {
            val count = tagDao.getTagUsageCount(outdoorTag.tagId)
            if (count > 0) {
                albums.add(SmartAlbum.Tagged("outdoor", "Outdoor Adventures", count))
            }
        }

        val indoorTag = tagDao.getByValue("indoor")
        if (indoorTag != null) {
            val count = tagDao.getTagUsageCount(indoorTag.tagId)
            if (count > 0) {
                albums.add(SmartAlbum.Tagged("indoor", "Indoor Moments", count))
            }
        }

        // Special occasions
        val birthdayTag = tagDao.getByValue("birthday")
        if (birthdayTag != null) {
            val count = tagDao.getTagUsageCount(birthdayTag.tagId)
            if (count > 0) {
                albums.add(SmartAlbum.Tagged("birthday", "Birthdays", count))
            }
        }

        // Quality albums
        val highResTag = tagDao.getByValue("high_res")
        if (highResTag != null) {
            val count = tagDao.getTagUsageCount(highResTag.tagId)
            if (count > 0) {
                albums.add(SmartAlbum.Tagged("high_res", "Best Quality", count))
            }
        }

        // Person albums
        val persons = personDao.getAllPersons()
        persons.forEach { person ->
            val stats = faceRecognitionRepository.getPersonFaceStats(person.id)
            if (stats != null && stats.taggedPhotoCount > 0) {
                albums.add(SmartAlbum.Person(
                    personId = person.id,
                    personName = person.name,
                    imageCount = stats.taggedPhotoCount
                ))
            }
        }

        return albums
    }

    /**
     * Get images for a specific smart album
     */
    suspend fun getImagesForAlbum(album: SmartAlbum): List<ImageEntity> {
        return when (album) {
            is SmartAlbum.TimeRange.Today -> {
                val startOfDay = getStartOfDay()
                imageDao.getImagesInRange(startOfDay, System.currentTimeMillis())
            }
            is SmartAlbum.TimeRange.ThisWeek -> {
                val startOfWeek = getStartOfWeek()
                imageDao.getImagesInRange(startOfWeek, System.currentTimeMillis())
            }
            is SmartAlbum.TimeRange.ThisMonth -> {
                val startOfMonth = getStartOfMonth()
                imageDao.getImagesInRange(startOfMonth, System.currentTimeMillis())
            }
            is SmartAlbum.TimeRange.LastYear -> {
                val oneYearAgo = System.currentTimeMillis() - (365L * 24 * 60 * 60 * 1000)
                imageDao.getImagesInRange(oneYearAgo, System.currentTimeMillis())
            }
            is SmartAlbum.Tagged -> {
                val tag = tagDao.getByValue(album.tagValue)
                if (tag != null) {
                    val imageIds = imageTagDao.findImagesByTag(tag.tagId, 0.5f)
                    imageDao.getImagesByIds(imageIds)
                } else {
                    emptyList()
                }
            }
            is SmartAlbum.Person -> {
                faceRecognitionRepository.getImagesForPerson(album.personId)
            }
        }
    }

    private fun getStartOfDay(): Long {
        return Calendar.getInstance().apply {
            set(Calendar.HOUR_OF_DAY, 0)
            set(Calendar.MINUTE, 0)
            set(Calendar.SECOND, 0)
            set(Calendar.MILLISECOND, 0)
        }.timeInMillis
    }

    private fun getStartOfWeek(): Long {
        return Calendar.getInstance().apply {
            set(Calendar.DAY_OF_WEEK, firstDayOfWeek)
            set(Calendar.HOUR_OF_DAY, 0)
            set(Calendar.MINUTE, 0)
            set(Calendar.SECOND, 0)
            set(Calendar.MILLISECOND, 0)
        }.timeInMillis
    }

    private fun getStartOfMonth(): Long {
        return Calendar.getInstance().apply {
            set(Calendar.DAY_OF_MONTH, 1)
            set(Calendar.HOUR_OF_DAY, 0)
            set(Calendar.MINUTE, 0)
            set(Calendar.SECOND, 0)
            set(Calendar.MILLISECOND, 0)
        }.timeInMillis
    }
}

/**
 * Smart album types
 */
sealed class SmartAlbum {
    abstract val displayName: String
    abstract val imageCount: Int

    sealed class TimeRange : SmartAlbum() {
        data object Today : TimeRange() {
            override val displayName = "Today"
            override val imageCount = 0 // Calculated dynamically
        }
        data object ThisWeek : TimeRange() {
            override val displayName = "This Week"
            override val imageCount = 0
        }
        data object ThisMonth : TimeRange() {
            override val displayName = "This Month"
            override val imageCount = 0
        }
        data object LastYear : TimeRange() {
            override val displayName = "Last Year"
            override val imageCount = 0
        }
    }

    data class Tagged(
        val tagValue: String,
        override val displayName: String,
        override val imageCount: Int
    ) : SmartAlbum()

    data class Person(
        val personId: String,
        val personName: String,
        override val imageCount: Int
    ) : SmartAlbum() {
        override val displayName = personName
    }
}