package com.alibaba.csp.sentinel.dashboard.rule.nacos.processor.impl;

import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.AuthorityRuleEntity;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.ParamFlowRuleEntity;
import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo;
import com.alibaba.csp.sentinel.dashboard.repository.rule.RuleRepository;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher;
import com.alibaba.csp.sentinel.dashboard.rule.nacos.processor.BaseProcessor;
import com.alibaba.csp.sentinel.dashboard.rule.nacos.processor.NacosPostProcessor;
import com.alibaba.csp.sentinel.dashboard.rule.nacos.util.NacosUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @author Clay
 * @date 2022/11/14
 */
@Service
public class ParamFlowNacosPostProcessor extends BaseProcessor implements NacosPostProcessor {

    @Autowired
    @Qualifier("paramFlowRuleNacosProvider")
    private DynamicRuleProvider<List<ParamFlowRuleEntity>> ruleProvider;

    @Autowired
    @Qualifier("paramFlowRuleNacosPublisher")
    private DynamicRulePublisher<List<ParamFlowRuleEntity>> rulePublisher;

    @Autowired
    private RuleRepository<ParamFlowRuleEntity, Long> repository;


    @Override
    public void initPostProcessor(String app, String ip, Integer port) throws Exception {
        List<ParamFlowRuleEntity> rules = ruleProvider.getRules(app);
        rules = NacosUtils.filterSelf(app,ip,port,rules);
        rules = repository.saveAll(rules);
        sentinelApiClient.setParamFlowRuleOfMachine(app, ip, port, rules);
    }

    @Override
    public void initClusterProcessor(String app, String ip, Integer port) throws Exception {
        List<ParamFlowRuleEntity> rules = ruleProvider.getRules(app);
        rules = repository.saveAll(rules);
        sentinelApiClient.setParamFlowRuleOfMachine(app, ip, port, rules);
    }

    @Override
    public boolean publishRules(String app, String ip, Integer port, Class<?> clazz) throws Exception {
        if (clazz != ParamFlowRuleEntity.class){
            return false;
        }
        List<ParamFlowRuleEntity> rules = ruleProvider.getRules(app);
        rules = NacosUtils.filterOther(app, ip, port, rules);
        List<ParamFlowRuleEntity> newRules = repository.findAllByMachine(MachineInfo.of(app, ip, port));
        rules.addAll(newRules);
        rulePublisher.publish(app, rules);
        sentinelApiClient.setParamFlowRuleOfMachine(app, ip, port, newRules).get();
        return true;
    }

    @Override
    public boolean publishClusterRules(String app, String ip, Integer port, Class<?> clazz) throws Exception {
        if (clazz != ParamFlowRuleEntity.class){
            return false;
        }
        List<ParamFlowRuleEntity> rules = repository.findAllByMachine(MachineInfo.of(app, ip, port));
        getAppInfo(app).forEach(info-> sentinelApiClient.setParamFlowRuleOfMachine(info.getApp(), info.getIp(), info.getPort(), rules));
        rulePublisher.publish(app, rules);
        return true;
    }

    @Override
    public <T> List<T> getRules(String app, String ip, Integer port, Class<?> clazz) throws Exception {
        if (clazz != ParamFlowRuleEntity.class){
            return null;
        }
        List<ParamFlowRuleEntity> rules = ruleProvider.getRules(app);
        return (List<T>) NacosUtils.filterSelf(app, ip, port, rules);
    }

    @Override
    public <T> List<T> getClusterRules(String app, String ip, Integer port, Class<?> clazz) throws Exception {
        if (clazz != ParamFlowRuleEntity.class){
            return null;
        }
        return (List<T>) ruleProvider.getRules(app);
    }
}
