package track.task;

import common.model.CalculationFlow;
import common.model.Contract;
import common.model.ContractChange;
import common.model.TkioFlow;
import common.repository.CalculationFlowRepository;
import common.repository.ContractChangeRepository;
import common.repository.ContractRepository;
import common.repository.TkioFlowRepository;
import dic.ContractStatusEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import tkio.model.Account;
import tkio.repository.AccountRepository;
import tkio.repository.AppRepository;
import tkio.service.AccountFlowRestrictService;
import util.DateUtil;

import javax.persistence.Entity;
import java.math.BigInteger;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author liyin
 * @description
 * @date
 */
public class TrackingFlowTask {

    private final Logger logger = LoggerFactory.getLogger(TrackingFlowTask.class);

    @Autowired
    private ContractRepository contractRepository;
    @Autowired
    private AccountRepository accountRepository;
    @Autowired
    private AppRepository appRepository;
    @Autowired
    private AccountFlowRestrictService accountFlowRestrictService;
    @Autowired
    private TkioFlowRepository tkioFlowRepository;
    @Autowired
    private ContractChangeRepository contractChangeRepository;
    @Autowired
    private CalculationFlowRepository calculationFlowRepository;

    public void syncFlow(){
        List<CalculationFlow> calculationFlows = calculationFlowRepository.findByStatus(0);
        for (CalculationFlow calculationFlow : calculationFlows) {
            List<TkioFlow> tkioFlowList = new ArrayList<>();
            calculationFlow.setStatus(1);
            calculationFlowRepository.save(calculationFlow);
            tkioFlowRepository.deleteByEmail(calculationFlow.getEmail());
            String email = calculationFlow.getEmail();
            //查询用户下所有appkey
            Account account = accountRepository.findByEmail(email);
            List<Account> accountList = accountRepository.findByRootParent(account.getRootParent());
            List<Long> idList = new ArrayList<>();
            for (Account ac : accountList) {
                idList.add(ac.getId());
            }
            List<String> appkeys = appRepository.findAppkeysNotDebug(idList);
            String appkeyStr = String.join("','", appkeys);
            appkeyStr= "'"+appkeyStr+"'";

            String ago = DateUtil.format(account.getCreateTime(),DateUtil.C_DATE_PATTON_DEFAULT);//查找最早一天的流量
            if(ago==null){
                calculationFlow.setStatus(2);
                calculationFlowRepository.save(calculationFlow);
                continue;
            }

            int between = 0;
            try {
                between = DateUtil.daysBetween(ago, DateUtil.getBeforeDays(1))+1;
            } catch (ParseException e) {
                logger.error("强转错误：",e);
            }
            int startInt = 0;
            if(Integer.valueOf(DateUtil.getHH())>10){
                startInt = -1;
            }
            for (int ii = between; ii > startInt; ii--) {
                String yesterday = DateUtil.getBeforeDays(ii);//昨日
                BigInteger clickNum = accountFlowRestrictService.getTotalNum(yesterday, yesterday, appkeyStr, "account_track_flow_restrict", "click_sum");
                if(clickNum!=null&&clickNum.longValue()>0){
                    List<Contract> contracts = contractRepository.findByPlatformAndEmail("tkio", email);
                    if(contracts.size()==1){//只有一个合同
                        TkioFlow tkioFlow = getTkioFlow(clickNum, yesterday, contracts.get(0));
                        if(tkioFlow!=null){
                            tkioFlowList.add(tkioFlow);
                        }
                    }else{
                        //多个合同
                        //看昨日被哪几个合同包含了
                        List<Contract>  correlationContract = new ArrayList<>();
                        for (Contract contract : contracts) {
                            if (ContractStatusEnum.CANCEL.getKey().equals(contract.getStatus()) || ContractStatusEnum.SUSPEND.getKey().equals(contract.getStatus())) {
                                //中止或作废合同处理结束时间，以方便昨日流量的归属计算
                                ContractChange contractChange = contractChangeRepository.findByContentCode(ContractStatusEnum.CANCEL.getValue(), contract.getContractCode());
                                if(contractChange!=null){
                                    contract.setEndDate(contractChange.getDs());
                                }
                            }
                            String startDate = contract.getStartDate();
                            String endDate = contract.getEndDate();
                            if(DateUtil.getDate(yesterday).getTime()>=DateUtil.getDate(startDate).getTime() && DateUtil.getDate(yesterday).getTime()<=DateUtil.getDate(endDate).getTime()){
                                correlationContract.add(contract);
                            }
                        }
                        //多个合同时，进行排序，如果第一个合同流量超出就要看第二个合同，以此往下
                        if(correlationContract.size()>1){
                            //冒泡
                            //第一优先级：合同开始日期，第二优先级，合同编号大小
                            Contract[] contractsArray = new Contract[correlationContract.size()];
                            contractsArray = correlationContract.toArray(contractsArray);

                            contractsArray = orderByContract(contractsArray);

                            for (int i = 0; i < contractsArray.length; i++) {
                                TkioFlow tkioFlow = getTkioFlow(clickNum, yesterday, contractsArray[i]);
                                if(tkioFlow!=null&& i<contractsArray.length-1 && tkioFlow.getCostFlow()>0L){//处理成本流量，如果超出了，依次算在下一个合同上
                                    clickNum = BigInteger.valueOf(tkioFlow.getCostFlow());
                                    tkioFlow.setCostFlow(null);
                                    tkioFlowList.add(tkioFlow);
                                }else{
                                    if(tkioFlow!=null){
                                        tkioFlowList.add(tkioFlow);
                                    }
                                    break;
                                }

                            }
                        }else{
                            if(correlationContract.size()==0){//昨日不包含在所有合同中
                                //排序
                                Contract[] contractsArray = new Contract[contracts.size()];
                                contractsArray = contracts.toArray(contractsArray);
                                contractsArray = orderByContract(contractsArray);
                                //如果昨日日期在第一个合同之前，则归属到第一个合同的成本，其余区间都归属到前一个合同的成本上
                                for (int i = 0; i < contractsArray.length; i++) {
                                    if(DateUtil.getDate(yesterday).getTime()<=DateUtil.getDate(contractsArray[i].getStartDate()).getTime() || i==contractsArray.length-1){
                                        int j = 0;

                                        if(i!=0){
                                            j=i-1;
                                        }

                                        if(i==contractsArray.length-1){
                                            j = i;
                                        }

                                        TkioFlow tkioFlow = getTkioFlow(clickNum, yesterday, contractsArray[j]);
                                        if(tkioFlow!=null){
                                            tkioFlowList.add(tkioFlow);
                                        }
                                        break;
                                    }
                                }
                            }else{
                                TkioFlow tkioFlow = getTkioFlow(clickNum, yesterday, correlationContract.get(0));
                                if(tkioFlow!=null){
                                    tkioFlowList.add(tkioFlow);
                                }
                            }

                        }
                    }
                }
            }
            if(tkioFlowList.size()>0){
                tkioFlowRepository.save(tkioFlowList);
            }
            calculationFlow.setStatus(2);
            calculationFlowRepository.save(calculationFlow);
        }
    }

