package com.boot.security.server.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.boot.security.server.dao.AdvertDao;
import com.boot.security.server.dto.LoginUser;
import com.boot.security.server.model.AdvertiserData;
import com.boot.security.server.page.table.PageTableRequest;
import com.boot.security.server.service.AdvertiserService;
import com.boot.security.server.utils.UserUtil;
import com.boot.security.server.utils.redis.JedisHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class AdvertiserServiceImpl implements AdvertiserService {

    @Autowired
    private AdvertDao advertDao;

    @Override
    public JSONObject getAdvertiserData(PageTableRequest request) {
        String today = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        String startTime = request.getStartTime();
        String endTime = request.getEndTime();
        Integer advertiserId = request.getAdvertiserId();
        String advertId = request.getAdvertId();
        List<AdvertiserData> advertiser=new ArrayList<>();
        List<AdvertiserData> advert=new ArrayList<>();
        AdvertiserData schema=new AdvertiserData();
        JSONObject jsonObject = new JSONObject();
        LoginUser loginUser = UserUtil.getLoginUser();

        if(startTime.equals(endTime)&&startTime.equals(today)){
            if(advertiserId==null&&advertId.equals("all")){
                advertiser=advertDao.getAdvertiserByUserId(loginUser.getId());
                advert=advertDao.getAdvertDataById(advertiser.get(0).getAdvertiserId());
                schema=advertDao.getAdvertiserDataById(advertiser.get(0).getAdvertiserId());
                JSONObject chartInfo = getRedisChartInfo(advertiser.get(0).getAdvertiserId(), advertId);
                jsonObject.put("dataTime",chartInfo.get("dataTime"));
                jsonObject.put("exposure",chartInfo.get("exposure"));
                jsonObject.put("click",chartInfo.get("click"));
            }else if(advertiserId!=null&&advertId!=null){
                advert=advertDao.getAdvertDataById(advertiserId);
                schema=advertDao.getAdvertiserDataById(advertiserId);
                JSONObject chartInfo = getRedisChartInfo(advertiserId, advertId);
                jsonObject.put("dataTime",chartInfo.get("dataTime"));
                jsonObject.put("exposure",chartInfo.get("exposure"));
                jsonObject.put("click",chartInfo.get("click"));
            }
        }else if(startTime.equals(endTime)&&!startTime.equals(today)){
            if(advertiserId==null&&advertId.equals("all")){
                advertiser=advertDao.getAdvertiserByUserId(loginUser.getId());
                advert=advertDao.getAdvertDataById(advertiser.get(0).getAdvertiserId());
                schema=advertDao.getAdvertiserDataById(advertiser.get(0).getAdvertiserId());
                List<AdvertiserData> advertExCl = advertDao.getAdvertExCl(advertiser.get(0).getAdvertiserId(), startTime);
                JSONObject mysqlChartInfo = getMysqlChartInfo(advertExCl);
                jsonObject.put("dataTime",mysqlChartInfo.get("dataTime"));
                jsonObject.put("exposure",mysqlChartInfo.get("exposure"));
                jsonObject.put("click",mysqlChartInfo.get("click"));
            }else if(advertiserId!=null&&advertId!=null){
                advert=advertDao.getAdvertDataById(advertiserId);
                schema=advertDao.getAdvertiserDataById(advertiserId);
                List<AdvertiserData> advertExCl=null;
                if(advertId.equals("all")){
                    advertExCl = advertDao.getAdvertExCl(advertiserId,startTime);
                }else {
                    advertExCl = advertDao.getAdvertExCls(advertiserId,advertId,startTime);
                }
                JSONObject mysqlChartInfo = getMysqlChartInfo(advertExCl);
                jsonObject.put("dataTime",mysqlChartInfo.get("dataTime"));
                jsonObject.put("exposure",mysqlChartInfo.get("exposure"));
                jsonObject.put("click",mysqlChartInfo.get("click"));
            }
        }else {
            if(advertId.equals("all")){
                advert=advertDao.getAdvertDataById(advertiserId);
                schema=advertDao.getAdvertiserDataById(advertiserId);
                List<AdvertiserData> advertExClDays = advertDao.getAdvertExClDay(advertiserId, startTime, endTime);
                JSONObject mysqlChartInfo = getMysqlChartInfo(advertExClDays);
                jsonObject.put("dataTime",mysqlChartInfo.get("dataTime"));
                jsonObject.put("exposure",mysqlChartInfo.get("exposure"));
                jsonObject.put("click",mysqlChartInfo.get("click"));
            }else {
                advert=advertDao.getAdvertDataById(advertiserId);
                schema=advertDao.getAdvertiserDataById(advertiserId);
                List<AdvertiserData> advertExClDays = advertDao.getAdvertExClDays(advertiserId, advertId,startTime, endTime);
                JSONObject mysqlChartInfo = getMysqlChartInfo(advertExClDays);
                jsonObject.put("dataTime",mysqlChartInfo.get("dataTime"));
                jsonObject.put("exposure",mysqlChartInfo.get("exposure"));
                jsonObject.put("click",mysqlChartInfo.get("click"));
            }
        }
        jsonObject.put("advertiser",advertiser);
        jsonObject.put("advert",advert);
        jsonObject.put("schema",schema);
        return jsonObject;
    }

    @Override
    public JSONObject getAdvertiserManagerData(PageTableRequest request) {
        List<AdvertiserData> data = advertDao.getAdvertiserDataByUserId(UserUtil.getLoginUser().getId());
        Integer count = advertDao.getAdvertiserDataByUserIdCount(UserUtil.getLoginUser().getId());
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("data",data);
        jsonObject.put("count",count);
        jsonObject.put("code",0);
        return jsonObject;
    }

    @Override
    public void updateAdvertiserManagerData(AdvertiserData advertiserData) {
        advertDao.updateAdvertiserData(advertiserData.getAdvertiserId(),advertiserData.getBalance(),advertiserData.getExposureView(),advertiserData.getClickView());
    }

    private JSONObject getRedisChartInfo(Integer advertiserId,String advertId){
        JSONObject jsonObject = new JSONObject();
        String date = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        String clickKey="redisAdvertDataDayClick:"+date+":"+advertiserId;
        Map<String, Integer> clickMap = JedisHelper.hgetAll(Integer.class, clickKey);
        List<String> minutesCodeIdClick = mapToList(clickMap);
        String exposureKey="redisAdvertDataDayExposure:"+date+":"+advertiserId;
        Map<String, Integer> exposureMap = JedisHelper.hgetAll(Integer.class, exposureKey);
        List<String> minutesCodeIdExposure = mapToList(exposureMap);
        if(advertId.equals("all")){
            Map<String, List<String>> click = minutesCodeIdClick.stream().collect(Collectors.groupingBy(x -> x.split(",")[0]));
            Map<String, List<String>> exposure = minutesCodeIdExposure.stream().collect(Collectors.groupingBy(x -> x.split(",")[0]));
            JSONObject resultClick = sumByKey(click);
            JSONObject resultExposure = sumByKey(exposure);
            jsonObject.put("dataTime",resultClick.get("dataTime"));
            jsonObject.put("click",resultClick.get("sum"));
            jsonObject.put("exposure",resultExposure.get("sum"));
        }else {
            Map<String, List<String>> click = minutesCodeIdClick.stream().filter(x->x.split(",")[1].equals(advertId)).collect(Collectors.groupingBy(x -> x.split(",")[0]));
            Map<String, List<String>> exposure = minutesCodeIdExposure.stream().filter(x->x.split(",")[1].equals(advertId)).collect(Collectors.groupingBy(x -> x.split(",")[0]));
            JSONObject resultClick = sumByKey(click);
            JSONObject resultExposure = sumByKey(exposure);
            jsonObject.put("dataTime",resultClick.get("dataTime"));
            jsonObject.put("click",resultClick.get("sum"));
            jsonObject.put("exposure",resultExposure.get("sum"));
        }
        return jsonObject;
    }

    public static List mapToList(Map<String, Integer> map){
        List<String> list=new ArrayList();
        Iterator it=map.keySet().iterator();
        while(it.hasNext()){
            String key=it.next().toString();
            Integer value = map.get(key);
            list.add(key+","+value);
        }
        return list;
    }

    public static JSONObject sumByKey(Map<String, List<String>> map){
        Object[] objects = map.keySet().toArray();
        Arrays.sort(objects);
        JSONObject jsonObject = new JSONObject();
        List<String> dataTime=new ArrayList<>();
        List<Integer> sum=new ArrayList<>();
        //Iterator it=map.keySet().iterator();
        for(Object obj:objects){
            String key=obj.toString();
            dataTime.add(key.split(",")[0]);
            Integer count=0;
            List<String> list = map.get(key);
            for (String s : list) {
                Integer i = Integer.valueOf(s.split(",")[2]);
                count+=i;
            }
            sum.add(count);
        }
        jsonObject.put("dataTime",dataTime);
        jsonObject.put("sum",sum);
        return jsonObject;
    }

    public static JSONObject getMysqlChartInfo(List<AdvertiserData> advertExCl){
        JSONObject jsonObject = new JSONObject();
        List<String> dataTime=new ArrayList<>();
        List<Integer> exposure=new ArrayList<>();
        List<Integer> click=new ArrayList<>();
        for (AdvertiserData advertiserData : advertExCl) {
            if(advertiserData.getMinutes()!=null){
                dataTime.add(advertiserData.getMinutes());
            }else {
                dataTime.add(advertiserData.getReportDate());
            }
            exposure.add(advertiserData.getExposure());
            click.add(advertiserData.getClick());
        }
        jsonObject.put("dataTime",dataTime);
        jsonObject.put("exposure",exposure);
        jsonObject.put("click",click);
        return jsonObject;
    }
}
