package com.slodon.b2b2c.controller.statistics.admin;

import com.slodon.b2b2c.core.constant.StoreConst;
import com.slodon.b2b2c.core.controller.BaseController;
import com.slodon.b2b2c.core.response.JsonResult;
import com.slodon.b2b2c.core.response.PageVO;
import com.slodon.b2b2c.core.response.PagerInfo;
import com.slodon.b2b2c.core.response.SldResponse;
import com.slodon.b2b2c.core.util.StringUtil;
import com.slodon.b2b2c.core.util.WebUtil;
import com.slodon.b2b2c.enums.ProvinceJson;
import com.slodon.b2b2c.enums.StatsTimeType;
import com.slodon.b2b2c.enums.WebSiteConstant;
import com.slodon.b2b2c.model.seller.StoreModel;
import com.slodon.b2b2c.model.seller.StoreSiteInfoModel;
import com.slodon.b2b2c.model.statistics.StoreDayModel;
import com.slodon.b2b2c.seller.dto.StoreStatisticsDTO;
import com.slodon.b2b2c.seller.example.StoreExample;
import com.slodon.b2b2c.seller.example.StoreSiteInfoExample;
import com.slodon.b2b2c.seller.pojo.Store;
import com.slodon.b2b2c.seller.pojo.StoreSiteInfo;
import com.slodon.b2b2c.statistics.example.StoreDayExample;
import com.slodon.b2b2c.statistics.pojo.base.PlatformBase;
import com.slodon.b2b2c.statistics.pojo.base.StoreBase;
import com.slodon.b2b2c.util.StatsModelUtil;
import com.slodon.b2b2c.vo.statistics.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.*;

@Api(tags = "admin-店铺分析")
@RestController
@RequestMapping("v3/statistics/admin/store/analysis")
public class AdminStoreAnalysisController extends BaseController {

    @Resource
    private StoreDayModel storeDayModel;
    @Resource
    private StatsModelUtil statsModelUtil;
    @Resource
    private StoreModel storeModel;
    @Resource
    private StoreSiteInfoModel storeSiteInfoModel;

    @ApiOperation("店铺总览(店铺总数)")
    @GetMapping("storeNum")
    public JsonResult storeNum(HttpServletRequest request) {
        StoreExample example = new StoreExample();
        example.setStateNotEquals(StoreConst.STORE_STATE_DELETE);
        Map<String, Integer> map = new HashMap<>();
        map.put("storeNum", storeModel.getStoreCount(example));
        return SldResponse.success(map);
    }

