package com.greenorange.promotion.controller.course;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.greenorange.promotion.annotation.RequiresPermission;
import com.greenorange.promotion.annotation.SysLog;
import com.greenorange.promotion.common.BaseResponse;
import com.greenorange.promotion.common.ErrorCode;
import com.greenorange.promotion.common.ResultUtils;
import com.greenorange.promotion.constant.OrderStatusConstant;
import com.greenorange.promotion.constant.SystemConstant;
import com.greenorange.promotion.constant.UserConstant;
import com.greenorange.promotion.exception.ThrowUtils;
import com.greenorange.promotion.model.dto.CommonBatchRequest;
import com.greenorange.promotion.model.dto.CommonRequest;
import com.greenorange.promotion.model.dto.courseOrder.CourseOrderAddRequest;
import com.greenorange.promotion.model.dto.courseOrder.CourseOrderQueryRequest;
import com.greenorange.promotion.model.dto.courseOrder.CourseOrderUpdateRequest;
import com.greenorange.promotion.model.entity.*;
import com.greenorange.promotion.model.enums.CommissionStatusEnum;
import com.greenorange.promotion.model.enums.UserRoleEnum;
import com.greenorange.promotion.model.vo.course.CourseCardVO;
import com.greenorange.promotion.model.vo.course.CourseVO;
import com.greenorange.promotion.model.vo.courseOrder.CourseOrderBaseInfoVO;
import com.greenorange.promotion.model.vo.courseOrder.CourseOrderCardVO;
import com.greenorange.promotion.model.vo.courseOrder.CourseOrderVO;
import com.greenorange.promotion.service.common.CommonService;
import com.greenorange.promotion.service.course.CourseOrderService;
import com.greenorange.promotion.service.course.CoursePromotionCommissionPendingService;
import com.greenorange.promotion.service.course.CourseService;
import com.greenorange.promotion.service.userInfo.UserInfoService;
import com.greenorange.promotion.service.userInfo.UserPerformanceSummaryService;
import com.greenorange.promotion.utils.OrderNumberUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;
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;

import java.math.BigDecimal;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;


/**
 * 课程订单 控制器
 */
@RestController
@RequestMapping("courseOrder")
@Slf4j
@Tag(name = "课程订单模块")
@Transactional
public class CourseOrderController {

    @Resource
    private CourseService courseService;

    @Resource
    private CourseOrderService courseOrderService;

    @Resource
    private CommonService commonService;

    @Resource
    private UserInfoService userInfoService;

    @Resource
    private UserPerformanceSummaryService userPerformanceSummaryService;

    @Resource
    private CoursePromotionCommissionPendingService coursePromotionCommissionPendingService;

    /**
     * 小程序端用户生成课程订单
     * @param courseOrderAddRequest 课程id
     * @return 是否添加成功
     */
    @PostMapping("add")
    @Operation(summary = "小程序端用户生成课程订单", description = "参数：课程id，权限：管理员，方法名：addCourseOrder")
    @RequiresPermission(mustRole = UserConstant.DEFAULT_ROLE)
//    @SysLog(title = "课程订单管理", content = "小程序端用户生成课程订单")
    public BaseResponse<Long> addCourseOrder(@Valid @RequestBody CourseOrderAddRequest courseOrderAddRequest, HttpServletRequest request) {
        Long userId = (Long) request.getAttribute("userId");
        UserInfo userInfo = userInfoService.getById(userId);
        String userRole = userInfo.getUserRole();
        UserRoleEnum userRoleEnum = UserRoleEnum.getEnumByValue(userRole);
        ThrowUtils.throwIf(!UserRoleEnum.USER.equals(userRoleEnum), ErrorCode.NO_AUTH_ERROR, "只有普通用户才能创建订单");
        Long courseId = courseOrderAddRequest.getCourseId();
        Course course = courseService.getById(courseId);
        ThrowUtils.throwIf(course == null, ErrorCode.OPERATION_ERROR, "该课程不存在");
        CourseVO courseVO = commonService.copyProperties(course, CourseVO.class);
        CourseOrder courseOrder = commonService.copyProperties(courseVO, CourseOrder.class);
        courseOrder.setId(null);
        courseOrder.setCourseId(courseId);
        courseOrder.setOrderNumber(OrderNumberUtils.generateOrderId());
        courseOrder.setTotalAmount(course.getDiscountPrice());
        courseOrder.setUserId(userId);
        courseOrderService.save(courseOrder);
        // 向消息队列中发送订单创建的消息
        courseOrderService.sendCreateOrderMessage(courseOrder.getId());
        return ResultUtils.success(courseOrder.getId());
    }


