package org.egl_cepgl.pm.service;

import lombok.extern.slf4j.Slf4j;
import org.egl_cepgl.pm.dto.CabinetDto;
import org.egl_cepgl.pm.dto.FileDto;
import org.egl_cepgl.pm.exception.EntityNotFoundException;
import org.egl_cepgl.pm.model.Cabinet;
import org.egl_cepgl.pm.model.Procurement;
import org.egl_cepgl.pm.model.ValidateEmail;
import org.egl_cepgl.pm.repository.CabinetRepository;
import org.egl_cepgl.pm.repository.ProcurementRepository;
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.stereotype.Service;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class CabinetService
{
    private CabinetRepository repository;
    private ProcurementRepository procurementRepository;

    @Autowired
    public CabinetService(CabinetRepository repository, ProcurementRepository procurementRepository) {
        this.repository = repository;
        this.procurementRepository= procurementRepository;
    }

    public Cabinet save(Cabinet obj, Long procurement_id)
    {
        Cabinet cabinet= this.repository.save(obj);
        if(procurement_id != null){
            Procurement procurement_s= this.procurementRepository.findById(procurement_id).get();
            procurement_s.getCabinets().add(cabinet);
            this.procurementRepository.save(procurement_s);
        }
        return repository.save(cabinet);
    }

    public Page<Cabinet> findAll(String search, int page, int size, Boolean dateRange, Date bdate, Date edate)
    {
        Pageable paging = PageRequest.of(page, size);
        Page<Cabinet> objs = null;
        if (search == null && bdate == null) {
            objs = this.repository.findAll(paging);
        }else{
            SimpleDateFormat fd= new SimpleDateFormat("YYYY-MM-dd");
            if(bdate == null && search != null)
                objs = this.repository
                        .findAllByCountry_NamepContainingIgnoreCaseOrNamepContainingIgnoreCaseOrQualification_NamepContainingIgnoreCase(search, search, search, paging);
            else{
                if(bdate !=null && edate == null && search == null){
                    LocalDate lbdate= LocalDate.parse(fd.format(bdate));
                    log.info(lbdate.toString());
                    objs = this.repository.findAllByCreatedatEquals(lbdate, paging);
                }else if(bdate !=null && edate != null && search == null){
                    LocalDate lbdate= LocalDate.parse(fd.format(bdate));
                    LocalDate ledate= LocalDate.parse(fd.format(edate));
                    objs = this.repository.findAllByCreatedatBetween(lbdate, ledate, paging);
                }else if(bdate != null && edate != null && search != null){
                    LocalDate lbdate= LocalDate.parse(fd.format(bdate));
                    LocalDate ledate= LocalDate.parse(fd.format(edate));
                    objs = this.repository
                            .findAllByCountry_NamepContainingIgnoreCaseOrNamepContainingIgnoreCaseOrQualification_NamepContainingIgnoreCaseOrCreatedatBetween(search, search, search, lbdate, ledate, paging);
                }else if(bdate != null && edate == null && search != null){
                    LocalDate lbdate= LocalDate.parse(fd.format(bdate));
                    objs = this.repository
                            .findAllByCountry_NamepContainingIgnoreCaseOrNamepContainingIgnoreCaseOrQualification_NamepContainingIgnoreCaseOrCreatedatEquals(search, search, search, lbdate, paging);
                }
            }
        }
        return objs;
    }

    public List<Map<String, Object>> findAllCabinetNames(Long procurement_id)
    {
        if(procurement_id != 0){
            return this.repository.findAllCabinetNamesByProcurement(procurement_id);
        }
        return this.repository.findAllCabinetNames();
    }

    public List<Map<String, Object>> findAllCabinetNamesNotInUser()
    {
        return this.repository.findAllCabinetNamesNotInUser();
    }

    public Optional<CabinetDto> findCabinetById(Long id)
    {
        return Optional.ofNullable(CabinetDto.fromEntity(this.repository.findById(id).orElseThrow(() -> {
            throw new EntityNotFoundException("Le Cabinet avec cet ID est introuvableé");
        })));
    }

    public Optional<CabinetDto> findCabinetByEmail(String email)
    {
        return Optional.ofNullable(CabinetDto.fromEntity(this.repository.findByEmail(email).orElseThrow(() -> {
            throw new EntityNotFoundException("Le Cabinet avec cet email est introuvableé");
        })));
    }

    public List<FileDto> findAllFilesByCabinetId(Long id)
    {
        List<FileDto> files = new ArrayList<>();
        Optional<Cabinet> cabinet= repository.findById(id);
        if(cabinet.isPresent()){
            files= cabinet.get().getFiles().stream().map(FileDto::fromEntity).collect(Collectors.toList());
        }
        return files;
    }

    public Cabinet update(Cabinet obj)
    {
        return this.repository.save(obj);
    }

    public void delete(Long id)
    {
        if(id == null){
            log.error("ID est null");
            return;
        }
        repository.deleteById(id);
    }

    public Boolean existsByEmail(ValidateEmail obj)
    {
        if(obj.getId() != null){
            Boolean res= repository.existsByEmailAndIdNot(obj.getEmail(), obj.getId());
            if(res) return true;
        }else
        if(repository.existsByEmail(obj.getEmail())) return true;
        return false;
    }

    public Cabinet changeStatus(Cabinet obj)
    {
        return repository.changeStatus(obj.getId(), obj.getStatus());
    }
}
