package com.starry.admin.modules.statistics.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.starry.admin.modules.clerk.module.entity.PlayClerkLevelInfoEntity;
import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity;
import com.starry.admin.modules.clerk.service.IPlayClerkLevelInfoService;
import com.starry.admin.modules.clerk.service.IPlayClerkUserInfoService;
import com.starry.admin.modules.order.module.constant.OrderConstant;
import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity;
import com.starry.admin.modules.order.service.IPlayOrderInfoService;
import com.starry.admin.modules.personnel.module.entity.PlayPersonnelGroupInfoEntity;
import com.starry.admin.modules.personnel.service.IPlayPersonnelGroupInfoService;
import com.starry.admin.modules.statistics.module.vo.ClerkPerformanceDetailQueryVo;
import com.starry.admin.modules.statistics.module.vo.ClerkPerformanceDetailResponseVo;
import com.starry.admin.modules.statistics.module.vo.ClerkPerformanceOverviewQueryVo;
import com.starry.admin.modules.statistics.module.vo.ClerkPerformanceOverviewResponseVo;
import com.starry.admin.modules.statistics.module.vo.PlayClerkPerformanceInfoQueryVo;
import com.starry.admin.modules.statistics.module.vo.PlayClerkPerformanceInfoReturnVo;
import com.starry.admin.modules.statistics.service.IPlayClerkPerformanceService;
import com.starry.admin.utils.DateRangeUtils;
import com.starry.common.result.R;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 店员业绩查询对
 *
 * @author admin
 * @since 2024/6/15 下午3:15
 **/
@Api(tags = "店员业绩统计", description = "店员业绩统计相关接口，包括按日期、月份查询等操作")
@RestController
@RequestMapping("/statistics/performance")
public class PlayClerkPerformanceController {

    @Resource
    private IPlayClerkUserInfoService clerkUserInfoService;

    @Resource
    private IPlayOrderInfoService playOrderInfoService;

    @Resource
    private IPlayClerkLevelInfoService playClerkLevelInfoService;

    @Resource
    private IPlayPersonnelGroupInfoService playPersonnelGroupInfoService;

    @Resource
    private IPlayClerkPerformanceService playClerkPerformanceService;

    @ApiOperation(value = "分页查询店员业绩", notes = "分页查询店员业绩统计信息")
    @ApiResponses({
            @ApiResponse(code = 200, message = "操作成功", response = PlayClerkPerformanceInfoReturnVo.class, responseContainer = "Page")})
    @PostMapping("/listByPage")
    public R listByPage(
            @ApiParam(value = "查询条件", required = true) @Validated @RequestBody PlayClerkPerformanceInfoQueryVo vo) {
        IPage<PlayClerkUserInfoEntity> page = clerkUserInfoService.selectByPage(vo);
        IPage<PlayClerkPerformanceInfoReturnVo> voPage = page.convert(user -> {
            List<PlayClerkLevelInfoEntity> clerkLevelInfoEntity = playClerkLevelInfoService.selectAll();
            String rawStart = vo.getEndOrderTime() != null && vo.getEndOrderTime().size() > 0
                    ? vo.getEndOrderTime().get(0)
                    : null;
            String rawEnd = vo.getEndOrderTime() != null && vo.getEndOrderTime().size() > 1
                    ? vo.getEndOrderTime().get(1)
                    : null;
            String startTime = DateRangeUtils.normalizeStartOptional(rawStart);
            String endTime = DateRangeUtils.normalizeEndOptional(rawEnd);
            List<PlayOrderInfoEntity> orderInfoEntities = playOrderInfoService.clerkSelectOrderInfoList(user.getId(),
                    startTime, endTime);
            List<PlayPersonnelGroupInfoEntity> groupInfoEntities = playPersonnelGroupInfoService.selectAll();

            return playClerkPerformanceService.getClerkPerformanceInfo(user, orderInfoEntities, clerkLevelInfoEntity,
                    groupInfoEntities, startTime, endTime);
        });
        voPage.setRecords(voPage.getRecords().stream()
                .sorted(Comparator.comparing(PlayClerkPerformanceInfoReturnVo::getOrderNumber).reversed())
                .collect(Collectors.toList()));

        return R.ok(voPage);
    }

