package com.arms.api.admin.indexstatus.aspect;

import com.arms.api.admin.indexstatus.annotation.IndexStatusSnapShot;
import com.arms.api.admin.indexstatus.model.entity.IndexStatusEntity;
import com.arms.api.admin.indexstatus.model.enums.JobStatus;
import com.arms.egovframework.javaservice.esframework.model.vo.CatIndexVO;
import com.arms.egovframework.javaservice.esframework.repository.common.EsCommonRepositoryWrapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.core.ResolvableType;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@Slf4j
@Aspect
@Component
@AllArgsConstructor
public class IndexStatusSaveAspect {

    private final EsCommonRepositoryWrapper<IndexStatusEntity> esCommonRepositoryWrapper;

    private final ListableBeanFactory beanFactory;

    @Around("@annotation(indexStatusSnapShot)")
    public Object indexStatusAspect(ProceedingJoinPoint joinPoint, IndexStatusSnapShot indexStatusSnapShot) throws Throwable {

        EsCommonRepositoryWrapper<?> wrapper = findWrapperByClass(indexStatusSnapShot.clazz());

        String uuid = String.valueOf(UUID.randomUUID());
        log.info("BEFORE :: {}",indexStatusSnapShot.value());

        this.saveIndexStatus(wrapper.indexAliasName(), getCatIndexVOList(wrapper), uuid, JobStatus.BEFORE);

        Object joinPointResult = joinPoint.proceed();
        log.info("AFTER :: {}",indexStatusSnapShot.value());

        this.saveIndexStatus(wrapper.indexAliasName(), getCatIndexVOList(wrapper), uuid, JobStatus.AFTER);

        return joinPointResult;

    }

    private EsCommonRepositoryWrapper<?> findWrapperByClass(Class<?> clazz) {
        ResolvableType type = ResolvableType.forClassWithGenerics(EsCommonRepositoryWrapper.class, clazz);
        String[] names = beanFactory.getBeanNamesForType(type);
        if (names.length == 0) {
            throw new IllegalArgumentException("타입이 존재 하지 않습니다: " + clazz.getName());
        }
        return (EsCommonRepositoryWrapper<?>) beanFactory.getBean(names[0]);
    }

    private List<CatIndexVO> getCatIndexVOList(EsCommonRepositoryWrapper<?> wrapper) {
        return new ArrayList<>(wrapper.catIndexVOList());
    }

    private void saveIndexStatus(String indexAlias, List<CatIndexVO> catIndexVOList, String jobId, JobStatus jobStatus) {

        if(jobId==null){
            throw new IllegalArgumentException("jobId is null");
        }

        for (CatIndexVO catIndexVO : catIndexVOList) {
            IndexStatusEntity indexStatusEntity = IndexStatusEntity.from(catIndexVO);
            indexStatusEntity.setIndexAlias(indexAlias);
            indexStatusEntity.setJobId(jobId);
            indexStatusEntity.setJobStatus(jobStatus);
            this.esCommonRepositoryWrapper.save(indexStatusEntity);
        }

    }
}
