package com.mvrent.carrental.service;

import com.mvrent.carrental.model.*;
import com.mvrent.carrental.repository.*;
import lombok.RequiredArgsConstructor;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;

@Service
@RequiredArgsConstructor
public class VendorService {

    private final VendorRepository vendorRepository;
    private final UserRepository userRepository;
    private final CarRepository carRepository;
    private final DriverRepository driverRepository;
    private final BookingRepository bookingRepository;
    private final CommissionService commissionService;
    private final PasswordEncoder passwordEncoder;

    public List<Vendor> findAll() {
        return vendorRepository.findAllByOrderByName();
    }

    public List<Vendor> findActive() {
        return vendorRepository.findByActiveTrueOrderByName();
    }

    public Vendor findById(Long id) {
        return vendorRepository.findById(id)
                .orElseThrow(() -> new IllegalArgumentException("Vendor not found: " + id));
    }

    @Transactional
    public Vendor save(Vendor vendor) {
        return vendorRepository.save(vendor);
    }

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

    /* ---------- Portal login ---------- */

    @Transactional
    public User createPortalUser(Long vendorId, String username, String email, String rawPassword) {
        Vendor vendor = findById(vendorId);
        if (userRepository.existsByUsername(username)) {
            throw new IllegalArgumentException("Username already taken");
        }
        if (userRepository.existsByEmail(email)) {
            throw new IllegalArgumentException("Email already registered");
        }
        User user = User.builder()
                .username(username)
                .email(email)
                .password(passwordEncoder.encode(rawPassword))
                .fullName(vendor.getName() + " (Vendor)")
                .role(Role.VENDOR)
                .vendor(vendor)
                .enabled(true)
                .build();
        return userRepository.save(user);
    }

    /* ---------- Scoped views ---------- */

    public List<Car> cars(Long vendorId) {
        return carRepository.findByVendorIdOrderByMake(vendorId);
    }

    public List<Driver> drivers(Long vendorId) {
        return driverRepository.findByVendorIdOrderByName(vendorId);
    }

    public List<Booking> trips(Long vendorId) {
        return bookingRepository.findByCarVendorIdOrderByCreatedAtDesc(vendorId);
    }

    /** Gross revenue, commission deducted and net payable across a vendor's trips. */
    public VendorRevenue revenue(Long vendorId) {
        List<Booking> trips = trips(vendorId);
        BigDecimal gross = BigDecimal.ZERO;
        BigDecimal commission = BigDecimal.ZERO;
        for (Booking b : trips) {
            // Gross = rental (vehicle) revenue; fall back to total for pre-breakdown bookings.
            BigDecimal base = b.getVehicleCharge() != null ? b.getVehicleCharge()
                    : (b.getTotalAmount() == null ? BigDecimal.ZERO : b.getTotalAmount());
            BigDecimal comm = b.getCommissionAmount() != null ? b.getCommissionAmount()
                    : commissionService.commissionAmount(b.getCar(), base);
            gross = gross.add(base);
            commission = commission.add(comm);
        }
        return new VendorRevenue(trips.size(), gross, commission, gross.subtract(commission));
    }
}
