package tkio.service.impl;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import tkio.model.*;
import tkio.repository.*;
import tkio.service.AccountFlowRestrictService;
import util.Constant;
import util.DateUtil;
import util.HttpClientUtil;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by song on 2017/10/19.
 */
@Service
public class AccountFlowRestrictServiceImpl implements AccountFlowRestrictService {
    @Autowired
    private AppRepository appRepository;

    @Autowired
    private AccountRepository accountRepository;

    @Autowired
    private PackageTypeRepository packageTypeRepository;

    @Autowired
    private IsNotifiedRepository isNotifiedRepository;

    @Autowired
    private SalesManLeaderRepository salesManLeaderRepository;
    
    @Autowired
    private IncrementFlowRepository incrementFlowRepository;

    @Override
    public AccountRestrict4Web findRestrictByAccount(Long accountId) {

        Long rootParent = accountRepository.findRootParentByAccountId(accountId).longValue();
        AccountRestrict4Web accountRestrict4Web = new AccountRestrict4Web();
        Account one = accountRepository.findOne(accountId);

        List<App> apps = appRepository.listAppByRootAccount(rootParent);
        Account rootAccount = accountRepository.findOne(rootParent);
        String companyOrEmail = rootAccount.getCompany() != null ? rootAccount.getCompany() : rootAccount.getEmail();
        IsNotified isNotifiedObject = isNotifiedRepository.findIsNotifiedByAccountId(rootParent);

        boolean isTrackProduct = true;
        boolean isIOProduct = rootAccount.getAllowBehavior();

        StringBuffer appsStr = new StringBuffer();
        for (App app : apps) {
            appsStr = appsStr.append("\'" + app.getAppkey() + "\'" + ",");
        }
        String appids = "";
        if (apps.size() != 0) {
            appids = appsStr.substring(0, appsStr.length() - 1);
        }

        PackageType packageType = packageTypeRepository.findPackageTypeByRootParent(rootParent);
        Boolean flowRestrict = rootAccount.getFlowRestrict();

        String pastDate = rootAccount.getPastDate();
        String trackBeginTime;
        Date rootCreateTime = rootAccount.getCreateTime();
        String createTime = DateUtil.format(rootCreateTime, "yyyy-MM-dd");
        trackBeginTime = (rootAccount.getNewContract() != null && rootAccount.getNewContract()) ? rootAccount.getModifyPricelevelTime() : createTime;
        Date currentDate = DateUtil.getCurrentDate();
        String currentDateStr = DateUtil.getCurrentDateStr();
        int remainingDays = DateUtil.daysBetween(currentDate, DateUtil.parseDate(pastDate)) + 1;


        String salesManLeaderEmail = salesManLeaderRepository.findLeaderByBussinessMan(rootAccount.getBussinessman());
        ArrayList<String> emailList = new ArrayList<>();
        emailList.add(salesManLeaderEmail);

        Date lastMonth = getLastMonth(1);
        String firstDayOfLastMonth = DateUtil.getFirstDayOfMonth(lastMonth);
        String lastDayOfLastMonth = DateUtil.getLastDayOfMonth(lastMonth);
        String firstDayOfThisMonth = DateUtil.getFirstDayOfMonth(new Date());


        BigInteger clickNum =new BigInteger("0");
        BigInteger lastThreeDaysClickNum1=new BigInteger("0");
        if(apps.size()>0) {
            clickNum = getTotalNum(trackBeginTime, pastDate, appids, "account_track_flow_restrict", "click_sum");
            //lastThreeDaysClickNum1 = getTotalNum(trackBeginTime, currentDateStr, appids, "account_track_three_days_flow_restrict", "click_sum");
        }

        //BigInteger lastThreeDaysClickNum = lastThreeDaysClickNum1.compareTo(new BigInteger("0")) != 0 ? lastThreeDaysClickNum1 : new BigInteger("1");
       // int trackRemainDays = (int) Math.floor((packageType.getTrackFlow().doubleValue() - clickNum.doubleValue()) / ((lastThreeDaysClickNum.doubleValue() / 3)));
       // double trackRemainPercent = 1.0 - clickNum.doubleValue() / packageType.getTrackFlow().doubleValue();
       // DecimalFormat decimalFormat = new DecimalFormat("0%");
        //String trackRemainPercent1 = decimalFormat.format(trackRemainPercent);


        String IOBeginTime = (isNotifiedObject != null && isNotifiedObject.getThisMonthUpgradeLevel() != null && isNotifiedObject.getThisMonthUpgradeLevel()) ? rootAccount.getModifyPricelevelTime() : firstDayOfThisMonth;


        BigInteger lastMonthEventNum=new BigInteger("0");
        BigInteger thisMonthEventNum=new BigInteger("0");
        BigInteger lastThreeDaysEventNum=new BigInteger("0");
        if(apps.size()>0){
        lastMonthEventNum = getTotalNum(firstDayOfLastMonth, lastDayOfLastMonth, appids, "account_io_flow_restrict", "event_sum");
        thisMonthEventNum = getTotalNum(IOBeginTime, currentDateStr, appids, "account_io_flow_restrict", "event_sum");
        lastThreeDaysEventNum = getTotalNum(IOBeginTime, currentDateStr, appids, "account_io_three_days_flow_restrict", "event_sum");
    }

        BigInteger lastMonthExceedNum = (lastMonthEventNum.subtract(packageType.getIoFlow()).compareTo(new BigInteger("0")) == 1) ? lastMonthEventNum.subtract(packageType.getIoFlow()) : new BigInteger("0");
        if (isNotifiedObject != null && isNotifiedObject.getThisMonthUpgradeLevel() != null && isNotifiedObject.getThisMonthUpgradeLevel()) {
            lastMonthExceedNum = new BigInteger("0");
        }
        double v = packageType.getIoFlow().doubleValue() * 1 - lastMonthExceedNum.doubleValue();
        DecimalFormat decimalFormat1 = new DecimalFormat("0");
        String format = decimalFormat1.format(v);
        BigInteger thisMonthAvailableTotalFlow = new BigInteger(format);
        BigInteger thisMonthRemainingFlow = thisMonthAvailableTotalFlow.subtract(thisMonthEventNum);
        int IORemainDays = -1;
        if (lastThreeDaysEventNum.compareTo(new BigInteger("1")) == 1) {
            IORemainDays = (int) (Math.floor(Double.valueOf(thisMonthRemainingFlow.divide(lastThreeDaysEventNum.divide(new BigInteger("3"))).toString())));
        }
        double ioRemainPercent = thisMonthRemainingFlow.doubleValue() / thisMonthAvailableTotalFlow.doubleValue();
        //String ioRemainPercent1 = decimalFormat.format(ioRemainPercent);

        BigInteger num = incrementFlowRepository.listByRootAccount(accountId, DateUtil.getBeforeDays(0));
        BigInteger trackNum = packageType.getTrackFlow();

        if(trackNum.doubleValue() != -1 && null != num){
            trackNum = trackNum.add(num);
        }


        accountRestrict4Web.setPastDate(pastDate);
        accountRestrict4Web.setPackageName(packageType.getPackageName());
        accountRestrict4Web.setOriginalName(packageType.getOriginalName());
        accountRestrict4Web.setIOLimit(packageType.getIoFlow());
        accountRestrict4Web.setTrackLimit(trackNum);
        accountRestrict4Web.setThisMonthIOFlow(thisMonthEventNum);
        accountRestrict4Web.setTrackTotalFlow(clickNum);
        accountRestrict4Web.setAccountId(rootParent);
        accountRestrict4Web.setPriceLevel(rootAccount.getPricelevel().intValue());
        accountRestrict4Web.setLastMonthIOFlow(lastMonthEventNum);
        accountRestrict4Web.setIORemainPercent(ioRemainPercent);
        //accountRestrict4Web.setTrackRemainPercent(trackRemainPercent);
        accountRestrict4Web.setiOremainingDays(IORemainDays);
        //accountRestrict4Web.setTrackRemainingDays(trackRemainDays);
        accountRestrict4Web.setPackLevel(new Long(packageType.getId()));
        accountRestrict4Web.setFlowRestrict(flowRestrict);
        accountRestrict4Web.setAllowBehavior(isIOProduct);


        if (packageType.getTrackFlow().doubleValue() < 0) {
            accountRestrict4Web.setPackageName("包年套餐");
        }

        boolean ioFlag = true;
        boolean ioStatus = true;
        boolean trackFlag = true;
        boolean trackStatus = true;
        if (rootParent.equals(accountId)) {
            if (!(packageType.getTrackFlow().doubleValue() < 0) && flowRestrict) {
                /**
                 * 不是超级用户，是包流量的用户
                 */
                if (isTrackProduct) {
                    boolean tenPercent = (trackNum.doubleValue() * 0.9 <= clickNum.doubleValue()) && (trackNum.doubleValue() * 0.95 > clickNum.doubleValue());
                    boolean exPercent = trackNum.doubleValue() <= clickNum.doubleValue();
                    if (exPercent) {
                        ioFlag = false;
                        ioStatus = false;
                    }else if (tenPercent && (isNotifiedObject.getTrackTenPercentNotified() == null || !isNotifiedObject.getTrackTenPercentNotified())) {
                        ioStatus = false;
                    }
                }

                if (isIOProduct) {
                    boolean tenPercent = (thisMonthAvailableTotalFlow.doubleValue() * 0.9 <= thisMonthEventNum.doubleValue()) && (thisMonthAvailableTotalFlow.doubleValue() * 0.95 > thisMonthEventNum.doubleValue());
                    boolean exPercent = thisMonthAvailableTotalFlow.doubleValue() * 1 <= thisMonthEventNum.doubleValue();
                    if (exPercent) {
                        trackFlag = false;
                        trackStatus = false;
                    }else if (tenPercent && (isNotifiedObject.getIoTenPercentNotified() == null || !isNotifiedObject.getIoTenPercentNotified())) {
                        trackStatus = false;
                    }
                }

                //是否流量用尽
                if(trackFlag){
                    accountRestrict4Web.setIOFlowNotified(false);
                } else{
                    accountRestrict4Web.setIOFlowNotified(true);
                }
                accountRestrict4Web.setAllowBehavior(ioStatus);
                accountRestrict4Web.setTrackFlowNotified(trackStatus);
            }

        }
        return accountRestrict4Web;
    }


