package com.petshop.backend.repository;

import com.petshop.backend.entity.Sale;
import jakarta.persistence.LockModeType;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import java.time.LocalDateTime;
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 SaleRepository extends JpaRepository<Sale, Long> {

    @Query("SELECT s FROM Sale s WHERE " +
           "(:q IS NULL OR (" +
           "LOWER(s.employee.firstName) LIKE LOWER(CONCAT('%', :q, '%')) OR " +
           "LOWER(s.employee.lastName) LIKE LOWER(CONCAT('%', :q, '%')) OR " +
           "LOWER(s.store.storeName) LIKE LOWER(CONCAT('%', :q, '%'))" +
           ")) AND " +
           "(:paymentMethod IS NULL OR LOWER(s.paymentMethod) = LOWER(:paymentMethod)) AND " +
           "(:isRefund IS NULL OR s.isRefund = :isRefund) AND " +
           "(:storeId IS NULL OR s.store.storeId = :storeId) AND " +
           "(:customerId IS NULL OR s.customer.id = :customerId)")
    Page<Sale> searchSales(@Param("q") String query, @Param("paymentMethod") String paymentMethod, @Param("storeId") Long storeId, @Param("isRefund") Boolean isRefund, @Param("customerId") Long customerId, Pageable pageable);

    long countByCoupon_CouponId(Long couponId);

    @Query("SELECT s FROM Sale s WHERE s.saleDate > :startDate " +
           "AND (:endDate IS NULL OR s.saleDate <= :endDate) " +
           "AND (:paymentMethod IS NULL OR LOWER(s.paymentMethod) = LOWER(:paymentMethod)) " +
           "AND (:storeId IS NULL OR s.store.storeId = :storeId) " +
           "AND (:channel IS NULL OR s.channel = :channel)")
    List<Sale> findForAnalytics(@Param("startDate") LocalDateTime startDate,
                                @Param("endDate") LocalDateTime endDate,
                                @Param("paymentMethod") String paymentMethod,
                                @Param("storeId") Long storeId,
                                @Param("channel") String channel);

    List<Sale> findByOriginalSaleSaleId(Long originalSaleId);

    @Lock(LockModeType.PESSIMISTIC_WRITE)
    @Query("SELECT s FROM Sale s WHERE s.saleId = :id")
    Optional<Sale> findByIdForUpdate(@Param("id") Long id);

    Optional<Sale> findByCartCartId(Long cartId);
}
