package com.petshop.backend.service;

import com.petshop.backend.dto.common.BulkDeleteRequest;
import com.petshop.backend.dto.common.CouponRequest;
import com.petshop.backend.dto.common.CouponResponse;
import com.petshop.backend.entity.Coupon;
import com.petshop.backend.exception.ResourceNotFoundException;
import com.petshop.backend.repository.CouponRepository;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class CouponService {

    private final CouponRepository couponRepository;

    public CouponService(CouponRepository couponRepository) {
        this.couponRepository = couponRepository;
    }

    public Page<CouponResponse> getAllCoupons(String query, Boolean active, Pageable pageable) {
        return couponRepository.searchCoupons(query, active, pageable).map(this::mapToResponse);
    }

    public CouponResponse getCouponById(Long id) {
        Coupon coupon = couponRepository.findById(id)
                .orElseThrow(() -> new ResourceNotFoundException("Coupon not found with id: " + id));
        return mapToResponse(coupon);
    }

    public CouponResponse getCouponByCode(String code) {
        Coupon coupon = couponRepository.findByCouponCode(code)
                .orElseThrow(() -> new ResourceNotFoundException("Coupon not found with code: " + code));
        return mapToResponse(coupon);
    }

    @Transactional
    public CouponResponse createCoupon(CouponRequest request) {
        if (couponRepository.findByCouponCode(request.getCouponCode()).isPresent()) {
            throw new IllegalArgumentException("Coupon code already exists: " + request.getCouponCode());
        }

        Coupon coupon = new Coupon();
        updateCouponFields(coupon, request);
        coupon = couponRepository.save(coupon);
        return mapToResponse(coupon);
    }

    @Transactional
    public CouponResponse updateCoupon(Long id, CouponRequest request) {
        Coupon coupon = couponRepository.findById(id)
                .orElseThrow(() -> new ResourceNotFoundException("Coupon not found with id: " + id));

        couponRepository.findByCouponCode(request.getCouponCode()).ifPresent(existing -> {
            if (!existing.getCouponId().equals(id)) {
                throw new IllegalArgumentException("Coupon code already exists: " + request.getCouponCode());
            }
        });

        updateCouponFields(coupon, request);
        coupon = couponRepository.save(coupon);
        return mapToResponse(coupon);
    }

    @Transactional
    public void deleteCoupon(Long id) {
        if (!couponRepository.existsById(id)) {
            throw new ResourceNotFoundException("Coupon not found with id: " + id);
        }
        couponRepository.deleteById(id);
    }

    @Transactional
    public void bulkDeleteCoupons(BulkDeleteRequest request) {
        couponRepository.deleteAllById(request.getIds());
    }

    private void updateCouponFields(Coupon coupon, CouponRequest request) {
        coupon.setCouponCode(request.getCouponCode());
        coupon.setDiscountType(request.getDiscountType());
        coupon.setDiscountValue(request.getDiscountValue());
        coupon.setMinOrderAmount(request.getMinOrderAmount());
        coupon.setActive(request.getActive());
        coupon.setStartsAt(request.getStartsAt());
        coupon.setEndsAt(request.getEndsAt());
        coupon.setUsageLimit(request.getUsageLimit());
    }

    private CouponResponse mapToResponse(Coupon coupon) {
        return new CouponResponse(
                coupon.getCouponId(),
                coupon.getCouponCode(),
                coupon.getDiscountType(),
                coupon.getDiscountValue(),
                coupon.getMinOrderAmount(),
                coupon.getActive(),
                coupon.getStartsAt(),
                coupon.getEndsAt(),
                coupon.getUsageLimit(),
                coupon.getCreatedAt(),
                coupon.getUpdatedAt()
        );
    }
}
