package com.xingxi.unifiedpay.configuration;

import com.xingxi.unifiedpay.service.XingxiUnifiedpay;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;

import java.io.IOException;
import java.util.Arrays;
import java.util.Set;

class RegisterMissingBeanPostProcessor implements BeanDefinitionRegistryPostProcessor {

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {

        ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(registry, false);
        scanner.addIncludeFilter(new TypeFilter() {
            @Override
            public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
                return metadataReader.getAnnotationMetadata().isAnnotated(XingxiUnifiedpay.class.getName());
            }
        });

        Set<BeanDefinition> candidateComponents = scanner.findCandidateComponents("com.xingxi.unifiedpay.service");
        if (!candidateComponents.isEmpty()) {
            for (BeanDefinition candidateComponent : candidateComponents) {
                String beanClassName = candidateComponent.getBeanClassName();

                Class<?> aClass = null;
                try {
                    aClass = Class.forName(beanClassName);
                } catch (ClassNotFoundException e) {
                    throw new RuntimeException(e);
                }

                XingxiUnifiedpay annotation = aClass.getAnnotation(XingxiUnifiedpay.class);
                String[] dependsOn = annotation.dependsOn();
                if (dependsOn.length > 0) {
                    boolean test = Arrays.stream(dependsOn).anyMatch(x -> !x.isEmpty() && !registry.containsBeanDefinition(x));
                    if (test) {
                        continue;
                    }
                }

                registry.registerBeanDefinition(annotation.name(), candidateComponent);

            }
        }

    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    }

}
