package com.arms.api.issue.schedule.service;

import com.arms.api.issue.almapi.model.dto.AlmIssueIncrementDTO;
import com.arms.api.issue.almapi.model.dto.AlmIssueWithRequirementDTO;
import com.arms.api.issue.almapi.model.vo.AlmIssueWithRequirementVO;
import com.arms.api.issue.almapi.model.entity.AlmIssueEntity;
import com.arms.api.issue.almapi.service.CategoryMappingService;
import com.arms.api.issue.almapi.service.IssueService;
import com.arms.api.serverinfo.model.vo.ServerInfoVO;
import com.arms.api.serverinfo.model.enums.ServerType;
import com.arms.api.serverinfo.service.ServerInfoService;
import com.arms.api.util.UUIDUtil;
import com.arms.api.util.aspect.DwrSendAlarm;
import com.arms.api.util.aspect.SlackSendAlarm;
import com.arms.egovframework.javaservice.esframework.model.dto.esquery.SortDTO;
import com.arms.egovframework.javaservice.esframework.repository.common.EsCommonRepositoryWrapper;
import com.arms.egovframework.javaservice.esframework.esquery.SimpleQuery;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

@Slf4j
@Service("issueScheduleService")
@AllArgsConstructor
@Validated
public class IssueScheduleServiceImpl implements IssueScheduleService {

    private final IssueService issueService;

    private final CategoryMappingService categoryMappingService;

    private final ServerInfoService serverInfoService;

    private final EsCommonRepositoryWrapper<AlmIssueEntity> esCommonRepositoryWrapper;

    @Override
    public List<AlmIssueEntity> discoveryIncrementALmIssue(AlmIssueIncrementDTO almIssueIncrementDTO) {
        return issueService.discoveryIncrementALmIssueAndGetReqAlmIssueEntities(almIssueIncrementDTO);
    }

    @Override
    public void preSaveReqStatus(AlmIssueWithRequirementDTO almIssueWithRequirementDTO) {
        issueService.preSaveReqStatus(almIssueWithRequirementDTO);
    }

    @Override
    public void deleteIfDoesNotExistDoc() {
        issueService.deleteIfDoesNotExistDoc();
    }

    @Override
    public AlmIssueEntity findIssueByRecentId(String recentId) {
        return issueService.findIssueByRecentId(recentId);
    }

    @Async
    @Override
    @DwrSendAlarm(messageOnStart = "StatusMapping 카테고리 동기화 시작", messageOnEnd = "StatusMapping 카테고리 동기화 종료")
    @SlackSendAlarm(messageOnStart = "StatusMapping 카테고리 동기화 시작", messageOnEnd = "StatusMapping 카테고리 동기화 종료")
    public void updateArmsStateCategory() {
        String logMessagePrefix = "[ IssueScheduleServiceImpl :: updateArmsStateCategory ]";
        String shortUUID = UUIDUtil.createShortUUID();

        LocalDateTime startTime = LocalDateTime.now();
        DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

        log.info("[{}] :: {} :: started at {}", shortUUID, logMessagePrefix, startTime.format(timeFormatter));

        List<AlmIssueEntity> almIssueEntities = esCommonRepositoryWrapper.findAllRecentDocsBySearchAfter(
                SimpleQuery.matchAllQueryMust()
                        .orderBy(SortDTO.builder().field("@timestamp").sortType("desc").build())
        );

        List<AlmIssueEntity> updatedEntities = almIssueEntities.stream()
                .map(almIssueEntity -> {
                    try {
                        return updateArmsStateCategoryIfNeeded(almIssueEntity);
                    }
                    catch (Exception e) {
                        log.error("Error updating entity: {}", e.getMessage());
                        return null;
                    }
                })
                .filter(Objects::nonNull)
                .toList();

        updatedEntities.forEach(esCommonRepositoryWrapper::save);

        LocalDateTime endTime = LocalDateTime.now();
        Duration elapsed = Duration.between(startTime, endTime);
        log.info("[{}] :: {} :: finished at {} (completed in {} ms)", shortUUID, logMessagePrefix, endTime.format(timeFormatter), elapsed.toMillis());
    }

    @Override
    public void cloudJiraTestApiRequest() {
        issueService.cloudJiraTestApiRequest();
    }

    private AlmIssueEntity updateArmsStateCategoryIfNeeded(AlmIssueEntity entity) {
        String serverId = entity.getJira_server_id();
        ServerInfoVO serverInfoVO = serverInfoService.verifyServerInfo(serverId);
        ServerType serverType = ServerType.typeValueOf(serverInfoVO.getType());

        String projectKey = null;
        String issueTypeId = null;

        if (serverType == ServerType.CLOUD) {
            AlmIssueEntity.Project project = entity.getProject();
            if(project!=null){
                projectKey = project.getKey();
            }
            AlmIssueEntity.IssueType issuetype = entity.getIssuetype();
            if(issuetype!=null){
                issueTypeId = issuetype.getId();
            }
        }

        AlmIssueEntity.상태 status = entity.getStatus();

        if(status!=null){
            String statusId = status.getId();
            String newCategory = categoryMappingService.getMappingCategory(serverInfoVO, projectKey, issueTypeId, statusId);
            if (!newCategory.equals(entity.getArmsStateCategory())) {
                entity.setArmsStateCategory(newCategory);
                entity.generateId();
                return entity;
            }
        }

        return null;
    }


}
