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.DegradeRuleEntity;
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 DegradeNacosPostProcessor extends BaseProcessor implements NacosPostProcessor {

    @Autowired
    private RuleRepository<DegradeRuleEntity, Long> repository;

    @Autowired
    @Qualifier("degradeRuleNacosProvider")
    private DynamicRuleProvider<List<DegradeRuleEntity>> ruleProvider;

    @Autowired
    @Qualifier("degradeRuleNacosPublisher")
    private DynamicRulePublisher<List<DegradeRuleEntity>> rulePublisher;


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

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

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

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

    @Override
    public <T> List<T> getRules(String app, String ip, Integer port, Class<?> clazz) throws Exception {
        if (clazz != DegradeRuleEntity.class){
            return null;
        }
        List<DegradeRuleEntity> 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 != DegradeRuleEntity.class){
            return null;
        }
        return (List<T>) ruleProvider.getRules(app);
    }
}
