package com.placeholder.sherpai2.data.local.dao

import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.Update
import com.placeholder.sherpai2.data.local.entity.FaceCacheEntity

/**
 * FaceCacheDao - ENHANCED with cache-aware queries
 *
 * PHASE 1 ENHANCEMENTS:
 * ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 * ✅ Query quality faces WITHOUT requiring embeddings
 * ✅ Count faces without embeddings for diagnostics
 * ✅ Support 3-path clustering strategy:
 *    Path 1: Cached embeddings (instant)
 *    Path 2: Quality metadata → generate embeddings (fast)
 *    Path 3: Full scan (slow, fallback only)
 */
@Dao
interface FaceCacheDao {

    // ═══════════════════════════════════════
    // INSERT / UPDATE
    // ═══════════════════════════════════════

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insert(faceCache: FaceCacheEntity)

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertAll(faceCaches: List<FaceCacheEntity>)

    @Update
    suspend fun update(faceCache: FaceCacheEntity)

    /**
     * Batch update embeddings for existing cache entries
     * Used when generating embeddings on-demand
     */
    @Update
    suspend fun updateAll(faceCaches: List<FaceCacheEntity>)

    // ═══════════════════════════════════════
    // PHASE 1: CACHE-AWARE CLUSTERING QUERIES
    // ═══════════════════════════════════════

    /**
     * Path 1: Get faces WITH embeddings (instant clustering)
     *
     * This is the fastest path - embeddings already cached
     */
    @Query("""
        SELECT * FROM face_cache
        WHERE faceAreaRatio >= :minRatio
          AND qualityScore >= :minQuality
          AND embedding IS NOT NULL
        ORDER BY qualityScore DESC, faceAreaRatio DESC
        LIMIT :limit
    """)
    suspend fun getAllQualityFaces(
        minRatio: Float = 0.05f,
        minQuality: Float = 0.7f,
        limit: Int = Int.MAX_VALUE
    ): List<FaceCacheEntity>

    /**
     * Path 2: Get quality faces WITHOUT requiring embeddings
     *
     * PURPOSE: Pre-filter to quality faces, then generate embeddings on-demand
     * BENEFIT: Process ~1,200 faces instead of 10,824 photos
     *
     * USE CASE: First-time Discovery when cache has metadata but no embeddings
     */
    @Query("""
        SELECT * FROM face_cache
        WHERE faceAreaRatio >= :minRatio
          AND qualityScore >= :minQuality
        ORDER BY qualityScore DESC, faceAreaRatio DESC
        LIMIT :limit
    """)
    suspend fun getQualityFacesWithoutEmbeddings(
        minRatio: Float = 0.03f,
        minQuality: Float = 0.6f,
        limit: Int = 5000
    ): List<FaceCacheEntity>

    /**
     * Count faces without embeddings (for diagnostics)
     *
     * Shows how many faces need embedding generation
     */
    @Query("""
        SELECT COUNT(*) FROM face_cache
        WHERE embedding IS NULL
          AND qualityScore >= :minQuality
    """)
    suspend fun countFacesWithoutEmbeddings(
        minQuality: Float = 0.5f
    ): Int

    /**
     * Count faces WITH embeddings (for progress tracking)
     */
    @Query("""
        SELECT COUNT(*) FROM face_cache
        WHERE embedding IS NOT NULL
          AND qualityScore >= :minQuality
    """)
    suspend fun countFacesWithEmbeddings(
        minQuality: Float = 0.5f
    ): Int

    // ═══════════════════════════════════════
    // EXISTING QUERIES (PRESERVED)
    // ═══════════════════════════════════════

    /**
     * Get premium solo faces (STILL WORKS if you have solo photos cached)
     */
    @Query("""
        SELECT * FROM face_cache
        WHERE faceAreaRatio >= :minRatio
          AND qualityScore >= :minQuality
          AND embedding IS NOT NULL
        ORDER BY qualityScore DESC, faceAreaRatio DESC
        LIMIT :limit
    """)
    suspend fun getPremiumSoloFaces(
        minRatio: Float = 0.05f,
        minQuality: Float = 0.8f,
        limit: Int = 1000
    ): List<FaceCacheEntity>

    /**
     * Get standard quality faces (WORKS with any cached faces)
     */
    @Query("""
        SELECT * FROM face_cache
        WHERE faceAreaRatio >= :minRatio
          AND qualityScore >= :minQuality
          AND embedding IS NOT NULL
        ORDER BY qualityScore DESC, faceAreaRatio DESC
        LIMIT :limit
    """)
    suspend fun getStandardSoloFaces(
        minRatio: Float = 0.03f,
        minQuality: Float = 0.6f,
        limit: Int = 2000
    ): List<FaceCacheEntity>