    /**
     * 模拟订单支付回调
     */
    @PostMapping("payment")
    @Operation(summary = "模拟订单支付回调", description = "参数：订单id，权限：管理员，方法名：paymentCourse")
    @RequiresPermission(mustRole = UserConstant.DEFAULT_ROLE)
    public BaseResponse<Boolean> paymentCourse(@Valid @RequestBody CommonRequest commonRequest) {

        System.out.println("---------------------------微信支付回调（开始）-------------------------------");
        // 获取订单信息
        Long id = commonRequest.getId();
        CourseOrder courseOrder = courseOrderService.getById(id);

        // 修改订单状态
        LambdaUpdateWrapper<CourseOrder> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(CourseOrder::getId, courseOrder.getId())
                .set(CourseOrder::getOrderStatus, OrderStatusConstant.SUCCESS);
        courseOrderService.update(updateWrapper);

        // 修改当前课程下单人数
        Long courseId = courseOrder.getCourseId();
        Course course = courseService.getById(courseId);
        if (course != null) {
            course.setOrderCount(course.getOrderCount() + 1);
            courseService.updateById(course);
        }

        // 更新主管和员工的绩效记录
        Long userId = courseOrder.getUserId();
        List<Long> pathToRoot = userInfoService.findPathToRoot(userId);
        List<Long> subPathToRoot = pathToRoot.subList(1, 3);
        List<UserPerformanceSummary> userPerformanceSummaryList = commonService.findByFieldInTargetFieldWithSpecificFields(
                subPathToRoot, userPerformanceSummaryService, Function.identity(), UserPerformanceSummary::getUserId,
                List.of(UserPerformanceSummary::getTotalAmount, UserPerformanceSummary::getNetAmount, UserPerformanceSummary::getOrderCount,
                        UserPerformanceSummary::getToRelease, UserPerformanceSummary::getToSettle));
        BigDecimal rate;
        Map<String, BigDecimal> rateMap = userPerformanceSummaryService.queryRakeRewardsRate();
        for (int i = 0; i < userPerformanceSummaryList.size(); i ++ ) {
            if (i == 0) rate = rateMap.get("first");
            else rate = rateMap.get("second");
            // 计算理论上获得的最大提成奖励
            BigDecimal rakeRewards = courseOrder.getTotalAmount().multiply(rate);
            UserPerformanceSummary userPerformanceSummary = userPerformanceSummaryList.get(i);

            userPerformanceSummary.setTotalAmount(userPerformanceSummary.getTotalAmount().add(courseOrder.getTotalAmount()));
            userPerformanceSummary.setNetAmount(userPerformanceSummary.getNetAmount().add(courseOrder.getTotalAmount().multiply(SystemConstant.FEE_RATE)));
            userPerformanceSummary.setOrderCount(userPerformanceSummary.getOrderCount() + 1);
            userPerformanceSummary.setToRelease(userPerformanceSummary.getToRelease().add(rakeRewards.multiply(SystemConstant.REFUND_RATE)));
            userPerformanceSummary.setToSettle(userPerformanceSummary.getToSettle().add(rakeRewards.multiply(SystemConstant.FEE_RATE)));
        }
        userPerformanceSummaryService.updateBatchById(userPerformanceSummaryList);


        // 添加课程推广待提成记录
        Long firstUserId = subPathToRoot.get(0);
        Long secondUserId = subPathToRoot.get(1);
        CoursePromotionCommissionPending coursePromotionCommissionPending = CoursePromotionCommissionPending.builder()
                .firstUserId(firstUserId)
                .secondUserId(secondUserId)
                .courseId(courseId)
                .name(courseOrder.getName())
                .type(courseOrder.getType())
                .image(courseOrder.getImage())
                .orderId(courseOrder.getId())
                .userId(userId)
                .firstRate(rateMap.get("first"))
                .secondRate(rateMap.get("second"))
                .firstReward(courseOrder.getTotalAmount().multiply(rateMap.get("first")))
                .secondReward(courseOrder.getTotalAmount().multiply(rateMap.get("second")))
                .totalAmount(courseOrder.getTotalAmount())
                .commissionStatus(CommissionStatusEnum.PENDING.getValue())
                .orderCreateTime(courseOrder.getCreateTime())
                .build();
        coursePromotionCommissionPendingService.save(coursePromotionCommissionPending);


        System.out.println("---------------------------微信支付回调（结束）-------------------------------");

        return ResultUtils.success(true);
    }




