package com.arms.api.issue.almapi.strategy;

import com.arms.api.issue.almapi.model.dto.AlmIssueIncrementDTO;
import com.arms.api.issue.almapi.model.entity.AlmIssueEntity;
import com.arms.api.issue.almapi.model.vo.AlmIssueVOCollection;
import com.arms.api.issue.almapi.service.AlmIssueToEntityConverter;
import com.arms.api.util.alm.AlmDiscoveryDate;
import com.arms.api.util.msa_communicate.DwrBackendCoreClient;
import com.arms.egovframework.javaservice.esframework.repository.common.EsCommonRepositoryWrapper;
import com.google.common.base.Function;
import jakarta.validation.Valid;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

@Component
@AllArgsConstructor
@Slf4j
public class IssueSaveTemplate {

    private final EsCommonRepositoryWrapper<AlmIssueEntity> esCommonRepositoryWrapper;

    private final AlmDiscoveryDate almDiscoveryDate;

    private final DwrBackendCoreClient dwrBackendCoreClient;

    public List<AlmIssueEntity> discoveryIncrementALmIssueAndGetReqAlmIssueEntities(
            @Valid AlmIssueIncrementDTO almIssueIncrementDTO,
            Function<AlmIssueIncrementDTO,AlmIssueVOCollection> discoveryIssueAndGetReqEntitiesFunction)  {

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

        log.info("almDiscoveryDate getStartDate: {} ", almDiscoveryDate.getStartDate());
        log.info("almDiscoveryDate getDateRange: {} ", almDiscoveryDate.getDateRange());

        LocalDate startDate = LocalDate.parse(Optional.ofNullable(almIssueIncrementDTO.getStartDate()).orElseGet(almDiscoveryDate::getStartDate), formatter);

        LocalDate endDate = LocalDate.parse(almIssueIncrementDTO.getEndDate(), formatter);

        LocalDate currentStart = startDate;

        List<AlmIssueEntity> requirementAlmIssueEntities = new ArrayList<>();

        while (!currentStart.isAfter(endDate)) {
            LocalDate currentEnd = currentStart.plusDays(almDiscoveryDate.getDateRange());
            if (currentEnd.isAfter(endDate)) {
                currentEnd = endDate;
            }

            AlmIssueIncrementDTO dynamicIncrementDto
                = AlmIssueIncrementDTO.builder()
                        .serverId(almIssueIncrementDTO.getServerId())
                        .projectKey(almIssueIncrementDTO.getProjectKey())
                        .startDate(String.valueOf(currentStart))
                        .endDate(String.valueOf(currentEnd))
                    .build();

            requirementAlmIssueEntities.addAll(
                discoveryIncrementALmIssueAndGetReqAlmIssueEntities(discoveryIssueAndGetReqEntitiesFunction.apply(dynamicIncrementDto))
            );

            currentStart = currentEnd.plusDays(1);
        }

        return requirementAlmIssueEntities;

    }

    private List<AlmIssueEntity> discoveryIncrementALmIssueAndGetReqAlmIssueEntities(AlmIssueVOCollection almIssueVOCollection)  {

        List<AlmIssueEntity> requirementAlmIssueEntities
                = AlmIssueToEntityConverter.discoveryRequirementIssue(almIssueVOCollection).almIssueEntities();

        saveEntities(requirementAlmIssueEntities);

        List<AlmIssueEntity> noneRequirementAlmIssueEntities
                = AlmIssueToEntityConverter.discoveryNoneRequirementIssue(almIssueVOCollection).almIssueEntities();

        saveEntities(noneRequirementAlmIssueEntities);

        return requirementAlmIssueEntities;

    }

    private void saveEntities(List<AlmIssueEntity> almIssueList) {
        almIssueList.forEach(esCommonRepositoryWrapper::save);

        List<AlmIssueEntity> almIssueEntities = almIssueList.stream().filter(a->a.izReqFalse()&&a.getKey()!=null).toList();

        for (AlmIssueEntity almIssueEntity : almIssueEntities) {

            AlmIssueEntity almIssueEntityByUpperKey = esCommonRepositoryWrapper.findRecentDocByRecentId(almIssueEntity.recentIdByNewKey(almIssueEntity.getUpperKey()));
            while(almIssueEntity.isNeedOverallUpdatedDate(almIssueEntityByUpperKey)){
                almIssueEntityByUpperKey.setOverallUpdatedDate(almIssueEntity.getOverallUpdatedDate());
                esCommonRepositoryWrapper.save(almIssueEntityByUpperKey);
                almIssueEntityByUpperKey = esCommonRepositoryWrapper.findRecentDocByRecentId(almIssueEntityByUpperKey.recentIdByNewKey(almIssueEntityByUpperKey.getUpperKey()));
            }
        }
    }

}
