package org.egl_cepgl.pm.service;

import lombok.extern.slf4j.Slf4j;
import org.egl_cepgl.pm.dto.*;
import org.egl_cepgl.pm.exception.EntityNotFoundException;
import org.egl_cepgl.pm.model.Applicant;
import org.egl_cepgl.pm.model.Enterprise;
import org.egl_cepgl.pm.model.Procurement;
import org.egl_cepgl.pm.repository.ApplicantRepository;
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.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

@Slf4j
@Service
public class ApplicantService {

    private ApplicantRepository applicantRepository;
    private ProcurementRepository procurementRepository;

    @Autowired
    public ApplicantService(ApplicantRepository applicantRepository, ProcurementRepository procurementRepository) {
        this.applicantRepository = applicantRepository;
        this.procurementRepository= procurementRepository;
    }

    public Applicant save(Applicant obj, Long procurement_id)
    {
        Applicant applicant= this.applicantRepository.save(obj);
        if(procurement_id != null){
            Procurement procurement_s= this.procurementRepository.findById(procurement_id).get();
            procurement_s.getApplicants().add(applicant);
            this.procurementRepository.save(procurement_s);
        }
        return applicant;
    }

    public Page<Applicant> findAll(String search, int page, int size, Boolean dateRange, Date bdate, Date edate)
    {
        Pageable paging = PageRequest.of(page, size);
        Page<Applicant> pageApplicants;
        if (search == null && bdate == null) {
            pageApplicants = this.applicantRepository.findAll(paging);
        } else {
            SimpleDateFormat fd= new SimpleDateFormat("YYYY-MM-dd");
            if(dateRange == null)
                pageApplicants = this.applicantRepository.findAllByFilters(search, paging);
            else{
                if(edate == null)
                    pageApplicants = this.applicantRepository.findAllByFilters2(search, paging, fd.format(bdate));
                else
                    pageApplicants = this.applicantRepository.findAllByFilters3(search, paging, fd.format(bdate), fd.format(edate));
            }
        }
        return pageApplicants;
    }

    public List<Map<String, Object>> findAllApplicantNames(Long procurement_id)
    {
        if(procurement_id != 0){
            return this.applicantRepository.findAllApplicantNamesByProcurement(procurement_id);
        }
        return this.applicantRepository.findAllApplicantNames();
    }

    public Optional<ApplicantDto> findApplicantById(Long id)
    {
        return Optional.ofNullable(ApplicantDto.fromEntity(this.applicantRepository.findById(id).orElseThrow(() -> {
            throw new EntityNotFoundException("L'Applicant avec cet ID est introuvableé");
        })));
    }

    public Optional<ApplicantDto> findApplicantByEmail(String email)
    {
        return Optional.ofNullable(ApplicantDto.fromEntity(this.applicantRepository.findByEmail(email).orElseThrow(() -> {
            throw new EntityNotFoundException("L'Applicant avec cet email est introuvableé");
        })));
    }

    public List<FileDto> findAllFilesByApplicantId(Long id)
    {
        List<FileDto> files = new ArrayList<>();
        Optional<Applicant> applicant= applicantRepository.findById(id);
        if(applicant.isPresent()){
            files= applicant.get().getFiles().stream().map(FileDto::fromEntity).collect(Collectors.toList());
        }
        return files;
    }

    public Applicant update(Applicant obj, Long procurement_id)
    {
        Applicant applicant= this.applicantRepository.save(obj);
        if(procurement_id != null){
            Procurement procurement_s= this.procurementRepository.findById(procurement_id).get();
            procurement_s.getApplicants().add(applicant);
            this.procurementRepository.save(procurement_s);
        }
        return applicant;
    }

    public void delete(Long id)
    {
        if(id == null){
            log.error("ID est null");
            return;
        }
        applicantRepository.deleteById(id);
    }

    public Boolean existsByCode(String email)
    {
        if(applicantRepository.existsByEmail(email)){
            return true;
        }
        return false;
    }

    public Applicant changeStatus(Applicant obj)
    {
        return applicantRepository.changeStatus(obj.getId(), obj.getStatus());
    }
}