    /**
     * 模拟订单退款回调
     */
    @PostMapping("refund")
    @Operation(summary = "模拟订单退款回调", description = "参数：订单id，权限：管理员，方法名：refundCourse")
    @RequiresPermission(mustRole = UserConstant.ADMIN_ROLE)
    public BaseResponse<Boolean> refundCourse(@Valid @RequestBody CommonRequest commonRequest) {
        System.out.println("---------------------------微信退款回调（开始）-------------------------------");
        // 获取订单信息
        Long id = commonRequest.getId();
        CourseOrder courseOrder = courseOrderService.getById(id);

        // 修改订单状态
        LambdaUpdateWrapper<CourseOrder> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(CourseOrder::getId, courseOrder.getId())
                .set(CourseOrder::getOrderStatus, OrderStatusConstant.REFUNDED);
        courseOrderService.update(updateWrapper);

        // 修改课程下单人数
        Long courseId = courseOrder.getCourseId();
        Course course = courseService.getById(courseId);
        if (course != null) {
            course.setOrderCount(course.getOrderCount() - 1);
            courseService.updateById(course);
        }

        // 更新主管和员工的绩效记录
        Long userId = courseOrder.getUserId();
        List<Long> pathToRoot = userInfoService.findPathToRoot(userId);
        List<Long> superUserIdList = pathToRoot.subList(1, 3);
        List<UserPerformanceSummary> userPerformanceSummaryList = commonService.findByFieldInTargetFieldWithSpecificFields(
                superUserIdList, userPerformanceSummaryService, Function.identity(), UserPerformanceSummary::getUserId,
                List.of(UserPerformanceSummary::getTotalAmount, UserPerformanceSummary::getToRelease, UserPerformanceSummary::getRefunded));
        BigDecimal rate;
        LambdaQueryWrapper<CoursePromotionCommissionPending> coursePromotionQueryWrapper = new LambdaQueryWrapper<>();
        coursePromotionQueryWrapper.eq(CoursePromotionCommissionPending::getOrderId, courseOrder.getId());
        CoursePromotionCommissionPending coursePromotionCommissionPending = coursePromotionCommissionPendingService.getOne(coursePromotionQueryWrapper);
        for (int i = 0; i < userPerformanceSummaryList.size(); i ++ ) {
            if (i == 0) rate = coursePromotionCommissionPending.getFirstRate();
            else rate = coursePromotionCommissionPending.getSecondRate();
            // 计算理论上获得的最大提成奖励
            BigDecimal rakeRewards = courseOrder.getTotalAmount().multiply(rate);
            UserPerformanceSummary userPerformanceSummary = userPerformanceSummaryList.get(i);

            userPerformanceSummary.setTotalAmount(userPerformanceSummary.getTotalAmount().subtract(courseOrder.getTotalAmount().multiply(SystemConstant.REFUND_RATE)));
            userPerformanceSummary.setToRelease(userPerformanceSummary.getToRelease().subtract(rakeRewards.multiply(SystemConstant.REFUND_RATE)));
            userPerformanceSummary.setRefunded(userPerformanceSummary.getRefunded().add(rakeRewards.multiply(SystemConstant.REFUND_RATE)));
        }
        userPerformanceSummaryService.updateBatchById(userPerformanceSummaryList);

        // 修改课程推广待提成状态为"已失效"
        LambdaUpdateWrapper<CoursePromotionCommissionPending> coursePromotionUpdateWrapper = new LambdaUpdateWrapper<>();
        coursePromotionUpdateWrapper.eq(CoursePromotionCommissionPending::getOrderId, courseOrder.getId())
                .set(CoursePromotionCommissionPending::getCommissionStatus, CommissionStatusEnum.EXPIRED.getValue());
        coursePromotionCommissionPendingService.update(coursePromotionUpdateWrapper);

        System.out.println("---------------------------微信退款回调（结束）-------------------------------");
        return ResultUtils.success(true);
    }



