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

import com.arms.api.issue.type.model.dto.IssueTypeDTO;
import com.arms.api.issue.type.model.vo.IssueTypeVO;
import com.arms.api.serverinfo.model.vo.ServerInfoVO;
import com.arms.api.serverinfo.service.ServerInfoService;
import com.arms.api.util.alm.JiraApi;
import com.arms.api.util.alm.JiraUtil;
import com.arms.api.util.errors.ErrorLogUtil;
import lombok.AllArgsConstructor;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.client.WebClient;

import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

@Component
@AllArgsConstructor
public class CloudJiraIssueTypeStrategy implements IssueTypeStrategy {

    private final JiraUtil jiraUtil;

    private final JiraApi jiraApi;

    private final ServerInfoService serverInfoService;

    @Override
    public List<IssueTypeVO> getIssueTypeList(ServerInfoVO serverInfoVO) {

        String endpoint = jiraApi.getEndpoint().getIssue().getIssuetype();
        WebClient webClient = jiraUtil.createJiraCloudCommunicator(serverInfoVO.getUri(), serverInfoVO.getUserId(), serverInfoService.getDecryptPasswordOrToken(serverInfoVO.getPasswordOrToken()));

        try {
            List<IssueTypeDTO> issueTypeList = jiraUtil.get(webClient, endpoint,
                    new ParameterizedTypeReference<List<IssueTypeDTO>>() {}).block();

            return Optional.ofNullable(issueTypeList)
                    .orElse(Collections.emptyList())
                    .stream()
                    .filter(Objects::nonNull)
                    .map(this::convertIssueTypeVO)
                    .collect(Collectors.toList());
        }
        catch (Exception e) {
            String errorMessage = ErrorLogUtil.exceptionLoggingAndReturn(e, this.getClass().getName(),
                    String.format("%s[%s] :: getIssueTypeList Error", serverInfoVO.getType(), serverInfoVO.getUri()));
            throw new IllegalArgumentException(errorMessage);
        }
    }

    @Override
    public List<IssueTypeVO> getIssueTypeListByProject(ServerInfoVO serverInfoVO, String projectId) {

        String endpoint = jiraApi.getEndpoint().getIssue().getIssuetype() + "/project?projectId=" + projectId;
        WebClient webClient = jiraUtil.createJiraCloudCommunicator(serverInfoVO.getUri(), serverInfoVO.getUserId(), serverInfoService.getDecryptPasswordOrToken(serverInfoVO.getPasswordOrToken()));

        try {
            List<IssueTypeDTO> issueTypeList = jiraUtil.get(webClient, endpoint,
                    new ParameterizedTypeReference<List<IssueTypeDTO>>() {}).block();

            return Optional.ofNullable(issueTypeList)
                    .orElse(Collections.emptyList())
                    .stream()
                    .filter(Objects::nonNull)
                    .map(this::convertIssueTypeVO)
                    .collect(Collectors.toList());
        }
        catch (Exception e) {
            String errorMessage = ErrorLogUtil.exceptionLoggingAndReturn(e, this.getClass().getName(),
                    String.format("%s[%s] :: getIssueTypeListByProject Error :: projectId[%s]",
                                serverInfoVO.getType(), serverInfoVO.getUri(), projectId));
            throw new IllegalArgumentException(errorMessage);
        }
    }

    private IssueTypeVO convertIssueTypeVO(IssueTypeDTO issueTypeDTO) {
        return IssueTypeVO.builder()
                .self(issueTypeDTO.getSelf())
                .id(issueTypeDTO.getId())
                .description(issueTypeDTO.getDescription())
                .name(issueTypeDTO.getName())
                .subtask(issueTypeDTO.getSubtask())
                .untranslatedName(issueTypeDTO.getUntranslatedName())
                .hierarchyLevel(issueTypeDTO.getHierarchyLevel()).build();
    }
}