package com.mvrent.carrental.service;

import com.mvrent.carrental.model.Booking;
import com.mvrent.carrental.model.Payment;
import com.mvrent.carrental.model.PaymentMethod;
import com.mvrent.carrental.repository.PaymentRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@RequiredArgsConstructor
public class PaymentService {

    private final PaymentRepository paymentRepository;
    private final BookingService bookingService;

    public List<Payment> forBooking(Long bookingId) {
        return paymentRepository.findByBookingIdOrderByPaidAtDescIdDesc(bookingId);
    }

    public BigDecimal totalPaid(Long bookingId) {
        BigDecimal sum = paymentRepository.sumForBooking(bookingId);
        return sum == null ? BigDecimal.ZERO : sum;
    }

    /** bookingId -> total paid, for the whole bookings list in one query. */
    public Map<Long, BigDecimal> paidByBooking() {
        Map<Long, BigDecimal> map = new HashMap<>();
        for (Object[] row : paymentRepository.sumGroupedByBooking()) {
            map.put((Long) row[0], (BigDecimal) row[1]);
        }
        return map;
    }

    @Transactional
    public Payment record(Long bookingId, BigDecimal amount, PaymentMethod method,
                          String reference, LocalDate paidAt, String notes) {
        if (amount == null || amount.signum() <= 0) {
            throw new IllegalArgumentException("Amount must be greater than zero");
        }
        Booking booking = bookingService.findById(bookingId);
        String user = SecurityContextHolder.getContext().getAuthentication() != null
                ? SecurityContextHolder.getContext().getAuthentication().getName() : null;
        Payment payment = Payment.builder()
                .booking(booking)
                .amount(amount)
                .method(method != null ? method : PaymentMethod.CASH)
                .reference(reference)
                .paidAt(paidAt != null ? paidAt : LocalDate.now())
                .notes(notes)
                .recordedBy(user)
                .build();
        return paymentRepository.save(payment);
    }

    @Transactional
    public void delete(Long id) {
        paymentRepository.deleteById(id);
    }
}