    /**
     * 小程序端用户取消课程订单
     * @param courseOrderAddRequest 课程id
     * @return 是否添加成功
     */
    @PostMapping("cancel")
    @Operation(summary = "小程序端用户取消课程订单", description = "参数：订单id，权限：管理员，方法名：cancelCourseOrder")
    @RequiresPermission(mustRole = UserConstant.DEFAULT_ROLE)
//    @SysLog(title = "课程订单管理", content = "小程序端用户取消课程订单")
    public BaseResponse<Long> cancelCourseOrder(@Valid @RequestBody CourseOrderAddRequest courseOrderAddRequest) {
        Long courseId = courseOrderAddRequest.getCourseId();
        CourseOrder courseOrder = courseOrderService.getById(courseId);
        ThrowUtils.throwIf(courseOrder == null || !courseOrder.getOrderStatus().equals(OrderStatusConstant.PENDING),
                ErrorCode.OPERATION_ERROR, "该订单不存在或者订单状态错误");
        LambdaUpdateWrapper<CourseOrder> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(CourseOrder::getId, courseId).set(CourseOrder::getOrderStatus, OrderStatusConstant.CLOSED);
        courseOrderService.update(updateWrapper);
        return ResultUtils.success(courseOrder.getId());
    }


    /**
     * 小程序端用户查询课程订单列表
     * @return 课程订单列表
     */
    @PostMapping("query/list")
    @Operation(summary = "小程序端用户查询课程订单列表", description = "参数：无，权限：管理员，方法名:queryCourseOrderList")
    @RequiresPermission(mustRole = UserConstant.DEFAULT_ROLE)
//    @SysLog(title = "课程订单管理", content = "小程序端用户查询课程订单列表")
    public BaseResponse<List<CourseOrderCardVO>> queryCourseOrderList(HttpServletRequest request) {
        Long userId = (Long) request.getAttribute("userId");
        List<CourseOrder> courseOrderList = commonService.findByFieldEqTargetField(CourseOrder::getUserId, userId, courseOrderService);
        List<CourseOrderCardVO> courseOrderCardVOS = commonService.convertList(courseOrderList, CourseOrderCardVO.class);
        Collections.reverse(courseOrderCardVOS);
        return ResultUtils.success(courseOrderCardVOS);
    }


