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

import com.slodon.b2b2c.core.constant.GoodsConst;
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.TimeUtil;
import com.slodon.b2b2c.core.util.UserUtil;
import com.slodon.b2b2c.core.util.WebUtil;
import com.slodon.b2b2c.enums.StatsTimeType;
import com.slodon.b2b2c.goods.example.GoodsExample;
import com.slodon.b2b2c.model.goods.GoodsModel;
import com.slodon.b2b2c.model.statistics.GoodsDayModel;
import com.slodon.b2b2c.model.statistics.StoreDayModel;
import com.slodon.b2b2c.seller.pojo.Vendor;
import com.slodon.b2b2c.statistics.example.GoodsDayExample;
import com.slodon.b2b2c.statistics.example.StoreDayExample;
import com.slodon.b2b2c.statistics.pojo.StoreDay;
import com.slodon.b2b2c.statistics.pojo.base.GoodsBase;
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 = "seller-商品分析")
@RestController
@RequestMapping("v3/statistics/seller/goods/analysis")
public class SellerGoodsAnalysisController extends BaseController {

    @Resource
    private StoreDayModel storeDayModel;
    @Resource
    private GoodsDayModel goodsDayModel;
    @Resource
    private StatsModelUtil statsModelUtil;
    @Resource
    private GoodsModel goodsModel;

    @ApiOperation("商品总览(商品数)")
    @ApiImplicitParam(name = "webSite", value = "站点")
    @GetMapping("goodsNum")
    public JsonResult<SellerGoodsNumVO> goodsNum(HttpServletRequest request,@RequestParam(name = "webSite", required = false,defaultValue = "1") String webSite) {
        Vendor vendor = UserUtil.getUser(request, Vendor.class);

        SellerGoodsNumVO vo = new SellerGoodsNumVO();
        GoodsExample example = new GoodsExample();
        example.setStoreId(vendor.getStoreId());
        example.setStateNotEquals(GoodsConst.GOODS_STATE_DELETE);
        example.setWebSite(webSite);
        vo.setGoodsTotalNum(goodsModel.getGoodsCount(example));
        example.setState(GoodsConst.GOODS_STATE_UPPER);
        vo.setOnSaleGoodsNum(goodsModel.getGoodsCount(example));
        example.setState(GoodsConst.GOODS_STATE_LOWER_BY_SYSTEM);
        vo.setViolationGoodsNum(goodsModel.getGoodsCount(example));
        return SldResponse.success(vo);
    }

