package com.evseminar.service;

import com.evseminar.dto.SeminarDTO;
import com.evseminar.dto.SeminarRequest;
import com.evseminar.exception.ResourceNotFoundException;
import com.evseminar.model.Seminar;
import com.evseminar.model.Vehicle;
import com.evseminar.repository.RegistrationRepository;
import com.evseminar.repository.SeminarRepository;
import com.evseminar.repository.VehicleRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

@Service
@RequiredArgsConstructor
public class SeminarService {

    private final SeminarRepository seminarRepository;
    private final RegistrationRepository registrationRepository;
    private final VehicleRepository vehicleRepository;

    public List<SeminarDTO> getUpcomingSeminars() {
        return seminarRepository.findBySeminarDateAfterOrderBySeminarDateAsc(LocalDateTime.now())
                .stream()
                .map(s -> {
                    int booked = registrationRepository.countBookedSeats(s.getSeminarId());
                    return SeminarDTO.from(s, booked);
                })
                .toList();
    }

    public SeminarDTO getSeminarById(Long id) {
        Seminar seminar = seminarRepository.findById(id)
                .orElseThrow(() -> new ResourceNotFoundException("Seminar not found"));
        int booked = registrationRepository.countBookedSeats(id);
        return SeminarDTO.from(seminar, booked);
    }

    public List<SeminarDTO> getAllSeminars() {
        return seminarRepository.findAll().stream()
                .map(s -> {
                    int booked = registrationRepository.countBookedSeats(s.getSeminarId());
                    return SeminarDTO.from(s, booked);
                })
                .toList();
    }

    @Transactional
    public SeminarDTO createSeminar(SeminarRequest request) {
        Vehicle vehicle = vehicleRepository.findById(request.getVehicleId())
                .orElseThrow(() -> new ResourceNotFoundException("Vehicle not found"));
        Seminar seminar = Seminar.builder()
                .vehicle(vehicle)
                .seminarDate(request.getSeminarDate())
                .venue(request.getVenue())
                .venueZh(request.getVenueZh())
                .maxSeats(request.getMaxSeats())
                .description(request.getDescription())
                .descriptionZh(request.getDescriptionZh())
                .speakerName(request.getSpeakerName())
                .speakerNameZh(request.getSpeakerNameZh())
                .language(request.getLanguage() != null ? request.getLanguage() : "Cantonese")
                .seminarType(request.getSeminarType() != null ? request.getSeminarType() : "IN_PERSON")
                .registrationDeadline(request.getRegistrationDeadline())
                .build();
        Seminar saved = seminarRepository.save(seminar);
        return SeminarDTO.from(saved, 0);
    }

    @Transactional
    public SeminarDTO updateSeminar(Long id, SeminarRequest request) {
        Seminar seminar = seminarRepository.findById(id)
                .orElseThrow(() -> new ResourceNotFoundException("Seminar not found"));
        Vehicle vehicle = vehicleRepository.findById(request.getVehicleId())
                .orElseThrow(() -> new ResourceNotFoundException("Vehicle not found"));
        seminar.setVehicle(vehicle);
        seminar.setSeminarDate(request.getSeminarDate());
        seminar.setVenue(request.getVenue());
        seminar.setVenueZh(request.getVenueZh());
        seminar.setMaxSeats(request.getMaxSeats());
        seminar.setDescription(request.getDescription());
        seminar.setDescriptionZh(request.getDescriptionZh());
        seminar.setSpeakerName(request.getSpeakerName());
        seminar.setSpeakerNameZh(request.getSpeakerNameZh());
        if (request.getLanguage() != null) seminar.setLanguage(request.getLanguage());
        if (request.getSeminarType() != null) seminar.setSeminarType(request.getSeminarType());
        seminar.setRegistrationDeadline(request.getRegistrationDeadline());
        int booked = registrationRepository.countBookedSeats(id);
        return SeminarDTO.from(seminarRepository.save(seminar), booked);
    }

    @Transactional
    public void deleteSeminar(Long id) {
        Seminar seminar = seminarRepository.findById(id)
                .orElseThrow(() -> new ResourceNotFoundException("Seminar not found"));
        seminar.setDeletedAt(LocalDateTime.now());
        seminarRepository.save(seminar);
    }
}