    /**
     * 小程序端用户根据id查询订单详情
     * @return 课程订单列表
     */
    @PostMapping("query/detail")
    @Operation(summary = "小程序端用户根据id查询订单详情", description = "参数：订单id，权限：管理员，方法名:queryCourseOrderDetailById")
    @RequiresPermission(mustRole = UserConstant.DEFAULT_ROLE)
//    @SysLog(title = "课程订单管理", content = "小程序端用户根据id查询订单详情")
    public BaseResponse<CourseOrderVO> queryCourseOrderDetailById(@RequestBody CommonRequest commonRequest) {
        Long id = commonRequest.getId();
        CourseOrder courseOrder = courseOrderService.getById(id);
        CourseOrderVO courseOrderVO = commonService.copyProperties(courseOrder, CourseOrderVO.class);
        return ResultUtils.success(courseOrderVO);
    }





//
//    /**
//     * web端管理员根据id删除课程订单
//     * @param commonRequest 课程订单删除请求体
//     * @return 是否删除成功
//     */
//    @PostMapping("delete")
//    @Operation(summary = "web端管理员根据id删除课程订单", description = "参数：课程订单删除请求体，权限：管理员，方法名：delCourseOrder")
//    @RequiresPermission(mustRole = UserConstant.ADMIN_ROLE)
//    @SysLog(title = "课程订单管理", content = "web端管理员根据id删除课程订单")
//    public BaseResponse<Boolean> delCourseOrder(@Valid @RequestBody CommonRequest commonRequest) {
//        Long id = commonRequest.getId();
//        CourseOrder courseOrder = courseOrderService.getById(id);
//        ThrowUtils.throwIf(courseOrder == null || !courseOrder.getOrderStatus().equals(OrderStatusConstant.CLOSED),
//                ErrorCode.OPERATION_ERROR, "该课程订单不存在或订单状态错误");
//        courseOrderService.removeById(id);
//        return ResultUtils.success(true);
//    }
//
//    /**
//     * web端管理员批量删除课程订单
//     * @param commonBatchRequest 课程订单批量删除请求体
//     * @return 是否删除成功
//     */
//    @PostMapping("delBatch")
//    @Operation(summary = "web端管理员批量删除课程订单", description = "参数：课程订单批量删除请求体，权限：管理员，方法名：delBatchCourseOrder")
//    @RequiresPermission(mustRole = UserConstant.ADMIN_ROLE)
//    @SysLog(title = "课程订单管理", content = "web端管理员批量删除课程订单")
//    public BaseResponse<Boolean> delBatchCourseOrder(@Valid @RequestBody CommonBatchRequest commonBatchRequest) {
//        List<Long> ids = commonBatchRequest.getIds();
//        LambdaQueryWrapper<CourseOrder> queryWrapper = new LambdaQueryWrapper<>();
//        queryWrapper.ne(CourseOrder::getOrderStatus, OrderStatusConstant.CLOSED);
//        long count = courseOrderService.count(queryWrapper);
//        ThrowUtils.throwIf(count > 0, ErrorCode.OPERATION_ERROR, "存在未关闭的课程订单");
//        courseOrderService.removeByIds(ids);
//        return ResultUtils.success(true);
//    }

    /**
     * web端管理员根据id查询课程订单
     * @param commonRequest 课程订单查询请求体
     * @return 课程订单信息
     */
    @PostMapping("queryById")
    @Operation(summary = "web端管理员根据id查询课程订单", description = "参数：课程订单查询请求体，权限：管理员，方法名：queryCourseOrderById")
    @RequiresPermission(mustRole = UserConstant.ADMIN_ROLE)
//    @SysLog(title = "课程订单管理", content = "web端管理员根据id查询课程订单")
    public BaseResponse<CourseOrderVO> queryCourseOrderById(@Valid @RequestBody CommonRequest commonRequest) {
        Long id = commonRequest.getId();
        CourseOrder courseOrder = courseOrderService.getById(id);
        CourseOrderVO courseOrderVO = commonService.copyProperties(courseOrder, CourseOrderVO.class);
        return ResultUtils.success(courseOrderVO);
    }

    /**
     * Web端管理员分页查询课程订单
     * @param courseOrderQueryRequest 课程订单查询请求体
     * @return 课程订单列表
     */
    @PostMapping("page")
    @Operation(summary = "Web端管理员分页查询课程订单", description = "参数：课程订单查询请求体，权限：管理员，方法名：listCourseOrderByPage")
    @RequiresPermission(mustRole = UserConstant.ADMIN_ROLE)
//    @SysLog(title = "课程订单管理", content = "Web端管理员分页查询课程订单")
    public BaseResponse<Page<CourseOrderBaseInfoVO>> listCourseOrderByPage(@Valid @RequestBody CourseOrderQueryRequest courseOrderQueryRequest) {
        long current = courseOrderQueryRequest.getCurrent();
        long pageSize = courseOrderQueryRequest.getPageSize();
        QueryWrapper<CourseOrder> queryWrapper = courseOrderService.getQueryWrapper(courseOrderQueryRequest);
        Page<CourseOrder> page = courseOrderService.page(new Page<>(current, pageSize), queryWrapper);
        List<CourseOrder> courseOrderList = page.getRecords();
        List<CourseOrderBaseInfoVO> courseOrderBaseInfoVOS = commonService.convertList(courseOrderList, CourseOrderBaseInfoVO.class);
        Page<CourseOrderBaseInfoVO> voPage = new Page<>(current, pageSize);
        voPage.setRecords(courseOrderBaseInfoVOS);
        voPage.setPages(page.getPages());
        voPage.setTotal(page.getTotal());
        return ResultUtils.success(voPage);
    }
}