package com.bytesw.bytebot.service;

import com.bytesw.bytebot.bean.*;
import com.bytesw.bytebot.model.*;
import com.bytesw.bytebot.model.enums.AgentStatusEnum;
import com.bytesw.bytebot.repository.PassengerRepository;
import com.bytesw.bytebot.repository.ProxyRepository;
import com.bytesw.bytebot.repository.ReservationRepository;
import com.bytesw.xdf.exception.NotFoundException;
import com.bytesw.xdf.service.XDFService;
import com.bytesw.xdf.sql.beans.Pagination;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service
@Transactional
public class ReservationService extends CustomPaginationService<Reservation> {
    @Autowired
    private ReservationRepository reservationRepository;

    @Autowired
    private ProxyRepository proxyRepository;

    @Autowired
    private PassengerRepository passengerRepository;


    public void create(ReservationBean bean) {
        Optional<Proxy> proxy = this.proxyRepository.findById(bean.getProxyId());
        Optional<Passenger> passenger = this.passengerRepository.findById(bean.getPassengerId());
        if (!proxy.isPresent()) {
            throw new NotFoundException();
        }
        if (!passenger.isPresent()) {
            throw new NotFoundException();
        }
        Reservation model = new Reservation();
        model.setProxy(proxy.get());
        model.setPassenger(passenger.get());
        model.setNumberInParty(bean.getNumberInParty());
        model.setTravelTypeClass(bean.getTravelTypeClass());
        this.reservationRepository.save(model);
    }

    public void update(ReservationBean bean, Long id) {
        Optional<Reservation> found = this.reservationRepository.findById(id);
        if (!found.isPresent()) {
            throw new NotFoundException();
        }
        Optional<Proxy> proxy = this.proxyRepository.findById(bean.getProxyId());
        Optional<Passenger> passenger = this.passengerRepository.findById(bean.getPassengerId());
        if (!proxy.isPresent()) {
            throw new NotFoundException();
        }
        if (!passenger.isPresent()) {
            throw new NotFoundException();
        }
        Reservation model = found.get();
        model.setProxy(proxy.get());
        model.setPassenger(passenger.get());
        model.setNumberInParty(bean.getNumberInParty());
        model.setTravelTypeClass(bean.getTravelTypeClass());
        this.reservationRepository.save(model);
    }

    public void delete(Long id) {
        Optional<Reservation> found = this.reservationRepository.findById(id);
        if (!found.isPresent()) {
            throw new NotFoundException();
        }
        this.reservationRepository.delete(found.get());
    }

    public ReservationBean getReservation(Long id) {
        Optional<Reservation> found = reservationRepository.findById(id);

        if (!found.isPresent()) {
            throw new NotFoundException();
        }
        ReservationBean bean = new ReservationBean();
        bean.setId(found.get().getId());
        bean.setPassengerId(found.get().getPassenger().getId());
        bean.setProxyId(found.get().getProxy().getId());
        bean.setProxyName(found.get().getProxy().getName());
        bean.setPassengerName(found.get().getPassenger().getFirstName() + ' ' + found.get().getPassenger().getLastName());
        bean.setTravelTypeClass(found.get().getTravelTypeClass());
        bean.setNumberInParty(found.get().getNumberInParty());
        return bean;
    }

    public List<Reservation> getReservationAll() {
        List<Reservation> list = this.reservationRepository.findAll();
        if (list.isEmpty()) {
            throw new NotFoundException("Error al listar reservas.");
        }
        return list;
    }

    public void searchByPagination(Pagination<ReservationBean> pagination) {
        if (pagination.getItemsPerPage() == 0) {
            pagination.setItemsPerPage(10);
        }

        Sort sort = null;
        if (pagination.getSortFields() != null) {
            sort = createSort(pagination);
        }

        Pageable pageable = null;
        if (sort != null) {
            pageable = PageRequest.of(pagination.getCurrentPage(), pagination.getItemsPerPage(), sort);
        } else {
            pageable = PageRequest.of(pagination.getCurrentPage(), pagination.getItemsPerPage());
        }

        Specification<Reservation> specification = (Specification<Reservation>) (root, query, criteriaBuilder)
                -> criteriaBuilder.notEqual(root.get("id"), 0);

        if (pagination.getFilterExpression() != null && pagination.getFilterExpression().length() > 0) {
            specification = createSpecification(pagination.getFilterExpression()).and(specification);
        }

        Page<Reservation> page = reservationRepository.findAll(specification, pageable);

        pagination.setTotalItems(page.getTotalElements());
        pagination.setTotalPages(page.getTotalPages());

        // Clone to array
        List<ReservationBean> list = new ArrayList<>();

        for (Reservation reservation: page.getContent()) {
            list.add(ReservationBean.miniClone(reservation));
        }

        pagination.setData(list);
    }
}