    public void task(){
        List<String> emails = contractRepository.findDistinctEmailByPlatform("tkio");

        List<TkioFlow> tkioFlowList = new ArrayList<>();

        for (String email : emails) {

            //查询用户下所有appkey
            Account account = accountRepository.findByEmail(email);
            List<Account> accountList = accountRepository.findByRootParent(account.getRootParent());
            List<Long> idList = new ArrayList<>();
            for (Account ac : accountList) {
                idList.add(ac.getId());
            }
            List<String> appkeys = appRepository.findAppkeysNotDebug(idList);
            String appkeyStr = String.join("','", appkeys);
            appkeyStr= "'"+appkeyStr+"'";


            String yesterday = DateUtil.getBeforeDays(1);//昨日
            BigInteger clickNum = accountFlowRestrictService.getTotalNum(yesterday, yesterday, appkeyStr, "account_track_flow_restrict", "click_sum");
            if(clickNum!=null&&clickNum.longValue()>0){
                List<Contract> contracts = contractRepository.findByPlatformAndEmail("tkio", email);
                if(contracts.size()==1){//只有一个合同
                    TkioFlow tkioFlow = getTkioFlow(clickNum, yesterday, contracts.get(0));
                    if(tkioFlow!=null){
                        tkioFlowList.add(tkioFlow);
                    }
                }else{//多个合同
                    //看昨日被哪几个合同包含了
                    List<Contract>  correlationContract = new ArrayList<>();
                    for (Contract contract : contracts) {
                        if (ContractStatusEnum.CANCEL.getKey().equals(contract.getStatus()) || ContractStatusEnum.SUSPEND.getKey().equals(contract.getStatus())) {
                            //中止或作废合同处理结束时间，以方便昨日流量的归属计算
                            ContractChange contractChange = contractChangeRepository.findByContentCode(ContractStatusEnum.CANCEL.getValue(), contract.getContractCode());
                            if(contractChange!=null){
                                contract.setEndDate(contractChange.getDs());
                            }
                        }
                        String startDate = contract.getStartDate();
                        String endDate = contract.getEndDate();
                        if(DateUtil.getDate(yesterday).getTime()>=DateUtil.getDate(startDate).getTime() && DateUtil.getDate(yesterday).getTime()<=DateUtil.getDate(endDate).getTime()){
                            correlationContract.add(contract);
                        }
                    }
                    //多个合同时，进行排序，如果第一个合同流量超出就要看第二个合同，以此往下
                    if(correlationContract.size()>1){
                        //冒泡
                        //第一优先级：合同开始日期，第二优先级，合同编号大小
                        Contract[] contractsArray = new Contract[correlationContract.size()];
                        contractsArray = correlationContract.toArray(contractsArray);

                        contractsArray = orderByContract(contractsArray);

                        for (int i = 0; i < contractsArray.length; i++) {
                            TkioFlow tkioFlow = getTkioFlow(clickNum, yesterday, contractsArray[i]);
                            if(tkioFlow!=null&& i<contractsArray.length-1 && tkioFlow.getCostFlow()>0L){//处理成本流量，如果超出了，依次算在下一个合同上
                                clickNum = BigInteger.valueOf(tkioFlow.getCostFlow());
                                tkioFlow.setCostFlow(null);
                                tkioFlowList.add(tkioFlow);
                            }else{
                                if(tkioFlow!=null){
                                    tkioFlowList.add(tkioFlow);
                                }
                                break;
                            }

                        }
                    }else{
                        if(correlationContract.size()==0){//昨日不包含在所有合同中
                            //排序
                            Contract[] contractsArray = new Contract[contracts.size()];
                            contractsArray = contracts.toArray(contractsArray);
                            contractsArray = orderByContract(contractsArray);
                            //如果昨日日期在第一个合同之前，则归属到第一个合同的成本，其余区间都归属到前一个合同的成本上
                            for (int i = 0; i < contractsArray.length; i++) {
                                if(DateUtil.getDate(yesterday).getTime()<=DateUtil.getDate(contractsArray[i].getStartDate()).getTime() || i==contractsArray.length-1){
                                    int j = 0;

                                    if(i!=0){
                                        j=i-1;
                                    }

                                    if(i==contractsArray.length-1){
                                        j = i;
                                    }

                                    TkioFlow tkioFlow = getTkioFlow(clickNum, yesterday, contractsArray[j]);
                                    if(tkioFlow!=null){
                                        tkioFlowList.add(tkioFlow);
                                    }
                                    break;
                                }
                            }



                        }else{
                            TkioFlow tkioFlow = getTkioFlow(clickNum, yesterday, correlationContract.get(0));
                            if(tkioFlow!=null){
                                tkioFlowList.add(tkioFlow);
                            }
                        }

                    }
                }
            }



        }
        if(tkioFlowList.size()>0){
            tkioFlowRepository.save(tkioFlowList);
        }

    }

