package cn.com.countrygarden.bi.main.controller.datav.wo;

import cn.com.countrygarden.bi.main.model.eba.TbmMaintainTaskResult;
import cn.com.countrygarden.bi.main.service.eba.TbmMaintainTaskService;
import cn.com.countrygarden.bi.main.util.ChinaGeoUtil;
import cn.com.countrygarden.bi.main.util.NumberUtil;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import java.math.BigInteger;
import java.util.*;

@Controller("datavWorkOrderController")
@RequestMapping("/api/datav/wo")
public class WorkOrderController {

    @Resource
    private TbmMaintainTaskService service;
    private String upUrl = "https://datav.oss-cn-hangzhou.aliyuncs.com/uploads/images/8ac6e813ec8d986f57db4f90b2ad7f50.png";
    private String downUrl = "https://datav.oss-cn-hangzhou.aliyuncs.com/uploads/images/00566dbed2a575b441842af7c5d0e83e.png";

    /**
     * 今日工单统计数据
     *
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/aggre/yesterday", produces = "application/json;charset=utf-8", method = RequestMethod.GET)
    public Object aggregateYesterday() {
        List<Map<String, Object>> resultList = new ArrayList<>();
        Map<String, Object> aggre = service.aggregateYesterdayFromCache();
        aggre = flattenAggregate(aggre);

        resultList.add(aggre);
        return resultList;
    }

    /**
     * 今日工单统计数据
     *
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/aggre/today", produces = "application/json;charset=utf-8", method = RequestMethod.GET)
    public Object aggregateToday() {
        List<Map<String, Object>> resultList = new ArrayList<>();
        Map<String, Object> aggre = service.aggregateToday();
        Map<String, Object> aggreYesterday = service.aggregateYesterdayFromCache();

        int finished = getQuantity("finished", aggre);
        int finishedYesterday = getQuantity("finished", aggreYesterday);
        int unfinished = getQuantity("unfinished", aggre);
        int unfinishedYesterday = getQuantity("unfinished", aggreYesterday);
        int quantity = getQuantity("quantity", aggre);
        int quantityYesterday = getQuantity("quantity", aggreYesterday);

        aggre = flattenAggregate(aggre);

        float increaseRate = NumberUtil.percentage(quantity - quantityYesterday, quantityYesterday);
        float finishedRate = NumberUtil.percentage(finished - finishedYesterday, finishedYesterday);
        float unfinishedRate = NumberUtil.percentage(unfinished - unfinishedYesterday, unfinishedYesterday);

        aggre.put(
                "increaseRate",
                (increaseRate >= 0 ? "▲" : "▼") + NumberUtil.simpleFormat(Math.abs(increaseRate)) + "%"
        );
        aggre.put(
                "increaseRateUrl",
                getIncreaseRateImageUrl(increaseRate)
        );
        aggre.put(
                "finishedRate",
                (finishedRate >= 0 ? "▲" : "▼") + NumberUtil.simpleFormat(Math.abs(finishedRate)) + "%"
        );
        aggre.put(
                "finishedRateUrl",
                getIncreaseRateImageUrl(finishedRate)
        );
        aggre.put(
                "unfinishedRate",
                (unfinishedRate >= 0 ? "▲" : "▼") + NumberUtil.simpleFormat(Math.abs(unfinishedRate)) + "%"
        );
        aggre.put(
                "unfinishedRateUrl",
                getIncreaseRateImageUrl(unfinishedRate)
        );

        resultList.add(aggre);
        return resultList;
    }

    /**
     * 本月工单统计数据
     *
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/aggre/thismonth", produces = "application/json;charset=utf-8", method = RequestMethod.GET)
    public Object aggregateThisMonth() {
        List<Map<String, Object>> resultList = new ArrayList<>();

        Map<String, Object> aggre = service.aggregateThisMonth();
        int finishedInTime = getQuantity("finishedInTime", aggre);
        int takingInTime = getQuantity("takingInTime", aggre);
        int quantity = getQuantity("quantity", aggre);

        aggre = flattenAggregate(aggre);

        float finishedInTimeRate = NumberUtil.percentage(finishedInTime, quantity);
        float takingInTimeRate = NumberUtil.percentage(takingInTime, quantity);
        aggre.put(
                "finishedInTimeRate",
                NumberUtil.simpleFormat(finishedInTimeRate) + "%"
        );
        aggre.put(
                "takingInTimeRate",
                NumberUtil.simpleFormat(takingInTimeRate) + "%"
        );
        resultList.add(aggre);
        return resultList;
    }

    /**
     * 每月工单统计数据 - 人均接单数、平均处理时长
     * 人均接单数=已接单数/总维修工程人员数
     * 人均有效工时=总工时/总维修工程人员数
     *
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/aggre/thisyear/month/duration/ration", produces = "application/json;charset=utf-8", method = RequestMethod.GET)
    public Object aggregateRationDurationThisYearByMonth() {
        List<Map<String, Object>> resultList = new ArrayList<>();

        List<TbmMaintainTaskResult> aggres = service.aggregateThisYearByMonth();

        int enginer = service.getEngineeringQuatity();

        for (TbmMaintainTaskResult aggre : aggres) {
            Map<String, Object> item = new HashMap<>();
            int recieved = aggre.getRecieved();
            // 人均接单数
            String month = aggre.getCreateMonth().replace("-", "/");
            item.put("value", Math.ceil(recieved / enginer));
            item.put("s", "1");
            item.put("create_date", month);
            resultList.add(item);

            // 平均处理时长
            Map<String, Object> itemRation = new HashMap<>();
            int ration = aggre.getRationDuration();
            itemRation.put("value", Math.ceil(ration / enginer));
            itemRation.put("s", "2");
            itemRation.put("create_date", month);
            resultList.add(itemRation);
        }
        return resultList;
    }

    /**
     * 每月工单统计数据 - 平均处理时长
     * <p>
     * 平均处理时长 = 总完成时长（各单的完成时间减去开单时间相加之和）/总完成单数
     *
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/aggre/thisyear/month/duration/finish", produces = "application/json;charset=utf-8", method = RequestMethod.GET)
    public Object aggregateFinishDurationThisYearByMonth() {
        List<Map<String, Object>> resultList = new ArrayList<>();

        List<TbmMaintainTaskResult> aggres = service.aggregateThisYearByMonth();

        for (TbmMaintainTaskResult aggre : aggres) {
            Map<String, Object> item = new HashMap<>();

            BigInteger finishDuration = aggre.getFinishDuration();
            int finished = aggre.getFinished();
            // 平均处理时长 = 总完成时长 / 工程人员数
            String month = aggre.getCreateMonth().replace("-", "/");
            float durationAvg = finishDuration.floatValue() / (float) finished;

            item.put("finish_duration", durationAvg);
            item.put("create_date", month);
            resultList.add(item);
        }

        return resultList;
    }

    /**
     * 随机报事信息流
     * 新建、完成随机返回，总条数固定
     *
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/realtime/feed/random/{limit}", produces = "application/json;charset=utf-8", method = RequestMethod.GET)
    public Object realtimeFeedRandom(@PathVariable("limit") int limit) {
        List<Map<String, Object>> resultList = new ArrayList<>();

        limit = Math.max(5, limit);
        Random r = new Random();
        int limitNew = r.nextInt(limit);
        int limitFinished = limit - limitNew;

        List<TbmMaintainTaskResult> feeds = service.realtime(0, limitNew);

        feeds.addAll(service.realtime(1, limitFinished));
        resultList = flattenFeedList(feeds);

        return resultList;
    }

    /**
     * 随机报事信息流
     * 新建、完成随机返回，总条数固定
     *
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/realtime/feed/random/new/{limit}", produces = "application/json;charset=utf-8", method = RequestMethod.GET)
    public Object realtimeNewFeedRandom(@PathVariable("limit") int limit) {
        List<Map<String, Object>> resultList;

        List<TbmMaintainTaskResult> feeds = service.realtime(0, Math.max(5, limit));
        resultList = flattenFeedList(feeds);

        return resultList;
    }

    /**
     * 随机报事信息流
     * 新建、完成随机返回，总条数固定
     *
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/realtime/feed/random/finished/{limit}", produces = "application/json;charset=utf-8", method = RequestMethod.GET)
    public Object realtimeFinishedFeedRandom(@PathVariable("limit") int limit) {
        List<Map<String, Object>> resultList;

        List<TbmMaintainTaskResult> feeds = service.realtime(1, Math.max(5, limit));
        resultList = flattenFeedList(feeds);

        return resultList;
    }

    /**
     * 报事信息流
     *
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/realtime/feed/{limit}", produces = "application/json;charset=utf-8", method = RequestMethod.GET)
    public Object realtimeFeed(@PathVariable("limit") int limit) {
        List<Map<String, Object>> resultList = new ArrayList<>();
        List<TbmMaintainTaskResult> feeds = service.realtime(Math.max(5, limit));
        for (TbmMaintainTaskResult feed : feeds) {
            Map<String, Object> item = new HashMap<>();
            String cateName = "";
            String pureCateName = feed.getCateName().replaceAll("[0-9.]", "");
            int taskState = feed.getTaskState();
            if (taskState == 4 || taskState == 5) {
                if (feed.getIfPaid() == 1) {
                    cateName += "有偿（金额" + NumberUtil.simpleFormat(feed.getTotalPrice()) + "）" + pureCateName + "工单";
                } else {
                    cateName += "无偿" + pureCateName + "工单";
                }
            } else {
                cateName += pureCateName + "工单";
            }

            item.put("b", feed.getRepairUser()); //报事人
            item.put("2", cateName); // 报事类型
            item.put("3", feed.getTaskStateName()); // 状态
            resultList.add(item);
        }
        return resultList;
    }

    /**
     * 本年每月工单数统计
     *
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/aggre/thisyear/month", produces = "application/json;charset=utf-8", method = RequestMethod.GET)
    public Object aggregateThisYearByMonth() {
        List<Map<String, Object>> resultList = new ArrayList<>();
        List<TbmMaintainTaskResult> aggres = service.aggregateThisYearByMonth();
        System.out.println(aggres);
        for (TbmMaintainTaskResult aggre : aggres) {
            Map<String, Object> item = new HashMap<>();
            item.put("quantity", aggre.getQuantity());
            item.put("create_month", aggre.getCreateMonth().replace("-", "/"));
            resultList.add(item);
        }
        return resultList;
    }

    /**
     * 本月个区域接单统计
     *
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/aggre/thismonth/organ", produces = "application/json;charset=utf-8", method = RequestMethod.GET)
    public Object aggregateThisMonthByOrgan() {
        List<Map<String, Object>> aggres = service.aggregateThisMonthByOrgan();
        return aggres;
    }

    /**
     * 本月个区域接单统计
     *
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/aggre/thismonth/source", produces = "application/json;charset=utf-8", method = RequestMethod.GET)
    public Object aggregateThisMonthBySource() {
        List<Map<String, Object>> resultList = new ArrayList<>();
        List<TbmMaintainTaskResult> sources = service.aggregateThisMonthBySource();

        for (TbmMaintainTaskResult source : sources) {
            Map<String, Object> item = new HashMap<>();
            item.put("quantity", source.getQuantity());
            item.put("detail_name", source.getDetailName());
            resultList.add(item);
        }

        return resultList;
    }

    /**
     * 本月个区域接单统计
     *
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/aggre/thismonth/cate", produces = "application/json;charset=utf-8", method = RequestMethod.GET)
    public Object aggregateThisMonthByCategory() {
        List<Map<String, Object>> resultList = new ArrayList<>();

        List<TbmMaintainTaskResult> sources = service.aggregateThisMonthByCategory();

        for (TbmMaintainTaskResult source : sources) {
            Map<String, Object> item = new HashMap<>();
            item.put("quantity", source.getQuantity());
            item.put("cate_name", source.getCateName().replaceAll("[0-9.]", ""));
            resultList.add(item);
        }
        return resultList;
    }

    /**
     * 计算及时完成率、及时接单率
     *
     * @param aggre
     * @return
     */
    private Map<String, Object> flattenAggregate(Map<String, Object> aggre) {
        for (String key : aggre.keySet()) {
            aggre.replace(key, aggre.getOrDefault(key, "0"));
        }

        return aggre;
    }

