package com.petshop.backend.repository;

import com.petshop.backend.entity.Pet;
import jakarta.persistence.LockModeType;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Lock;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Optional;

@Repository
public interface PetRepository extends JpaRepository<Pet, Long> {

    List<Pet> findAllByPetStatusIgnoreCaseOrderByPetNameAsc(String petStatus);
    @Query("SELECT p FROM Pet p " +
           "WHERE LOWER(p.petStatus) = 'available' " +
           "AND NOT EXISTS (" +
           "    SELECT 1 FROM Adoption a " +
           "    WHERE a.pet = p AND (LOWER(a.adoptionStatus) = 'completed' OR LOWER(a.adoptionStatus) = 'pending')" +
           ") " +
           "ORDER BY p.petName ASC")
    List<Pet> findAdoptablePetsOrderByPetNameAsc();

    @Query("SELECT p FROM Pet p " +
           "WHERE LOWER(p.petStatus) = 'available' " +
           "AND (:storeId IS NULL OR p.store.storeId = :storeId) " +
           "AND NOT EXISTS (" +
           "    SELECT 1 FROM Adoption a " +
           "    WHERE a.pet = p AND (LOWER(a.adoptionStatus) = 'completed' OR LOWER(a.adoptionStatus) = 'pending')" +
           ") " +
           "ORDER BY p.petName ASC")
    List<Pet> findAdoptablePetsByStore(@Param("storeId") Long storeId);

    List<Pet> findAllByOwner_IdOrderByPetNameAsc(Long ownerId);
    List<Pet> findAllByOwner_IdAndPetStatusInOrderByPetNameAsc(Long ownerId, List<String> statuses);
    Optional<Pet> findByIdAndOwner_Id(Long id, Long ownerId);

    @Lock(LockModeType.PESSIMISTIC_WRITE)
    @Query("SELECT p FROM Pet p WHERE p.petId = :id")
    Optional<Pet> findByIdForUpdate(@Param("id") Long id);

    @Query("SELECT p FROM Pet p WHERE " +
           "(:q IS NULL OR LOWER(p.petName) LIKE LOWER(CONCAT('%', :q, '%')) OR LOWER(p.petSpecies) LIKE LOWER(CONCAT('%', :q, '%')) OR LOWER(COALESCE(p.petBreed, '')) LIKE LOWER(CONCAT('%', :q, '%'))) AND " +
           "(:species IS NULL OR LOWER(p.petSpecies) = LOWER(:species)) AND " +
           "(:breed IS NULL OR LOWER(COALESCE(p.petBreed, '')) = LOWER(:breed)) AND " +
           "(:status IS NULL OR LOWER(p.petStatus) = LOWER(:status)) AND " +
           "(:storeId IS NULL OR p.store.storeId = :storeId) AND " +
           "(:customerId IS NULL OR p.owner.id = :customerId)")
    Page<Pet> searchPets(@Param("q") String query, @Param("species") String species, @Param("breed") String breed, @Param("status") String status, @Param("storeId") Long storeId, @Param("customerId") Long customerId, Pageable pageable);

    @Query("SELECT p FROM Pet p WHERE LOWER(p.petStatus) = 'available' AND " +
           "(:q IS NULL OR LOWER(p.petName) LIKE LOWER(CONCAT('%', :q, '%')) OR LOWER(p.petSpecies) LIKE LOWER(CONCAT('%', :q, '%')) OR LOWER(COALESCE(p.petBreed, '')) LIKE LOWER(CONCAT('%', :q, '%'))) AND " +
           "(:species IS NULL OR LOWER(p.petSpecies) = LOWER(:species)) AND " +
           "(:breed IS NULL OR LOWER(COALESCE(p.petBreed, '')) = LOWER(:breed)) AND " +
           "(:storeId IS NULL OR p.store.storeId = :storeId)")
    Page<Pet> searchPublicPets(@Param("q") String query, @Param("species") String species, @Param("breed") String breed, @Param("storeId") Long storeId, Pageable pageable);

    @Query("SELECT DISTINCT p FROM Pet p LEFT JOIN Adoption a ON a.pet = p AND LOWER(a.adoptionStatus) = 'completed' WHERE " +
           "(LOWER(p.petStatus) = 'available' OR a.customer.id = :userId OR (LOWER(p.petStatus) = 'owned' AND p.owner.id = :userId)) AND " +
           "(:q IS NULL OR LOWER(p.petName) LIKE LOWER(CONCAT('%', :q, '%')) OR LOWER(p.petSpecies) LIKE LOWER(CONCAT('%', :q, '%')) OR LOWER(COALESCE(p.petBreed, '')) LIKE LOWER(CONCAT('%', :q, '%'))) AND " +
           "(:species IS NULL OR LOWER(p.petSpecies) = LOWER(:species)) AND " +
           "(:breed IS NULL OR LOWER(COALESCE(p.petBreed, '')) = LOWER(:breed)) AND " +
           "(:status IS NULL OR LOWER(p.petStatus) = LOWER(:status))")
    Page<Pet> searchCustomerVisiblePets(@Param("userId") Long userId, @Param("q") String query, @Param("species") String species, @Param("breed") String breed, @Param("status") String status, Pageable pageable);
}