    //排序
    public Contract[] orderByContract(Contract[] contractsArray){
        for (int i = 0; i < contractsArray.length-1; i++) {
            for (int j = 0; j < contractsArray.length-1-i; j++) {
                if(DateUtil.getDate(contractsArray[j].getStartDate()).getTime() > DateUtil.getDate(contractsArray[j + 1].getStartDate()).getTime()){
                    Contract temp = contractsArray[j];
                    contractsArray[j] = contractsArray[j+1];
                    contractsArray[j + 1] = temp;
                }else if(DateUtil.getDate(contractsArray[j].getStartDate()).getTime() == DateUtil.getDate(contractsArray[j + 1].getStartDate()).getTime()){
                    String contractCode = contractsArray[j].getContractCode().replaceAll("BJ-TKIO-", "").replaceAll("-", "");
                    String contractCodeMin = contractsArray[j + 1].getContractCode().replaceAll("BJ-TKIO-", "").replaceAll("-", "");
                    if(Long.valueOf(contractCode)>Long.valueOf(contractCodeMin)){
                        Contract temp = contractsArray[j];
                        contractsArray[j] = contractsArray[j+1];
                        contractsArray[j + 1] = temp;
                    }
                }
            }
        }
        return contractsArray;
    }

    public TkioFlow getTkioFlow(BigInteger clickNum,String yesterday,Contract contract){
        TkioFlow tkioFlow = new TkioFlow();
        tkioFlow.setDs(yesterday);
        tkioFlow.setEmail(contract.getEmail());
        tkioFlow.setContractCode(contract.getContractCode());
        try {
            if(DateUtil.daysBetween(contract.getStartDate(), yesterday)<0){//昨日日期早于合同开始日期
                //设置为成本流量
                tkioFlow.setCostFlow(clickNum.longValue());
            }else{
                //查看历史总消耗流量是否超出
                Long totalFlow = tkioFlowRepository.sumFlowByEmailAndContractCode(contract.getEmail(),contract.getContractCode());
                if(totalFlow!=null){
                    Double contractTrackFlow = contract.getTrackFlow() * 4;
                    if(contractTrackFlow.longValue()-totalFlow-clickNum.longValue()>=0){
                        tkioFlow.setFlow(clickNum.longValue());
                    }else{
                        tkioFlow.setFlow(contractTrackFlow.longValue() - totalFlow);
                        tkioFlow.setCostFlow(clickNum.longValue()-tkioFlow.getFlow());
                    }
                }else{
                    tkioFlow.setFlow(clickNum.longValue());
                }

            }
            return tkioFlow;
        } catch (ParseException e) {
            logger.error("合同编号-"+contract.getContractCode()+"-同步昨日流量错误：",e);
        }
        return null;
    }

    public static void main(String[] args) throws ParseException {
        String ago = "2020-10-01";
        int between = DateUtil.daysBetween(ago, DateUtil.getBeforeDays(1))+1;
        System.out.println(between);
        for (int i = between; i > 0; i--) {
            System.out.println(DateUtil.getBeforeDays(i));
        }
    }
}