    /**
     * 查询广告效果监控产品的点击量和行为分析产品的点击量的方法
     */
    @Override
    public BigInteger getTotalNum(String createTime, String pastDate, String appids, String reportName, String
            sumType) {
        Long appId = 1218L;
        Map<String, String> conditions = new HashMap<String, String>();
        conditions.put("appids", appids);
        conditions.put("startdate", createTime);
        conditions.put("enddate", pastDate);
        conditions.put("datatype", "list");
        conditions.put("iscache", "0");
        String url = Constant.reportUrl + "/api/trackingio/" + reportName + "/" + appId;
        String responseJson = HttpClientUtil.doHttpPostRequest(url, "trackingio", conditions);
        //System.out.println(reportName + "===========================" + responseJson);
        HashMap<String, String> resultValMap = new HashMap<>();
        String click_sum = "";
        String s = "";
        try {
            JSONObject jsonObject = new JSONObject(responseJson);
            Iterator keys = jsonObject.keys();
            while (keys.hasNext()) {
                String key = (String) keys.next();
                String value = jsonObject.getString(key);
                resultValMap.put(key, value);
            }
            String val = resultValMap.get("val");
            JSONArray jsonArray = new JSONArray(val);
            JSONObject jsonObject1 = jsonArray.getJSONObject(0);
            click_sum = jsonObject1.getString(sumType);
            if (StringUtils.isEmpty(click_sum) || "0".equals(click_sum)) {
                click_sum = "0";
            }
            Double aDouble = Double.valueOf(click_sum);
            BigDecimal bigDecimal = new BigDecimal(aDouble);
            s = bigDecimal.toPlainString();
            //System.out.println(sumType + "=======================" + s);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return new BigInteger(s);
    }

    @Override
    public Boolean isTrackAndIoBothExhaust(Long accountId) {
        Long rootParent = accountRepository.findRootParentByAccountId(accountId).longValue();
        List<App> apps = appRepository.listAppByRootAccount(rootParent);
        Boolean isBothExhaust = false;
        if (apps.size() != 0) {
            Account rootAccount = accountRepository.findOne(rootParent);
            StringBuffer appsStr = new StringBuffer();
            for (App app : apps) {
                appsStr = appsStr.append("\'" + app.getAppkey() + "\'" + ",");
            }
            String appids = appsStr.substring(0, appsStr.length() - 1);

            /**
             * 1.根据母帐号获取用户等级
             */
            PackageType packageType = packageTypeRepository.findPackageTypeByRootParent(rootParent);
            Boolean flowRestrict = rootAccount.getFlowRestrict();

            String pastDate = rootAccount.getPastDate();
            String trackBeginTime;

            Date rootCreateTime = rootAccount.getCreateTime();
            String createTime = DateUtil.format(rootCreateTime, "yyyy-MM-dd");
            trackBeginTime = (rootAccount.getNewContract() != null && rootAccount.getNewContract()) ? rootAccount.getModifyPricelevelTime() : createTime;
            String currentDateStr = DateUtil.getCurrentDateStr();

            Date lastMonth = getLastMonth(1);
            String firstDayOfLastMonth = DateUtil.getFirstDayOfMonth(lastMonth);
            String lastDayOfLastMonth = DateUtil.getLastDayOfMonth(lastMonth);
            String firstDayOfThisMonth = DateUtil.getFirstDayOfMonth(new Date());

            BigInteger clickNum = getTotalNum(trackBeginTime, pastDate, appids, "account_track_flow_restrict", "click_sum");

            IsNotified isNotifiedObject = isNotifiedRepository.findIsNotifiedByAccountId(rootParent);
            String IOBeginTime = (isNotifiedObject != null && isNotifiedObject.getThisMonthUpgradeLevel() != null && isNotifiedObject.getThisMonthUpgradeLevel()) ? rootAccount.getModifyPricelevelTime() : firstDayOfThisMonth;
            BigInteger lastMonthEventNum = getTotalNum(firstDayOfLastMonth, lastDayOfLastMonth, appids, "account_io_flow_restrict", "event_sum");
            BigInteger thisMonthEventNum = getTotalNum(IOBeginTime, currentDateStr, appids, "account_io_flow_restrict", "event_sum");
            BigInteger lastMonthExceedNum = (lastMonthEventNum.subtract(packageType.getIoFlow()).compareTo(new BigInteger("0")) == 1) ? lastMonthEventNum.subtract(packageType.getIoFlow()) : new BigInteger("0");
            if (isNotifiedObject != null && isNotifiedObject.getThisMonthUpgradeLevel() != null && isNotifiedObject.getThisMonthUpgradeLevel()) {
                lastMonthExceedNum = new BigInteger("0");
            }
            double v = packageType.getIoFlow().doubleValue() * 1 - lastMonthExceedNum.doubleValue();
            DecimalFormat decimalFormat1 = new DecimalFormat("0");
            String format = decimalFormat1.format(v);
            BigInteger thisMonthAvailableTotalFlow = new BigInteger(format);
            BigInteger thisMonthRemainingFlow = thisMonthAvailableTotalFlow.subtract(thisMonthEventNum);

            if (!(packageType.getId() == 7 || packageType.getId() == 8 || packageType.getId() == 5) && flowRestrict) {
                if (rootAccount.getAllowBehavior()) {
                    isBothExhaust = (packageType.getTrackFlow().doubleValue() - clickNum.doubleValue() < 0) && thisMonthRemainingFlow.doubleValue() < 0;
                } else {
                    isBothExhaust = (packageType.getTrackFlow().doubleValue() - clickNum.doubleValue() < 0);
                }
            }
        }
        return isBothExhaust;
    }

    @Override
    public Boolean isTrackExhaust(Long accountId) {
        Long rootParent = accountRepository.findRootParentByAccountId(accountId).longValue();
        List<App> apps = appRepository.listAppByRootAccount(rootParent);
        Boolean isBothExhaust = false;
        if (apps.size() != 0) {
            Account rootAccount = accountRepository.findOne(rootParent);
            StringBuffer appsStr = new StringBuffer();
            for (App app : apps) {
                appsStr = appsStr.append("\'" + app.getAppkey() + "\'" + ",");
            }
            String appids = appsStr.substring(0, appsStr.length() - 1);

            /**
             * 1.根据母帐号获取用户等级
             */
            PackageType packageType = packageTypeRepository.findPackageTypeByRootParent(rootParent);
            Boolean flowRestrict = rootAccount.getFlowRestrict();

            String pastDate = rootAccount.getPastDate();
            String trackBeginTime;
            Date rootCreateTime = rootAccount.getCreateTime();
            String createTime = DateUtil.format(rootCreateTime, "yyyy-MM-dd");
            trackBeginTime = (rootAccount.getNewContract() != null && rootAccount.getNewContract()) ? rootAccount.getModifyPricelevelTime() : createTime;
            BigInteger clickNum = getTotalNum(trackBeginTime, pastDate, appids, "account_track_flow_restrict", "click_sum");
            if (!(packageType.getId() == 7 || packageType.getId() == 8 || packageType.getId() == 5) && flowRestrict) {
                isBothExhaust = (packageType.getTrackFlow().doubleValue() - clickNum.doubleValue() < 0);
            }
        }
        return isBothExhaust;
    }


    public Date getLastMonth(int i) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.MONTH, -i);
        Date time = calendar.getTime();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String format = sdf.format(time);
        calendar.setTime(new Date());
        return time;
    }
}
