package com.ffii.fpsms.modules.stock.entity

import com.ffii.core.support.AbstractRepository
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.data.jpa.repository.Query
import org.springframework.data.repository.query.Param
import org.springframework.stereotype.Repository
import java.time.LocalDate
import java.time.LocalDateTime
@Repository
interface StockLedgerRepository: AbstractRepository<StockLedger, Long> {
    
    @Query("""
        SELECT sl FROM StockLedger sl
        LEFT JOIN sl.stockInLine sil
        LEFT JOIN sl.stockOutLine sol
        LEFT JOIN sl.inventory inv
        LEFT JOIN inv.item i
        WHERE sl.deleted = false
          AND (:itemCode IS NULL OR sl.itemCode LIKE CONCAT('%', :itemCode, '%'))
          AND (:itemName IS NULL OR i.name LIKE CONCAT('%', :itemName, '%'))
          AND (:type IS NULL OR sl.type = :type)
          AND (:startDateTime IS NULL OR sl.created >= :startDateTime)
          AND (:endDateExclusive IS NULL OR sl.created < :endDateExclusive)
    """)
    fun findStockTransactions(
        @Param("itemCode") itemCode: String?,
        @Param("itemName") itemName: String?,
        @Param("type") type: String?,
        @Param("startDateTime") startDateTime: LocalDateTime?,
        @Param("endDateExclusive") endDateExclusive: LocalDateTime?,
        pageable: Pageable
    ): Page<StockLedger>
    
    @Query("""
        SELECT COUNT(sl) FROM StockLedger sl
        LEFT JOIN sl.inventory inv
        LEFT JOIN inv.item i
        WHERE sl.deleted = false
          AND (:itemCode IS NULL OR sl.itemCode LIKE CONCAT('%', :itemCode, '%'))
          AND (:itemName IS NULL OR i.name LIKE CONCAT('%', :itemName, '%'))
          AND (:type IS NULL OR sl.type = :type)
          AND (:startDateTime IS NULL OR sl.created >= :startDateTime)
          AND (:endDateExclusive IS NULL OR sl.created < :endDateExclusive)
    """)
    fun countStockTransactions(
        @Param("itemCode") itemCode: String?,
        @Param("itemName") itemName: String?,
        @Param("type") type: String?,
        @Param("startDateTime") startDateTime: LocalDateTime?,
        @Param("endDateExclusive") endDateExclusive: LocalDateTime?
    ): Long


    @Query("""
    SELECT sl FROM StockLedger sl
    WHERE sl.itemId = :itemId AND sl.deleted = false
    ORDER BY sl.date DESC, sl.id DESC
""")
fun findLatestByItemId(@Param("itemId") itemId: Long): List<StockLedger>
fun findFirstByItemIdAndDeletedFalseOrderByDateDescIdDesc(itemId: Long): StockLedger?

    @Query("""
        SELECT sl FROM StockLedger sl
        LEFT JOIN sl.stockOutLine sol
        LEFT JOIN sol.inventoryLotLine ill
        LEFT JOIN ill.inventoryLot il
        LEFT JOIN sl.inventory inv
        LEFT JOIN inv.item i
        WHERE sl.deleted = false
          AND sl.type = :type
          AND sl.outQty IS NOT NULL AND sl.outQty > 0
          AND (:itemCode IS NULL OR sl.itemCode LIKE CONCAT('%', :itemCode, '%'))
          AND (:itemName IS NULL OR i.name LIKE CONCAT('%', :itemName, '%'))
          AND (:lotNo IS NULL OR il.lotNo LIKE CONCAT('%', :lotNo, '%'))
          AND (:startDate IS NULL OR sl.date >= :startDate)
          AND (:endDateExclusive IS NULL OR sl.date < :endDateExclusive)
        ORDER BY sl.date DESC, sl.id DESC
    """)
    fun findStockIssueHandleRecords(
        @Param("type") type: String,
        @Param("itemCode") itemCode: String?,
        @Param("itemName") itemName: String?,
        @Param("lotNo") lotNo: String?,
        @Param("startDate") startDate: LocalDate?,
        @Param("endDateExclusive") endDateExclusive: LocalDate?,
        pageable: Pageable,
    ): Page<StockLedger>

    @Query("""
        SELECT sl FROM StockLedger sl
        LEFT JOIN sl.stockOutLine sol
        LEFT JOIN sol.inventoryLotLine ill
        LEFT JOIN ill.inventoryLot il
        LEFT JOIN sl.inventory inv
        LEFT JOIN inv.item i
        WHERE sl.deleted = false
          AND sl.type = 'Expiry'
          AND sl.outQty IS NOT NULL AND sl.outQty > 0
          AND (:itemCode IS NULL OR sl.itemCode LIKE CONCAT('%', :itemCode, '%'))
          AND (:itemName IS NULL OR i.name LIKE CONCAT('%', :itemName, '%'))
          AND (:lotNo IS NULL OR il.lotNo LIKE CONCAT('%', :lotNo, '%'))
          AND (:startDate IS NULL OR il.expiryDate >= :startDate)
          AND (:endDateExclusive IS NULL OR il.expiryDate < :endDateExclusive)
        ORDER BY sl.date DESC, sl.id DESC
    """)
    fun findExpiryItemHandleRecords(
        @Param("itemCode") itemCode: String?,
        @Param("itemName") itemName: String?,
        @Param("lotNo") lotNo: String?,
        @Param("startDate") startDate: LocalDate?,
        @Param("endDateExclusive") endDateExclusive: LocalDate?,
        pageable: Pageable,
    ): Page<StockLedger>
}