    @ApiOperation("商品总览")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "startTime", value = "开始时间", required = true),
            @ApiImplicitParam(name = "endTime", value = "结束时间", required = true),
            @ApiImplicitParam(name = "webSite", value = "站点")
    })
    @GetMapping("goodsOverview")
    public JsonResult<GoodsOverviewVO> goodsOverview(HttpServletRequest request, Date startTime, Date endTime,@RequestParam(name = "webSite", required = false,defaultValue = "1") String webSite) {
        Vendor vendor = UserUtil.getUser(request, Vendor.class);

        StatsTimeType timeType = StatsTimeType.checkTimeType(startTime, endTime, false);
        List<? extends StoreBase> list = statsModelUtil.getStoreList(timeType, startTime, endTime, webSite, 1, "sale", vendor.getStoreId(), null);
        GoodsOverviewVO vo = new GoodsOverviewVO();
        if (!CollectionUtils.isEmpty(list)) {
            StoreBase storeBase = list.get(0);
            //上期数据
            StoreBase 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 StoreBase> previousList = statsModelUtil.getStoreList(timeType, preStartTime, preEndTime, webSite,1, "sale", vendor.getStoreId(), null);
                if (!CollectionUtils.isEmpty(previousList)) {
                    previousData = previousList.get(0);
                }
            }
            if (storeBase != null) {
                vo = new GoodsOverviewVO(storeBase, previousData);
            }
        }
        return SldResponse.success(vo);
    }

    @ApiOperation("商品动销趋势")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "startTime", value = "开始时间", required = true),
            @ApiImplicitParam(name = "endTime", value = "结束时间", required = true),
            @ApiImplicitParam(name = "webSite", value = "站点")
    })
    @GetMapping("goodsSalesTrend")
    public JsonResult<GoodsSalesTrendVO> goodsSalesTrend(HttpServletRequest request, Date startTime, Date endTime,@RequestParam(value = "webSite",required = false,defaultValue = "1") String webSite) {
        Vendor vendor = UserUtil.getUser(request, Vendor.class);

        StatsTimeType timeType = StatsTimeType.checkTimeType(startTime, endTime, true);
        List<MovableGoodsVO> list = statsModelUtil.getStoreTrendList(timeType, startTime, endTime, webSite, vendor.getStoreId());
        GoodsSalesTrendVO vo = new GoodsSalesTrendVO();
        //新增商品数列表
        List<MovableGoodsVO> newGoodsList = new ArrayList<>();
        //动销商品数列表
        List<MovableGoodsVO> movableGoodsList = new ArrayList<>();
        //下单数列表
        List<MovableGoodsVO> orderNumList = new ArrayList<>();
        //下单金额列表
        List<MovableGoodsVO> orderAmountList = new ArrayList<>();
        //支付订单数列表
        List<MovableGoodsVO> orderPayNumList = new ArrayList<>();
        //支付金额列表
        List<MovableGoodsVO> orderPayAmountList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(list)) {
            list.forEach(trendVO -> {
                //新增商品数
                MovableGoodsVO newGoods = new MovableGoodsVO();
                newGoods.setStatsTime(trendVO.getStatsTime());
                newGoods.setNewGoodsNum(trendVO.getNewGoodsNum());
                newGoodsList.add(newGoods);
                //动销商品数
                MovableGoodsVO movableGoods = new MovableGoodsVO();
                movableGoods.setStatsTime(trendVO.getStatsTime());
                movableGoods.setMovableGoodsNum(trendVO.getMovableGoodsNum());
                movableGoodsList.add(movableGoods);
                //下单数
                MovableGoodsVO orderNum = new MovableGoodsVO();
                orderNum.setStatsTime(trendVO.getStatsTime());
                orderNum.setOrderSubmitNum(trendVO.getOrderSubmitNum());
                orderNumList.add(orderNum);
                //下单金额
                MovableGoodsVO orderAmount = new MovableGoodsVO();
                orderAmount.setStatsTime(trendVO.getStatsTime());
                orderAmount.setOrderSubmitAmount(trendVO.getOrderSubmitAmount());
                orderAmountList.add(orderAmount);
                //支付订单数
                MovableGoodsVO orderPayNum = new MovableGoodsVO();
                orderPayNum.setStatsTime(trendVO.getStatsTime());
                orderPayNum.setOrderPayNum(trendVO.getOrderPayNum());
                orderPayNumList.add(orderPayNum);
                //支付金额
                MovableGoodsVO orderPayAmount = new MovableGoodsVO();
                orderPayAmount.setStatsTime(trendVO.getStatsTime());
                orderPayAmount.setOrderPayAmount(trendVO.getOrderPayAmount());
                orderPayAmountList.add(orderPayAmount);
            });
            vo.setNewGoodsList(newGoodsList);
            vo.setMovableGoodsList(movableGoodsList);
            vo.setOrderNumList(orderNumList);
            vo.setOrderAmountList(orderAmountList);
            vo.setOrderPayNumList(orderPayNumList);
            vo.setOrderPayAmountList(orderPayAmountList);
        }
        return SldResponse.success(vo);
    }

    @ApiOperation("商品销售趋势-TOP10")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "startTime", value = "开始时间", required = true),
            @ApiImplicitParam(name = "endTime", value = "结束时间", required = true),
            @ApiImplicitParam(name = "webSite", value = "站点"),
            @ApiImplicitParam(name = "sort", value = "排序:1-销售额；2-销量 默认不传按销售额降序")
    })
    @GetMapping("goodsSalesRank")
    public JsonResult<List<GoodsChangeTrendVO>> goodsSalesRank(HttpServletRequest request, Date startTime, Date endTime,@RequestParam(name = "webSite", required = false,defaultValue = "1") String webSite, Integer sort) {
        Vendor vendor = UserUtil.getUser(request, Vendor.class);

        StatsTimeType timeType = StatsTimeType.checkTimeType(startTime, endTime, true);
        //如果查询24小时，先按天查询前十条数据
        StatsTimeType timeType2 = timeType;
        if (timeType == StatsTimeType.HOUR) {
            timeType2 = StatsTimeType.DAY;
        }
        List<? extends GoodsBase> list = statsModelUtil.getGoodsList(timeType2, startTime, endTime,webSite, sort, "sale", vendor.getStoreId());
        List<GoodsChangeTrendVO> vos = getGoodsSalesRank(list, timeType, startTime, endTime);
        return SldResponse.success(vos);
    }

    @ApiOperation("商品报表(按天)")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "startTime", value = "开始时间", required = true),
            @ApiImplicitParam(name = "endTime", value = "结束时间", required = true),
            @ApiImplicitParam(name = "type", value = "排序类型；desc-降序;asc-升序;默认类型为降序"),
            @ApiImplicitParam(name = "sort", value = "排序:stats_time-时间;order_pay_amount-支付金额;order_submit_amount-下单金额;" +
                    "order_pay_num-支付订单数;order_submit_num-下单数;new_goods_num-新增商品数;saling_goods_num-动销商品数;默认按时间降序排序"),
            @ApiImplicitParam(name = "pageSize", value = "分页大小", defaultValue = "20", paramType = "query"),
            @ApiImplicitParam(name = "current", value = "当前页面位置", defaultValue = "1", paramType = "query")
    })
    @GetMapping("dayReport")
    public JsonResult<PageVO<GoodsReportDayVO>> dayReport(HttpServletRequest request, Date startTime, Date endTime,
                                                          @RequestParam(value = "type", required = false, defaultValue = "desc") String type,
                                                          @RequestParam(value = "sort", required = false, defaultValue = "stats_time") String sort) {
        Vendor vendor = UserUtil.getUser(request, Vendor.class);

        PagerInfo pager = WebUtil.handlerPagerInfo(request);
        StoreDayExample example = new StoreDayExample();
        example.setStoreId(vendor.getStoreId());
        example.setStatsTimeAfter(startTime);
        example.setStatsTimeBefore(endTime);
        example.setOrderBy(sort + " " + type);
        List<StoreDay> list = storeDayModel.getStoreDayList(example, pager);
        List<GoodsReportDayVO> vos = new ArrayList<>();
        if (!CollectionUtils.isEmpty(list)) {
            list.forEach(platformDay -> {
                vos.add(new GoodsReportDayVO(platformDay));
            });
        }
        return SldResponse.success(new PageVO<>(vos, pager));
    }

    @ApiOperation("商品报表(按商品)")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "startTime", value = "开始时间", required = true),
            @ApiImplicitParam(name = "endTime", value = "结束时间", required = true),
            @ApiImplicitParam(name = "goodsName", value = "商品名称"),
            @ApiImplicitParam(name = "type", value = "排序类型；desc-降序;asc-升序;默认类型为降序"),
            @ApiImplicitParam(name = "sort", value = "排序:visitorNum-访客数;saleNum-销量;saleAmount-支付金额;" +
                    "orderSubmitAmount-下单金额;orderPayNum-支付订单数;orderSubmitNum-下单数;viewNum-浏览量;collectionNum-收藏人数;" +
                    "addCartMemberNum-加购人数;returnNum-退单数;returnAmount-退单金额;默认按访客数降序排序"),
            @ApiImplicitParam(name = "pageSize", value = "分页大小", defaultValue = "20", paramType = "query"),
            @ApiImplicitParam(name = "current", value = "当前页面位置", defaultValue = "1", paramType = "query")
    })
    @GetMapping("goodsReport")
    public JsonResult<PageVO<SellerGoodsReportVO>> goodsReport(HttpServletRequest request, Date startTime, Date endTime, String goodsName,
                                                               @RequestParam(value = "type", required = false, defaultValue = "desc") String type,
                                                               @RequestParam(value = "sort", required = false, defaultValue = "visitorNum") String sort) {
        Vendor vendor = UserUtil.getUser(request, Vendor.class);

        PagerInfo pager = WebUtil.handlerPagerInfo(request);
        GoodsDayExample example = new GoodsDayExample();
        example.setStoreId(vendor.getStoreId());
        example.setStatsTimeAfter(startTime);
        example.setStatsTimeBefore(endTime);
        example.setGoodsNameLike(goodsName);
        example.setOrderBy(sort + " " + type);
        List<GoodsBase> list = goodsDayModel.getGoodsList(example, pager);
        List<SellerGoodsReportVO> vos = new ArrayList<>();
        if (!CollectionUtils.isEmpty(list)) {
            list.forEach(goodsBase -> {
                vos.add(new SellerGoodsReportVO(goodsBase));
            });
        }
        return SldResponse.success(new PageVO<>(vos, pager));
    }

    @ApiOperation("导出报表(按天)")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "startTime", value = "开始时间", required = true),
            @ApiImplicitParam(name = "endTime", value = "结束时间", required = true),
            @ApiImplicitParam(name = "type", value = "排序类型；desc-降序;asc-升序;默认类型为降序"),
            @ApiImplicitParam(name = "sort", value = "排序:stats_time-时间;order_pay_amount-支付金额;order_submit_amount-下单金额;" +
                    "order_pay_num-支付订单数;order_submit_num-下单数;new_goods_num-新增商品数;saling_goods_num-动销商品数;默认按时间降序排序")
    })
    @GetMapping("dayExport")
    public JsonResult dayExport(HttpServletRequest request, HttpServletResponse response, Date startTime, Date endTime,
                                @RequestParam(value = "type", required = false, defaultValue = "desc") String type,
                                @RequestParam(value = "sort", required = false, defaultValue = "stats_time") String sort) {
        Vendor vendor = UserUtil.getUser(request, Vendor.class);

        StoreDayExample example = new StoreDayExample();
        example.setStoreId(vendor.getStoreId());
        example.setStatsTimeAfter(startTime);
        example.setStatsTimeBefore(endTime);
        example.setOrderBy(sort + " " + type);
        storeDayModel.goodsReportExport(request, response, example);
        return null;
    }

    @ApiOperation("导出报表(按商品)")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "startTime", value = "开始时间", required = true),
            @ApiImplicitParam(name = "endTime", value = "结束时间", required = true),
            @ApiImplicitParam(name = "goodsName", value = "商品名称"),
            @ApiImplicitParam(name = "type", value = "排序类型；desc-降序;asc-升序;默认类型为降序"),
            @ApiImplicitParam(name = "sort", value = "排序:visitorNum-访客数;saleNum-销量;saleAmount-支付金额;" +
                    "orderSubmitAmount-下单金额;orderPayNum-支付订单数;orderSubmitNum-下单数;viewNum-浏览量;collectionNum-收藏人数;" +
                    "addCartMemberNum-加购人数;returnNum-退单数;returnAmount-退单金额;默认按访客数降序排序")
    })
    @GetMapping("goodsExport")
    public JsonResult goodsExport(HttpServletRequest request, HttpServletResponse response, Date startTime, Date endTime, String goodsName,
                                  @RequestParam(value = "type", required = false, defaultValue = "desc") String type,
                                  @RequestParam(value = "sort", required = false, defaultValue = "visitorNum") String sort) {
        Vendor vendor = UserUtil.getUser(request, Vendor.class);

        GoodsDayExample example = new GoodsDayExample();
        example.setStoreId(vendor.getStoreId());
        example.setStatsTimeAfter(startTime);
        example.setStatsTimeBefore(endTime);
        example.setGoodsNameLike(goodsName);
        example.setOrderBy(sort + " " + type);
        goodsDayModel.storeGoodsReportExport(request, response, example);
        return null;
    }

    /**
     * 变化趋势
     *
     * @param list
     * @return
     */
    public List<GoodsChangeTrendVO> getGoodsSalesRank(List<? extends GoodsBase> list, StatsTimeType timeType, Date startTime, Date endTime) {
        List<GoodsChangeTrendVO> result = new ArrayList<>();
        if (!CollectionUtils.isEmpty(list)) {
            //按照统计时间分组
            Map<String, List<GoodsChangeTrendVO.GoodsTrendVO>> timeMap = new HashMap<>();
            //商品id集合
            StringBuilder goodsIds = new StringBuilder();
            for (GoodsBase goodsBase : list) {
                goodsIds.append(",").append(goodsBase.getGoodsId());
            }
            //查询销售信息
            List<SalesTrendVO> trendList = statsModelUtil.getGoodsTrendList(timeType, startTime, endTime, goodsIds.toString().substring(1));
            if (!CollectionUtils.isEmpty(trendList)) {
                switch (timeType) {
                    case HOUR:
                        timeMap = getGoodsHourList(trendList);
                        break;
                    case DAY:
                    case WEEK:
                    case MONTH:
                        timeMap = getGoodsDayList(trendList, startTime, endTime);
                        break;
                    case YEAR:
                        timeMap = getGoodsMonthList(trendList);
                        break;
                }
            }
            timeMap.forEach((statsTime, voList) -> {
                GoodsChangeTrendVO vo = new GoodsChangeTrendVO();
                vo.setStatsTime(statsTime);
                vo.setGoodsList(voList);
                result.add(vo);
            });
            Collections.sort(result);
        }
        return result;
    }

    /**
     * 获取24小时数据
     *
     * @param list
     * @return
     */
    public Map<String, List<GoodsChangeTrendVO.GoodsTrendVO>> getGoodsHourList(List<SalesTrendVO> list) {
        Map<String, List<GoodsChangeTrendVO.GoodsTrendVO>> result = new HashMap<>();
        if (CollectionUtils.isEmpty(list)) {
            return result;
        }
        for (int i = 0; i < 24; i++) {
            String timeStr = i > 9 ? i + ":00" : "0" + i + ":00";
            for (SalesTrendVO vo : list) {
                //如果没有则存放到List
                GoodsChangeTrendVO.GoodsTrendVO goodsTrendVO = new GoodsChangeTrendVO.GoodsTrendVO();
                if (!vo.getStatsTime().equals(timeStr)) {
                    goodsTrendVO.setGoodsId(vo.getGoodsId());
                    goodsTrendVO.setGoodsName(vo.getGoodsName());
                    goodsTrendVO.setSaleAmount(BigDecimal.ZERO);
                    goodsTrendVO.setSaleNum(0);
                } else {
                    goodsTrendVO.setGoodsId(vo.getGoodsId());
                    goodsTrendVO.setGoodsName(vo.getGoodsName());
                    goodsTrendVO.setSaleAmount(vo.getOrderPayAmount());
                    goodsTrendVO.setSaleNum(vo.getOrderPayNum());
                }
                //按照统计时间分组
                if (result.containsKey(timeStr)) {
                    result.get(timeStr).add(goodsTrendVO);
                } else {
                    //商品列表
                    List<GoodsChangeTrendVO.GoodsTrendVO> goodsList = new ArrayList<>();
                    goodsList.add(goodsTrendVO);

                    result.put(timeStr, goodsList);
                }
            }
        }
        return result;
    }

    /**
     * 获取n天数据
     *
     * @param list
     * @param startTime
     * @param endTime
     * @return
     */
    public Map<String, List<GoodsChangeTrendVO.GoodsTrendVO>> getGoodsDayList(List<SalesTrendVO> list, Date startTime, Date endTime) {
        Map<String, List<GoodsChangeTrendVO.GoodsTrendVO>> result = new HashMap<>();
        if (CollectionUtils.isEmpty(list)) {
            return result;
        }
        for (Date i = startTime; i.before(endTime); i = TimeUtil.getDayAgoDate(i, 1)) {
            String timeStr = TimeUtil.dealMonthAndDay(i);
            for (SalesTrendVO vo : list) {
                //如果没有则存放到List
                GoodsChangeTrendVO.GoodsTrendVO goodsTrendVO = new GoodsChangeTrendVO.GoodsTrendVO();
                if (!vo.getStatsTime().equals(timeStr)) {
                    goodsTrendVO.setGoodsId(vo.getGoodsId());
                    goodsTrendVO.setGoodsName(vo.getGoodsName());
                    goodsTrendVO.setSaleAmount(BigDecimal.ZERO);
                    goodsTrendVO.setSaleNum(0);
                } else {
                    goodsTrendVO.setGoodsId(vo.getGoodsId());
                    goodsTrendVO.setGoodsName(vo.getGoodsName());
                    goodsTrendVO.setSaleAmount(vo.getOrderPayAmount());
                    goodsTrendVO.setSaleNum(vo.getOrderPayNum());
                }
                //按照统计时间分组
                if (result.containsKey(timeStr)) {
                    result.get(timeStr).add(goodsTrendVO);
                } else {
                    //商品列表
                    List<GoodsChangeTrendVO.GoodsTrendVO> goodsList = new ArrayList<>();
                    goodsList.add(goodsTrendVO);

                    result.put(timeStr, goodsList);
                }
            }
        }
        return result;
    }

    /**
     * 获取12个月数据
     *
     * @param list
     * @return
     */
    public Map<String, List<GoodsChangeTrendVO.GoodsTrendVO>> getGoodsMonthList(List<SalesTrendVO> list) {
        Map<String, List<GoodsChangeTrendVO.GoodsTrendVO>> result = new HashMap<>();
        if (CollectionUtils.isEmpty(list)) {
            return result;
        }
        for (int i = 1; i <= 12; i++) {
            String timeStr = i > 9 ? i + "" : "0" + i;
            for (SalesTrendVO vo : list) {
                //如果没有则存放到List
                GoodsChangeTrendVO.GoodsTrendVO goodsTrendVO = new GoodsChangeTrendVO.GoodsTrendVO();
                if (!vo.getStatsTime().equals(timeStr)) {
                    goodsTrendVO.setGoodsId(vo.getGoodsId());
                    goodsTrendVO.setGoodsName(vo.getGoodsName());
                    goodsTrendVO.setSaleAmount(BigDecimal.ZERO);
                    goodsTrendVO.setSaleNum(0);
                } else {
                    goodsTrendVO.setGoodsId(vo.getGoodsId());
                    goodsTrendVO.setGoodsName(vo.getGoodsName());
                    goodsTrendVO.setSaleAmount(vo.getOrderPayAmount());
                    goodsTrendVO.setSaleNum(vo.getOrderPayNum());
                }
                //按照统计时间分组
                if (result.containsKey(timeStr)) {
                    result.get(timeStr).add(goodsTrendVO);
                } else {
                    //商品列表
                    List<GoodsChangeTrendVO.GoodsTrendVO> goodsList = new ArrayList<>();
                    goodsList.add(goodsTrendVO);

                    result.put(timeStr, goodsList);
                }
            }
        }
        return result;
    }
}
