package ru.soune.nocopy.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import ru.soune.nocopy.entity.file.FileEntity;

import java.util.List;
import java.util.Set;

@Repository
public interface ImageSimilarityRepository
        extends JpaRepository<FileEntity, String> {
    @Query(value = """
        SELECT
            f.id AS id,
            f.original_file_name AS originalFileName,
            f.file_size AS fileSize,
            f.user_id AS userId,
            f.support_id AS supportId,
            f.created_at AS uploadDate,
            f.protection_status AS protectionStatus,
            f.file_extension AS extension,
            f.status AS fileStatus,
            h.hash64_hi AS hash64Hi,
            h.hash64_lo AS hash64Lo
        FROM image_hashes ref
        JOIN image_hashes h
            ON ref.file_id <> h.file_id
        JOIN file_entities f
            ON f.id = h.file_id
        WHERE ref.file_id = :fileId
        AND f.status IN ('ACTIVE', 'MODERATION')
        """,
            nativeQuery = true)
    List<SimilarImageProjection> findCandidates(
            @Param("fileId") String fileId
    );

    @Query(value = """
        SELECT
            f.id AS id,
            f.original_file_name AS originalFileName,
            f.file_size AS fileSize,
            f.user_id AS userId,
            f.support_id AS supportId,
            f.created_at AS uploadDate,
            f.protection_status AS protectionStatus,
            f.file_extension AS extension,
            h.hash64_hi AS hash64Hi,
            h.hash64_lo AS hash64Lo
        FROM image_hashes ref
        JOIN image_hashes h
            ON ref.file_id <> h.file_id
        JOIN file_entities f
            ON f.id = h.file_id
        WHERE ref.file_id = :fileId AND f.user_id = :userId
        AND (f.status = 'ACTIVE' OR f.status = 'MODERATION')
        """,
            nativeQuery = true)
    List<SimilarImageProjection> findCandidatesFromUserFiles(
            @Param("fileId") String fileId,
            @Param("userId") Long userId
    );

    @Query(value = """
        SELECT
            f.id AS id,
            f.original_file_name AS originalFileName,
            f.file_size AS fileSize,
            f.user_id AS userId,
            f.support_id AS supportId,
            f.created_at AS uploadDate,
            f.protection_status AS protectionStatus,
            f.file_extension AS extension,
            h.hash64_hi AS hash64Hi,
            h.hash64_lo AS hash64Lo
        FROM image_hashes ref
        JOIN image_hashes h
            ON ref.file_id <> h.file_id
        JOIN file_entities f
            ON f.id = h.file_id
        WHERE ref.file_id = :fileId AND f.user_id IN :userIds
        AND (f.status = 'ACTIVE' OR f.status = 'MODERATION')
        """,
            nativeQuery = true)
    List<SimilarImageProjection> findCandidatesFromUserFiles(
            @Param("fileId") String fileId,
            @Param("userIds") Set<Long> userIds
    );


    @Query(value = """
    SELECT
        h.hash64_hi AS hash64Hi,
        h.hash64_lo AS hash64Lo,
        h.file_id AS fileId,
        f.user_id AS userId,
        f.original_file_name AS originalFileName,
        f.file_size AS fileSize,
        f.stored_file_name AS similarFileId,
        f.support_id AS supportId,
        f.created_at AS uploadDate,
        f.file_extension AS extension,
        f.protection_status AS protectionStatus
    FROM image_hashes h
    JOIN file_entities f ON f.id = h.file_id
    WHERE h.hash64_hi = :hash64Hi
      AND h.hash64_lo = :hash64Lo
    AND (f.status = 'ACTIVE' OR f.status = 'MODERATION')
    """,
            nativeQuery = true)
    List<SimilarImageProjection> findExactDuplicates(
            @Param("hash64Hi") Long hash64_hi,
            @Param("hash64Lo") Long hash64_lo);

    @Query(value = """
    SELECT
        h.hash64_hi AS hash64Hi,
        h.hash64_lo AS hash64Lo,
        h.file_id AS fileId,
        f.user_id AS userId,
        f.original_file_name AS originalFileName,
        f.file_size AS fileSize,
        f.stored_file_name AS similarFileId,
        f.support_id AS supportId,
        f.created_at AS uploadDate,
        f.file_extension AS extension,
        f.protection_status AS protectionStatus
    FROM image_hashes h
    JOIN file_entities f ON f.id = h.file_id
    WHERE h.hash64_hi = :hash64Hi
      AND h.hash64_lo = :hash64Lo
    AND (f.status = 'TEMP')
    """,
            nativeQuery = true)
    List<SimilarImageProjection> findExactDuplicatesTemp(
            @Param("hash64Hi") Long hash64_hi,
            @Param("hash64Lo") Long hash64_lo);
}

