package org.nstart.dep265.requestservice.repository

import org.nstart.dep265.requestservice.entity.EarthCellEntity
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.data.jpa.repository.EntityGraph
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.data.jpa.repository.Query
import org.springframework.data.repository.query.Param
import java.util.Optional
import java.util.UUID

interface EarthCellRepository : JpaRepository<EarthCellEntity, Long> {
    @Query(
        value = """
        select earthCell
        from EarthCellEntity earthCell
        where (:minImportance is null or earthCell.importance > :minImportance)
        """,
        countQuery = """
        select count(earthCell)
        from EarthCellEntity earthCell
        where (:minImportance is null or earthCell.importance > :minImportance)
        """
    )
    fun findCells(
        @Param("minImportance") minImportance: Double?,
        pageable: Pageable,
    ): Page<EarthCellEntity>

    @EntityGraph(attributePaths = ["requestProjections"])
    @Query(
        """
        select distinct earthCell
        from EarthCellEntity earthCell
        where (:minImportance is null or earthCell.importance > :minImportance)
        order by earthCell.importance desc, earthCell.cellNum asc
        """
    )
    fun findCellsWithRequestProjections(
        @Param("minImportance") minImportance: Double?,
    ): List<EarthCellEntity>

    @Query(
        value = "SELECT * FROM earth_cells WHERE ST_Intersects(ST_GeomFromText(:polygon, 4326), contour_geom)",
        nativeQuery = true,
    )
    fun findIntersectingByContour(@Param("polygon") polygonWkt: String): List<EarthCellEntity>

    @Query(
        value = "SELECT * FROM earth_cells WHERE cell_id IN (SELECT cell_id FROM request_cells WHERE request_id = :requestId)",
        nativeQuery = true,
    )
    fun findByRequestId(@Param("requestId") requestId: UUID): List<EarthCellEntity>

    fun findByCellNum(cellNum: Long): Optional<EarthCellEntity>

    fun findAllByImportanceGreaterThanOrderByImportanceDesc(importance: Double): List<EarthCellEntity>

    @EntityGraph(attributePaths = ["requestProjections"])
    @Query("select distinct earthCell from EarthCellEntity earthCell where earthCell.importance > :importance order by earthCell.importance desc")
    fun findDetailedByImportanceGreaterThanOrderByImportanceDesc(@Param("importance") importance: Double): List<EarthCellEntity>

    @EntityGraph(attributePaths = ["requestProjections"])
    @Query("select earthCell from EarthCellEntity earthCell where earthCell.cellId = :cellId")
    fun findWithRequestProjectionsByCellId(@Param("cellId") cellId: Long): Optional<EarthCellEntity>

    @EntityGraph(attributePaths = ["requestProjections"])
    @Query("select earthCell from EarthCellEntity earthCell where earthCell.cellNum = :cellNum")
    fun findWithRequestProjectionsByCellNum(@Param("cellNum") cellNum: Long): Optional<EarthCellEntity>
}