    /**
     * Get any faces with embeddings (minimum requirements)
     */
    @Query("""
        SELECT * FROM face_cache
        WHERE embedding IS NOT NULL
          AND faceAreaRatio >= :minFaceRatio
        ORDER BY qualityScore DESC, faceAreaRatio DESC
        LIMIT :limit
    """)
    suspend fun getHighQualitySoloFaces(
        minFaceRatio: Float = 0.015f,
        limit: Int = 2000
    ): List<FaceCacheEntity>

    /**
     * Get faces with embeddings (no filters)
     */
    @Query("""
        SELECT * FROM face_cache
        WHERE embedding IS NOT NULL
        ORDER BY qualityScore DESC
        LIMIT :limit
    """)
    suspend fun getSoloFacesWithEmbeddings(
        limit: Int = 2000
    ): List<FaceCacheEntity>

    // ═══════════════════════════════════════
    // YEAR-BASED QUERIES (FOR FUTURE USE)
    // ═══════════════════════════════════════

    /**
     * Get faces from specific year
     * Note: Joins images table to get capturedAt
     */
    @Query("""
        SELECT fc.* FROM face_cache fc
        INNER JOIN images i ON fc.imageId = i.imageId
        WHERE fc.faceAreaRatio >= :minRatio
          AND fc.qualityScore >= :minQuality
          AND fc.embedding IS NOT NULL
          AND strftime('%Y', i.capturedAt/1000, 'unixepoch') = :year
        ORDER BY fc.qualityScore DESC, fc.faceAreaRatio DESC
        LIMIT :limit
    """)
    suspend fun getFacesByYear(
        year: String,
        minRatio: Float = 0.05f,
        minQuality: Float = 0.7f,
        limit: Int = 1000
    ): List<FaceCacheEntity>

    /**
     * Get years with sufficient photos
     */
    @Query("""
        SELECT 
            strftime('%Y', i.capturedAt/1000, 'unixepoch') as year,
            COUNT(*) as photoCount
        FROM face_cache fc
        INNER JOIN images i ON fc.imageId = i.imageId
        WHERE fc.faceAreaRatio >= :minRatio
          AND fc.embedding IS NOT NULL
        GROUP BY year
        HAVING photoCount >= :minPhotos
        ORDER BY year ASC
    """)
    suspend fun getYearsWithSufficientPhotos(
        minPhotos: Int = 20,
        minRatio: Float = 0.03f
    ): List<YearPhotoCount>

    // ═══════════════════════════════════════
    // UTILITY QUERIES
    // ═══════════════════════════════════════

    /**
     * Get faces excluding specific images
     */
    @Query("""
        SELECT * FROM face_cache
        WHERE faceAreaRatio >= :minRatio
          AND embedding IS NOT NULL
          AND imageId NOT IN (:excludedImageIds)
        ORDER BY qualityScore DESC
        LIMIT :limit
    """)
    suspend fun getSoloFacesExcluding(
        excludedImageIds: List<String>,
        minRatio: Float = 0.03f,
        limit: Int = 2000
    ): List<FaceCacheEntity>

    /**
     * Count quality faces
     */
    @Query("""
        SELECT COUNT(*) 
        FROM face_cache
        WHERE faceAreaRatio >= :minRatio
          AND qualityScore >= :minQuality
          AND embedding IS NOT NULL
    """)
    suspend fun countPremiumSoloFaces(
        minRatio: Float = 0.05f,
        minQuality: Float = 0.8f
    ): Int

    /**
     * Get stats on cached faces
     */
    @Query("""
        SELECT 
            COUNT(*) as totalFaces,
            COUNT(CASE WHEN embedding IS NOT NULL THEN 1 END) as withEmbeddings,
            AVG(faceAreaRatio) as avgSize,
            AVG(qualityScore) as avgQuality,
            MIN(qualityScore) as minQuality,
            MAX(qualityScore) as maxQuality
        FROM face_cache
    """)
    suspend fun getCacheStats(): CacheStats

    @Query("SELECT * FROM face_cache WHERE imageId = :imageId AND faceIndex = :faceIndex")
    suspend fun getFaceCacheByKey(imageId: String, faceIndex: Int): FaceCacheEntity?

    @Query("SELECT * FROM face_cache WHERE imageId = :imageId ORDER BY faceIndex")
    suspend fun getFaceCacheForImage(imageId: String): List<FaceCacheEntity>

    @Query("DELETE FROM face_cache WHERE imageId = :imageId")
    suspend fun deleteFaceCacheForImage(imageId: String)

    @Query("DELETE FROM face_cache")
    suspend fun deleteAll()

    @Query("DELETE FROM face_cache WHERE cacheVersion < :version")
    suspend fun deleteOldVersions(version: Int)
}

/**
 * Result classes
 */
data class YearPhotoCount(
    val year: String,
    val photoCount: Int
)

data class CacheStats(
    val totalFaces: Int,
    val withEmbeddings: Int,
    val avgSize: Float,
    val avgQuality: Float,
    val minQuality: Float,
    val maxQuality: Float
)