package cd.casic.plugin.core.register;

import cd.casic.plugin.dataobject.pojo.PluginInfo;
import cd.casic.plugin.function.IPluginProcessor;
import com.anwen.mongo.annotation.collection.CollectionName;
import com.anwen.mongo.conn.CollectionManager;
import com.anwen.mongo.conn.ConnectMongoDB;
import com.anwen.mongo.convert.CollectionNameConvert;
import com.anwen.mongo.manager.MongoPlusClient;
import com.anwen.mongo.mapper.BaseMapper;
import com.anwen.mongo.service.IService;
import com.anwen.mongo.service.impl.ServiceImpl;
import com.mongodb.MongoException;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import lombok.extern.slf4j.Slf4j;
import org.bson.Document;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @description: TODO
 * @author: mianbin
 * @date: 2025/5/22 18:25
 * @version: 1.0
 */
@Slf4j
@Component
public class MongoProcessor implements IPluginProcessor {

    private AnnotationConfigApplicationContext applicationContext;

    @Override
    public void initialize() throws Exception {
        log.info("Start to hand the Mongo Class for plugin");
    }

    @Override
    public void registry(PluginInfo plugin) throws Exception {
        applicationContext = plugin.getPluginApplicationContext();
        applicationContext.getBeansOfType(IService.class)
                .values()
                .stream()
                .filter(s -> s instanceof ServiceImpl)
                .forEach(s -> {
                    Class<?> clazz = s.getGenericityClass();
                    ServiceImpl<?> serviceImpl = (ServiceImpl<?>) s;
                    serviceImpl.setClazz(clazz);
                    String database = initFactory(clazz);
                    // 这里需要将MongoPlusClient给工厂
                    serviceImpl.setDatabase(database);
                    serviceImpl.setBaseMapper(applicationContext.getBean("baseMapper", BaseMapper.class));
                });
    }

    @Override
    public void unRegistry(PluginInfo plugin) throws Exception {
        //卸载暂时都先不处理
    }

    private String initFactory(Class<?> clazz) {
        String collectionName = clazz.getSimpleName().toLowerCase();
        final String[] dataBaseName = {""};
        if (clazz.isAnnotationPresent(CollectionName.class)) {
            CollectionName annotation = clazz.getAnnotation(CollectionName.class);
            collectionName = annotation.value();
            dataBaseName[0] = annotation.database();
        }
        try {
            String finalCollectionName = collectionName;
            final String[] finalDataBaseName = {dataBaseName[0]};
            List<MongoDatabase> mongoDatabaseList = new ArrayList<>();
            MongoPlusClient mongoPlusClient = applicationContext.getBean("mongoPlusClient", MongoPlusClient.class);
            String database = mongoPlusClient.getBaseProperty().getDatabase();
            Arrays.stream(database.split(",")).collect(Collectors.toList()).forEach(db -> {
                CollectionNameConvert collectionNameConvert = applicationContext.getBean("collectionNameConvert", CollectionNameConvert.class);
                CollectionManager collectionManager = new CollectionManager(mongoPlusClient.getMongoClient(), collectionNameConvert, db);
                ConnectMongoDB connectMongodb = new ConnectMongoDB(mongoPlusClient.getMongoClient(), db, finalCollectionName);
                MongoDatabase mongoDatabase = mongoPlusClient.getMongoClient().getDatabase(db);
                mongoDatabaseList.add(mongoDatabase);
                if (Objects.equals(db, finalDataBaseName[0])) {
                    MongoCollection<Document> collection = connectMongodb.open(mongoDatabase);
                    collectionManager.setCollectionMap(finalCollectionName, collection);
                }
                mongoPlusClient.getCollectionManager().put(db, collectionManager);
            });
            mongoPlusClient.setMongoDatabase(mongoDatabaseList);
        } catch (MongoException e) {
            log.error("Failed to connect to MongoDB: {}", e.getMessage(), e);
        }
        return dataBaseName[0];
    }
}