    @ApiOperation("店铺总览")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "webSite", value = "站点"),
            @ApiImplicitParam(name = "startTime", value = "开始时间", required = true),
            @ApiImplicitParam(name = "endTime", value = "结束时间", required = true)
    })
    @GetMapping("storeOverview")
    public JsonResult<StoreOverviewVO> storeOverview(HttpServletRequest request,String webSite, Date startTime, Date endTime) {
        StatsTimeType timeType = StatsTimeType.checkTimeType(startTime, endTime, false);
        StoreOverviewVO vo = new StoreOverviewVO();
        List<? extends PlatformBase> list = statsModelUtil.getPlatformList(timeType, webSite, startTime, endTime);
        if (!CollectionUtils.isEmpty(list)) {
            PlatformBase platformBase = list.get(0);
            //上期数据
            PlatformBase previousData = null;
            Date preStartTime;
            Date preEndTime;
            int differentDay = StatsTimeType.getDifferentDay(startTime, endTime);
            if (timeType == StatsTimeType.DAY && differentDay != 1) {
                preStartTime = StatsTimeType.getPreStartTime(startTime, differentDay);
                preEndTime = StatsTimeType.getPreEndTime(endTime, differentDay);
            } else {
                preStartTime = StatsTimeType.getStartTime(startTime, timeType);
                preEndTime = StatsTimeType.getEndTime(endTime, timeType);
            }
            if (preStartTime != null) {
                List<? extends PlatformBase> previousList = statsModelUtil.getPlatformList(timeType, webSite, preStartTime, preEndTime);
                if (!CollectionUtils.isEmpty(previousList)) {
                    previousData = previousList.get(0);
                }
            }
            if (platformBase != null) {
                vo = new StoreOverviewVO(platformBase, previousData);
            }
        }
        return SldResponse.success(vo);
    }

    @ApiOperation("新增店铺趋势")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "startTime", value = "开始时间", required = true),
            @ApiImplicitParam(name = "endTime", value = "结束时间", required = true),
            @ApiImplicitParam(name = "webSite", value = "站点")
    })
    @GetMapping("newStoreTrend")
    public JsonResult<List<NewStoreTrendVO>> newStoreTrend(HttpServletRequest request, Date startTime, Date endTime,@RequestParam(name = "webSite", required = false,defaultValue = "1") String webSite) {
        StatsTimeType timeType = StatsTimeType.checkTimeType(startTime, endTime, true);
        List<MovableGoodsVO> list = statsModelUtil.getPlatformTrendList(timeType, startTime, endTime, webSite);
        List<NewStoreTrendVO> vos = new ArrayList<>();
        if (!CollectionUtils.isEmpty(list)) {
            list.forEach(trendVO -> {
                NewStoreTrendVO vo = new NewStoreTrendVO();
                vo.setStatsTime(trendVO.getStatsTime());
                vo.setNewStoreNum(trendVO.getNewStoreNum());
                vos.add(vo);
            });
        }
        return SldResponse.success(vos);
    }

    @ApiOperation("地域分布")
    @GetMapping("regionDistribution")
    public JsonResult<List<ProvincePercentVO>> regionDistribution(HttpServletRequest request) {
        StoreExample example = new StoreExample();
        example.setStateNotEquals(StoreConst.STORE_STATE_DELETE);
        example.setOrderBy("storeNum DESC");
        List<StoreStatisticsDTO> list = storeModel.getStoreStatisticList(example);
        List<ProvincePercentVO> vos = getRegionDistributionPercent(list);
        return SldResponse.success(vos);
    }

    @ApiOperation("店铺等级分布占比")
    @GetMapping("gradePercent")
    public JsonResult<List<StoreGradePercentVO>> gradePercent(HttpServletRequest request,String webSite) {
        StoreExample example = new StoreExample();
        List<Store> list = storeModel.getStoreList(example, null);
        List<StoreGradePercentVO> vos = getStoreGradePercent(list, webSite);
        return SldResponse.success(vos);
    }

    @ApiOperation("店铺类型占比")
    @GetMapping("typePercent")
    public JsonResult<List<StoreTypePercentVO>> typePercent(HttpServletRequest request) {
        StoreExample example = new StoreExample();
        List<Store> list = storeModel.getStoreList(example, null);
        List<StoreTypePercentVO> vos = getStoreTypePercent(list);
        return SldResponse.success(vos);
    }

    @ApiOperation("店铺报表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "startTime", value = "开始时间", required = true),
            @ApiImplicitParam(name = "endTime", value = "结束时间", required = true),
            @ApiImplicitParam(name = "storeName", value = "店铺名称"),
            @ApiImplicitParam(name = "type", value = "排序类型；desc-降序;asc-升序;默认类型为降序"),
            @ApiImplicitParam(name = "sort", value = "排序:orderPayAmount-支付金额;orderSubmitAmount-下单金额;orderPayNum-支付订单数;" +
                    "orderSubmitNum-下单数;visitorNum-店铺访客数;viewNum-店铺浏览量;goodsVisitorNum-商品访客数;goodsViewNum-商品浏览量;" +
                    "viewGoodsNum-被访问商品数;salingGoodsNum-动销商品数;returnNum-退单数;returnAmount-退单金额;默认按支付金额降序排序"),
            @ApiImplicitParam(name = "pageSize", value = "分页大小", defaultValue = "20", paramType = "query"),
            @ApiImplicitParam(name = "current", value = "当前页面位置", defaultValue = "1", paramType = "query")
    })
    @GetMapping("storeReport")
    public JsonResult<PageVO<StoreReportVO>> storeReport(HttpServletRequest request, Date startTime, Date endTime, String storeName,
                                                         @RequestParam(value = "type", required = false, defaultValue = "desc") String type,
                                                         @RequestParam(value = "sort", required = false, defaultValue = "orderPayAmount") String sort) {
        PagerInfo pager = WebUtil.handlerPagerInfo(request);
        StoreDayExample example = new StoreDayExample();
        example.setStatsTimeAfter(startTime);
        example.setStatsTimeBefore(endTime);
        example.setStoreNameLike(storeName);
        example.setOrderBy(sort + " " + type);
        List<StoreBase> list = storeDayModel.getStoreList(example, pager);
        List<StoreReportVO> vos = new ArrayList<>();
        if (!CollectionUtils.isEmpty(list)) {
            list.forEach(storeBase -> {
                vos.add(new StoreReportVO(storeBase));
            });
        }
        return SldResponse.success(new PageVO<>(vos, pager));
    }

    @ApiOperation("导出报表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "startTime", value = "开始时间", required = true),
            @ApiImplicitParam(name = "endTime", value = "结束时间", required = true),
            @ApiImplicitParam(name = "storeName", value = "店铺名称"),
            @ApiImplicitParam(name = "type", value = "排序类型；desc-降序;asc-升序;默认类型为降序"),
            @ApiImplicitParam(name = "sort", value = "排序:orderPayAmount-支付金额;orderSubmitAmount-下单金额;orderPayNum-支付订单数;" +
                    "orderSubmitNum-下单数;visitorNum-店铺访客数;viewNum-店铺浏览量;goodsVisitorNum-商品访客数;goodsViewNum-商品浏览量;" +
                    "viewGoodsNum-被访问商品数;salingGoodsNum-动销商品数;returnNum-退单数;returnAmount-退单金额;默认按支付金额降序排序"),
    })
    @GetMapping("export")
    public JsonResult export(HttpServletRequest request, HttpServletResponse response, Date startTime, Date endTime, String storeName,
                             @RequestParam(value = "type", required = false, defaultValue = "desc") String type,
                             @RequestParam(value = "sort", required = false, defaultValue = "orderPayAmount") String sort) {
        StoreDayExample example = new StoreDayExample();
        example.setStatsTimeAfter(startTime);
        example.setStatsTimeBefore(endTime);
        example.setStoreNameLike(storeName);
        example.setOrderBy(sort + " " + type);
        storeDayModel.storeReportExport(request, response, example);
        return null;
    }

    /**
     * 店铺类型占比
     *
     * @param list
     * @return
     */
    public List<StoreTypePercentVO> getStoreTypePercent(List<Store> list) {
        List<StoreTypePercentVO> result = new ArrayList<>();
        if (!CollectionUtils.isEmpty(list)) {
            //店铺总数，用于计算各类型占比
            int totalNum = list.size();
            //key为类型，value为店铺数量
            Map<Integer, Integer> map = new HashMap<>();
            for (Store store : list) {
                if (map.containsKey(store.getIsOwnStore())) {
                    map.put(store.getIsOwnStore(), map.get(store.getIsOwnStore()) + 1);
                } else {
                    //第一次进来默认1
                    map.put(store.getIsOwnStore(), 1);
                }
            }
            for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
                int storeType = entry.getKey();
                int storeNum = entry.getValue();
                StoreTypePercentVO vo = new StoreTypePercentVO();
                if (storeType == StoreConst.IS_OWN_STORE) {
                    vo.setTypeName("自营店铺");
                } else {
                    vo.setTypeName("入驻店铺");
                }
                vo.setStoreNum(storeNum);
                BigDecimal per = new BigDecimal(storeNum).multiply(new BigDecimal(100)).divide(new BigDecimal(totalNum), 2, BigDecimal.ROUND_HALF_UP);
                vo.setStoreNumPercent(per.toString() + "%");
                result.add(vo);
            }
        }
        return result;
    }

    /**
     * 店铺等级分布占比
     *
     * @param list
     * @return
     */
    public List<StoreGradePercentVO> getStoreGradePercent(List<Store> list, String webSite) {
        List<StoreGradePercentVO> result = new ArrayList<>();
        if (CollectionUtils.isEmpty(list)) {
            return result;
        }
        //店铺总数，用于计算各等级占比
        int totalNum = list.size();
        //key为等级名称，value为店铺数量
        Map<String, Integer> dataMap = new HashMap<>();
        for (Store store : list) {
            String gradeName;
            if(WebSiteConstant.MEMBER_DISTRIBUTOR.equals(webSite)){
                StoreSiteInfoExample example = new StoreSiteInfoExample();
                example.setStoreId(store.getStoreId());
                example.setWebSite(webSite);
                StoreSiteInfo storeSiteInfo = storeSiteInfoModel.getStoreSiteInfo(example);
                gradeName = null != storeSiteInfo ? storeSiteInfo.getStoreGradeName() : ProvinceJson.defaultProvinceName;
            }else {
               gradeName = StringUtil.isEmpty(store.getStoreGradeName()) ? ProvinceJson.defaultProvinceName : store.getStoreGradeName();
            }
            if (dataMap.containsKey(gradeName)) {
                dataMap.put(gradeName, dataMap.get(gradeName) + 1);
            } else {
                //第一次进来默认1
                dataMap.put(gradeName, 1);
            }

        }
        List<Map.Entry<String, Integer>> mapList = new ArrayList<>(dataMap.entrySet());
        //排序
        Collections.sort(mapList, (o1, o2) -> o2.getValue().compareTo(o1.getValue()));
        for (Map.Entry<String, Integer> entry : mapList) {
            int storeNum = entry.getValue();
            StoreGradePercentVO vo = new StoreGradePercentVO();
            vo.setGradeName(entry.getKey());
            vo.setStoreNum(storeNum);
            BigDecimal per = new BigDecimal(storeNum).multiply(new BigDecimal(100)).divide(new BigDecimal(totalNum), 2, BigDecimal.ROUND_HALF_UP);
            vo.setStoreNumPercent(per.toString() + "%");
            result.add(vo);
        }
        //等级大于10，记录前10个，剩余记为其他
        if (result.size() > 10) {
            //其他等级
            int otherNum = totalNum;
            //其他等级占比
            BigDecimal otherPer = new BigDecimal(100);
            for (int i = 0; i < result.size() && i < 10; i++) {
                StoreGradePercentVO dto = result.get(i);

                Integer storeNum = dto.getStoreNum();

                StoreGradePercentVO vo = new StoreGradePercentVO();
                vo.setGradeName(dto.getGradeName());
                vo.setStoreNum(storeNum);
                BigDecimal numPer = new BigDecimal(storeNum).multiply(new BigDecimal(100)).divide(new BigDecimal(totalNum), 2, BigDecimal.ROUND_HALF_UP);
                vo.setStoreNumPercent(numPer.toString() + "%");
                result.add(vo);

                //数据计算
                otherNum = otherNum - storeNum;
                otherPer = otherPer.subtract(numPer);
            }
            //其他
            if (otherNum > 0) {
                StoreGradePercentVO vo = new StoreGradePercentVO();
                vo.setGradeName("其他");
                vo.setStoreNum(otherNum);
                vo.setStoreNumPercent(otherPer.toString() + "%");
                result.add(vo);
            }
        }
        return result;
    }

    /**
     * 地域分布
     *
     * @param list
     * @return
     */
    public List<ProvincePercentVO> getRegionDistributionPercent(List<StoreStatisticsDTO> list) {
        List<ProvincePercentVO> result = new ArrayList<>();
        if (CollectionUtils.isEmpty(list)) {
            return result;
        }
        //查询总店铺数，用于计算各省份占比
        StoreExample example = new StoreExample();
        example.setStateNotEquals(StoreConst.STORE_STATE_DELETE);
        int totalNum = storeModel.getStoreCount(example);
        //key为省份名称，value为店铺数量
        Map<String, Integer> dataMap = new HashMap<>();
        for (StoreStatisticsDTO dto : list) {
            String provinceCode = dto.getProvinceCode();
            //如果编码为空，按未知处理
            if (StringUtil.isEmpty(dto.getProvinceCode())) {
                provinceCode = ProvinceJson.defaultProvinceCode;
            }
            //如果省份为空，按未知处理
            String provinceName = ProvinceJson.provinceMap.getOrDefault(provinceCode, ProvinceJson.defaultProvinceName);
            //店铺数量
            Integer storeNum = dto.getStoreNum();
            if (dataMap.containsKey(provinceName)) {
                dataMap.put(provinceName, dataMap.get(provinceName) + storeNum);
            } else {
                dataMap.put(provinceName, storeNum);
            }
        }
        List<Map.Entry<String, Integer>> mapList = new ArrayList<>(dataMap.entrySet());
        //排序
        Collections.sort(mapList, (o1, o2) -> o2.getValue().compareTo(o1.getValue()));
        //循环列表,构造返回数据
        for (Map.Entry<String, Integer> entry : mapList) {
            Integer storeNum = entry.getValue();
            ProvincePercentVO vo = new ProvincePercentVO();
            vo.setProvinceName(entry.getKey());
            vo.setStoreNum(storeNum);
            BigDecimal numPer = new BigDecimal(storeNum).multiply(new BigDecimal(100)).divide(new BigDecimal(totalNum), 2, BigDecimal.ROUND_HALF_UP);
            vo.setStoreNumPercent(numPer.toString() + "%");
            result.add(vo);
        }
        //省份大于10，记录前10个，剩余记为其他
        if (result.size() > 10) {
            //其他省份店铺
            int otherNum = totalNum;
            //其他省份占比
            BigDecimal otherPer = new BigDecimal(100);
            for (int i = 0; i < result.size() && i < 10; i++) {
                ProvincePercentVO dto = result.get(i);

                Integer storeNum = dto.getStoreNum();

                ProvincePercentVO vo = new ProvincePercentVO();
                vo.setProvinceName(dto.getProvinceName());
                vo.setStoreNum(storeNum);
                BigDecimal numPer = new BigDecimal(storeNum).multiply(new BigDecimal(100)).divide(new BigDecimal(totalNum), 2, BigDecimal.ROUND_HALF_UP);
                vo.setStoreNumPercent(numPer.toString() + "%");
                result.add(vo);

                //数据计算
                otherNum = otherNum - storeNum;
                otherPer = otherPer.subtract(numPer);
            }
            //其他
            if (otherNum > 0) {
                ProvincePercentVO vo = new ProvincePercentVO();
                vo.setProvinceName("其他");
                vo.setStoreNum(otherNum);
                vo.setStoreNumPercent(otherPer.toString() + "%");
                result.add(vo);
            }
        }
        return result;
    }
}