    @ApiOperation(value = "店员业绩概览", notes = "汇总店员业绩榜单和汇总数据")
    @PostMapping("/overview")
    public R overview(
            @ApiParam(value = "查询条件", required = true) @Validated @RequestBody ClerkPerformanceOverviewQueryVo vo) {
        return R.ok(playClerkPerformanceService.queryOverview(vo));
    }

    @ApiOperation(value = "店员业绩详情", notes = "查看单个店员的业绩构成和趋势")
    @PostMapping("/detail")
    public R detail(
            @ApiParam(value = "查询条件", required = true) @Validated @RequestBody ClerkPerformanceDetailQueryVo vo) {
        return R.ok(playClerkPerformanceService.queryDetail(vo));
    }

    @ApiOperation(value = "按日查询业绩", notes = "按日期查询店员业绩统计信息")
    @ApiResponses({@ApiResponse(code = 200, message = "操作成功")})
    @PostMapping("/listByTime")
    public R listByTime(
            @ApiParam(value = "查询条件", required = true) @Validated @RequestBody PlayClerkPerformanceInfoQueryVo vo) {
        // 时间范围
        List<String> dates = getDateRangeByDay(vo.getEndOrderTime().get(0), vo.getEndOrderTime().get(1));
        // 指定时间内所有订单
        // List<PlayOrderInfoEntity> orderInfoEntities =
        // playOrderInfoService.listByTime("", vo.getEndOrderTime().get(0),
        // vo.getEndOrderTime().get(1), Stream.of("2",
        // "3").collect(Collectors.toList()));
        List<PlayOrderInfoEntity> orderInfoEntities = playOrderInfoService.listByTime("", vo.getEndOrderTime().get(0),
                vo.getEndOrderTime().get(1), new ArrayList<>());
        List<PlayClerkPerformanceInfoReturnVo> orders = new ArrayList<>(dates.size());
        for (String date : dates) {
            orders.add(getPerformanceInfo(date, orderInfoEntities));
        }
        Map<String, Object> resultMap = new HashMap<>(orders.size());
        resultMap.put("dates", dates);
        resultMap.put("orderToTal", getTotalInfo(orderInfoEntities));
        resultMap.put("list", orders);
        return R.ok(resultMap);
    }

    @ApiOperation(value = "按月查询业绩", notes = "按月份查询店员业绩统计信息")
    @ApiResponses({@ApiResponse(code = 200, message = "操作成功")})
    @PostMapping("/listByMonth")
    public R listByMonth(
            @ApiParam(value = "查询条件", required = true) @Validated @RequestBody PlayClerkPerformanceInfoQueryVo vo) {
        String startTime = LocalDate.of(Integer.parseInt(vo.getEndOrderTime().get(0).split("-")[0]),
                Integer.parseInt(vo.getEndOrderTime().get(0).split("-")[1]), 1).toString() + " 00:00:00";
        LocalDate endDate = LocalDate.of(Integer.parseInt(vo.getEndOrderTime().get(1).split("-")[0]),
                Integer.parseInt(vo.getEndOrderTime().get(1).split("-")[1]), 1);
        String endTime = endDate.with(TemporalAdjusters.lastDayOfMonth()) + " 23:59:59";

        List<String> dates = getDateRangeByMonth(startTime, endTime);
        // 指定时间内所有订单
        // List<PlayOrderInfoEntity> orderInfoEntities =
        // playOrderInfoService.listByTime("", startTime, endTime,
        // Stream.of("4").collect(Collectors.toList()));
        List<PlayOrderInfoEntity> orderInfoEntities = playOrderInfoService.listByTime("", startTime, endTime,
                new ArrayList<>());
        List<PlayClerkPerformanceInfoReturnVo> orders = new ArrayList<>(dates.size());
        for (String date : dates) {
            orders.add(getPerformanceInfo(date, orderInfoEntities));
        }
        Map<String, Object> resultMap = new HashMap<>(orders.size());
        resultMap.put("dates", dates);
        resultMap.put("orderToTal", getTotalInfo(orderInfoEntities));
        resultMap.put("list", orders);
        return R.ok(resultMap);
    }