    /**
     * 获取增长/下降图片路径
     *
     * @param rate
     * @return
     */
    private String getIncreaseRateImageUrl(float rate) {
        if (rate > 0) {
            return upUrl;
        } else if (rate < 0) {
            return downUrl;
        } else {
            return "#";
        }
    }

    /**
     * 取出数量值
     *
     * @param key
     * @param aggre
     * @return
     */
    private int getQuantity(String key, Map<String, Object> aggre) {
        return Integer.parseInt(aggre.getOrDefault(key, "0").toString());
    }

    private List<Map<String, Object>> flattenFeedList(List<TbmMaintainTaskResult> feeds) {
        List<Map<String, Object>> feedList = new ArrayList<>();
        if (feeds.isEmpty()) {
            return feedList;
        }

        for (TbmMaintainTaskResult feed : feeds) {
            Map<String, Object> item = new HashMap<>();

            item.put("info", feed.getRepairUser()); //报事人

            String lng = feed.getLongitude();
            String lat = feed.getLatitude();
            if (lat.equals("")) {
                List<String> geo = ChinaGeoUtil.getOrganProvinceGeo(feed.getOrganName());
                if (geo != null && !geo.isEmpty()) {
                    lng = geo.get(0);
                    lat = geo.get(1);
                }
            }

            item.put("lng", lng);
            item.put("lat", lat);

            feedList.add(item);
        }
        return feedList;
    }
}