    /**
     * 根据订单开始时间和结束时间，组装订单统计信息的查询时间范围
     *
     * @param startTime
     *            开始时间
     * @param endTime
     *            结束时间
     * @return 时间范围
     */
    public List<String> getDateRangeByDay(String startTime, String endTime) {
        List<String> dates = new ArrayList<>();
        LocalDateTime date1 = LocalDateTime.parse(startTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        LocalDateTime date2 = LocalDateTime.parse(endTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        while (!date1.isAfter(date2)) {
            dates.add(date1.toLocalDate().toString());
            date1 = date1.plusDays(1);

        }
        return dates;
    }

    /**
     * 根据订单开始时间和结束时间，组装订单统计信息的查询时间范围
     *
     * @param startTime
     *            开始时间
     * @param endTime
     *            结束时间
     * @return 时间范围
     */
    public List<String> getDateRangeByMonth(String startTime, String endTime) {
        List<String> dates = new ArrayList<>();
        LocalDateTime date1 = LocalDateTime.parse(startTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        LocalDateTime date2 = LocalDateTime.parse(endTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        while (!date1.isAfter(date2)) {
            dates.add(date1.getYear() + "-" + date1.getMonthValue());
            date1 = date1.plusMonths(1);

        }
        return dates;
    }

    public PlayClerkPerformanceInfoReturnVo getTotalInfo(List<PlayOrderInfoEntity> orderInfoEntities) {
        Set<String> customIds = new HashSet<>();
        int orderContinueNumber = 0;
        int orderRefundNumber = 0;
        int ordersExpiredNumber = 0;
        int completedOrders = 0;
        BigDecimal orderMoney = BigDecimal.ZERO;
        BigDecimal finalAmount = BigDecimal.ZERO;
        BigDecimal orderFirstAmount = BigDecimal.ZERO;
        BigDecimal orderTotalAmount = BigDecimal.ZERO;
        BigDecimal orderRewardAmount = BigDecimal.ZERO;
        BigDecimal orderRefundAmount = BigDecimal.ZERO;
        BigDecimal estimatedRevenue = BigDecimal.ZERO;
        for (PlayOrderInfoEntity orderInfoEntity : orderInfoEntities) {
            if (!isCompletedOrder(orderInfoEntity)) {
                continue;
            }
            completedOrders++;
            customIds.add(orderInfoEntity.getPurchaserBy());
            finalAmount = finalAmount.add(orderInfoEntity.getFinalAmount());
            orderMoney = orderMoney.add(orderInfoEntity.getOrderMoney());
            if ("1".equals(orderInfoEntity.getFirstOrder())) {
                orderFirstAmount = orderFirstAmount.add(orderInfoEntity.getFinalAmount());
            } else {
                orderContinueNumber++;
                orderTotalAmount = orderTotalAmount.add(orderInfoEntity.getFinalAmount());
            }
            if ("2".equals(orderInfoEntity.getPlaceType())) {
                orderRewardAmount = orderRewardAmount.add(orderInfoEntity.getFinalAmount());
            }
            if ("1".equals(orderInfoEntity.getRefundType())) {
                orderRefundNumber++;
                orderRefundAmount = orderRefundAmount.add(orderInfoEntity.getRefundAmount());
            }
            if ("1".equals(orderInfoEntity.getOrdersExpiredState())) {
                ordersExpiredNumber++;
            }
        }
        PlayClerkPerformanceInfoReturnVo returnVo = new PlayClerkPerformanceInfoReturnVo();
        returnVo.setOrderNumber(completedOrders);
        returnVo.setOrderContinueNumber(orderContinueNumber);
        returnVo.setOrderRefundNumber(orderRefundNumber);
        returnVo.setOrdersExpiredNumber(ordersExpiredNumber);
        returnVo.setFinalAmount(finalAmount);
        returnVo.setOrderFirstAmount(orderFirstAmount);
        returnVo.setOrderTotalAmount(orderTotalAmount);
        returnVo.setOrderRewardAmount(orderRewardAmount);
        returnVo.setOrderRefundAmount(orderRefundAmount);
        returnVo.setCustomNumber(customIds.size());
        returnVo.setEstimatedRevenue(estimatedRevenue);
        returnVo.setOrderMoney(estimatedRevenue);
        return returnVo;
    }
    /**
     * 组装统计数据
     *
     * @param performanceDate
     *            统计时间
     * @param orderInfoEntities
     *            订单列表
     * @return 统计数据
     */

    public PlayClerkPerformanceInfoReturnVo getPerformanceInfo(String performanceDate,
            List<PlayOrderInfoEntity> orderInfoEntities) {

        List<PlayOrderInfoEntity> itemOrderInfo = new ArrayList<>();
        for (PlayOrderInfoEntity orderInfoEntity : orderInfoEntities) {
            // 接单时间，在指定日期的 00:00:00点到23:59：59之间
            if (orderInfoEntity.getPurchaserTime()
                    .isAfter(LocalDateTime.parse(performanceDate + " 00:00:00",
                            DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))
                    && orderInfoEntity.getPurchaserTime().isBefore(LocalDateTime.parse(performanceDate + " 23:59:59",
                            DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))) {
                itemOrderInfo.add(orderInfoEntity);
            }
        }

        Set<String> customIds = new HashSet<>();
        int orderContinueNumber = 0;
        int orderRefundNumber = 0;
        int ordersExpiredNumber = 0;
        int completedOrders = 0;
        BigDecimal orderMoney = BigDecimal.ZERO;
        BigDecimal finalAmount = BigDecimal.ZERO;
        BigDecimal orderFirstAmount = BigDecimal.ZERO;
        BigDecimal orderTotalAmount = BigDecimal.ZERO;
        BigDecimal orderRewardAmount = BigDecimal.ZERO;
        BigDecimal orderRefundAmount = BigDecimal.ZERO;
        BigDecimal estimatedRevenue = BigDecimal.ZERO;
        for (PlayOrderInfoEntity orderInfoEntity : itemOrderInfo) {
            if (!isCompletedOrder(orderInfoEntity)) {
                continue;
            }
            completedOrders++;
            customIds.add(orderInfoEntity.getPurchaserBy());
            finalAmount = finalAmount.add(orderInfoEntity.getFinalAmount());
            orderMoney = orderMoney.add(orderInfoEntity.getOrderMoney());
            if ("1".equals(orderInfoEntity.getFirstOrder())) {
                orderFirstAmount = orderFirstAmount.add(orderInfoEntity.getFinalAmount());
            } else {
                orderContinueNumber++;
                orderTotalAmount = orderTotalAmount.add(orderInfoEntity.getFinalAmount());
            }
            if ("2".equals(orderInfoEntity.getPlaceType())) {
                orderRewardAmount = orderRewardAmount.add(orderInfoEntity.getFinalAmount());
            }
            if ("1".equals(orderInfoEntity.getRefundType())) {
                orderRefundNumber++;
                orderRefundAmount = orderRefundAmount.add(orderInfoEntity.getRefundAmount());
            }
            if ("1".equals(orderInfoEntity.getOrdersExpiredState())) {
                ordersExpiredNumber++;
            }
        }
        PlayClerkPerformanceInfoReturnVo returnVo = new PlayClerkPerformanceInfoReturnVo();
        returnVo.setPerformanceDate(performanceDate);
        returnVo.setOrderNumber(completedOrders);
        returnVo.setOrderContinueNumber(orderContinueNumber);
        returnVo.setOrderRefundNumber(orderRefundNumber);
        returnVo.setOrdersExpiredNumber(ordersExpiredNumber);
        returnVo.setFinalAmount(finalAmount);
        returnVo.setOrderFirstAmount(orderFirstAmount);
        returnVo.setOrderTotalAmount(orderTotalAmount);
        returnVo.setOrderRewardAmount(orderRewardAmount);
        returnVo.setOrderRefundAmount(orderRefundAmount);
        returnVo.setCustomNumber(customIds.size());
        returnVo.setEstimatedRevenue(estimatedRevenue);
        returnVo.setOrderMoney(estimatedRevenue);
        return returnVo;
    }

    private boolean isCompletedOrder(PlayOrderInfoEntity orderInfoEntity) {
        return orderInfoEntity != null
                && OrderConstant.OrderStatus.COMPLETED.getCode().equals(orderInfoEntity.getOrderStatus());
    }

}
