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

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.starry.admin.common.exception.CustomException;
import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity;
import com.starry.admin.modules.clerk.service.IPlayClerkUserInfoService;
import com.starry.admin.modules.order.module.constant.OrderConstant.OperatorType;
import com.starry.admin.modules.order.module.constant.OrderConstant.OrderTriggerSource;
import com.starry.admin.modules.order.module.dto.OrderRefundContext;
import com.starry.admin.modules.order.module.dto.OrderRevocationContext;
import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity;
import com.starry.admin.modules.order.module.vo.*;
import com.starry.admin.modules.order.service.IOrderLifecycleService;
import com.starry.admin.modules.order.service.IPlayOrderInfoService;
import com.starry.admin.modules.shop.module.vo.PlayCommodityInfoVo;
import com.starry.admin.modules.shop.service.IPlayCommodityInfoService;
import com.starry.admin.modules.weichat.service.WxCustomMpService;
import com.starry.admin.modules.withdraw.service.IEarningsService;
import com.starry.admin.utils.SecurityUtils;
import com.starry.common.annotation.Log;
import com.starry.common.context.CustomSecurityContextHolder;
import com.starry.common.enums.BusinessType;
import com.starry.common.result.R;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
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.util.List;
import java.util.Optional;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

/**
 * 订单管理
 *
 * @author admin
 * @since 2024-03-20
 */
@Api(tags = "订单管理", description = "订单信息管理相关接口，包括查询、修改、退款和删除等操作")
@RestController
@RequestMapping("/order/order/")
public class PlayOrderInfoController {
    @Resource
    private IPlayOrderInfoService orderInfoService;

    @Resource
    private WxCustomMpService wxCustomMpService;

    @Resource
    private IPlayClerkUserInfoService playClerkUserInfoService;

    @Resource
    private IPlayCommodityInfoService playCommodityInfoService;

    @Resource
    private IOrderLifecycleService orderLifecycleService;
    @Resource
    private IPlayClerkUserInfoService clerkUserInfoService;

    @Resource
    private IEarningsService earningsService;

    /**
     * 分页查询订单列表
     */
    @ApiOperation(value = "分页查询订单列表", notes = "分页查询订单信息列表")
    @ApiResponses({
            @ApiResponse(code = 200, message = "操作成功", response = PlayOrderInfoEntity.class, responseContainer = "Page")})
    @PostMapping("/listByPage")
    public R listByPage(@ApiParam(value = "查询条件", required = true) @Validated @RequestBody PlayOrderInfoQueryVo vo) {
        return R.ok(orderInfoService.selectOrderInfoPage(vo));
    }

    @ApiOperation(value = "发送订单微信通知", notes = "发送订单微信通知")
    @ApiResponses({
            @ApiResponse(code = 200, message = "操作成功", response = Boolean.class, responseContainer = "Page")})
    @PostMapping("/sendNotice")
    public R sendNotice(String orderId) {
        PlayOrderInfoEntity orderInfo = orderInfoService.selectOrderInfoById(orderId);
        List<PlayClerkUserInfoEntity> clerkList = clerkUserInfoService.list(Wrappers.lambdaQuery(PlayClerkUserInfoEntity.class).isNotNull(PlayClerkUserInfoEntity::getOpenid).eq(PlayClerkUserInfoEntity::getClerkState, "1").eq(PlayClerkUserInfoEntity::getSex, orderInfo.getSex()));
        wxCustomMpService.sendCreateOrderMessageBatch(
                clerkList,
                orderInfo.getOrderNo(),
                orderInfo.getOrderMoney().toString(),
                orderInfo.getCommodityName(),
                orderId,
                orderInfo.getPlaceType(),
                orderInfo.getRewardType());
        return R.ok();
    }

    /**
     * 订单退款
     */
    @ApiOperation(value = "订单退款", notes = "处理订单退款操作")
    @ApiResponses({@ApiResponse(code = 200, message = "退款成功"), @ApiResponse(code = 500, message = "退款失败，包含详细错误信息")})
    // @PreAuthorize("@customSs.hasPermission('order:order:update')")
    @PostMapping("/orderRefund")
    public R orderRefund(@ApiParam(value = "退款信息", required = true) @Validated @RequestBody PlayOrderRefundAddVo vo) {
        OrderRefundContext context = new OrderRefundContext();
        context.setOrderId(vo.getOrderId());
        context.setRefundAmount(vo.getRefundAmount());
        context.setRefundReason(vo.getRefundReason());
        context.setOperatorType(OperatorType.ADMIN.getCode());
        context.setOperatorId(SecurityUtils.getUserId());
        context.withTriggerSource(OrderTriggerSource.ADMIN_API);
        orderLifecycleService.refundOrder(context);
        return R.ok("退款成功");
    }

    @ApiOperation(value = "撤销已完成订单", notes = "管理员操作撤销，支持可选退款与收益处理")
    @PostMapping("/revokeCompleted")
    public R revokeCompleted(@Validated @RequestBody PlayOrderRevocationVo vo) {
        OrderRevocationContext context = new OrderRevocationContext();
        context.setOrderId(vo.getOrderId());
        context.setRefundToCustomer(vo.isRefundToCustomer());
        context.setRefundAmount(vo.getRefundAmount());
        context.setRefundReason(vo.getRefundReason());
        context.setDeductClerkEarnings(vo.isDeductClerkEarnings());
        context.setEarningsAdjustAmount(vo.getDeductAmount());
        context.setOperatorType(OperatorType.ADMIN.getCode());
        context.setOperatorId(SecurityUtils.getUserId());
        context.withTriggerSource(OrderTriggerSource.ADMIN_API);
        orderLifecycleService.revokeCompletedOrder(context);
        return R.ok("撤销成功");
    }

    @ApiOperation(value = "撤销限额", notes = "查询指定订单可退金额与可扣回收益")
    @GetMapping("/{id}/revocationLimits")
    public R getRevocationLimits(@PathVariable("id") String id) {
        PlayOrderInfoEntity order = orderInfoService.selectOrderInfoById(id);
        BigDecimal maxRefundAmount = Optional.ofNullable(order.getFinalAmount()).orElse(BigDecimal.ZERO);
        BigDecimal maxDeductAmount = BigDecimal.ZERO;
        if (order.getAcceptBy() != null) {
            maxDeductAmount = Optional.ofNullable(earningsService.getRemainingEarningsForOrder(order.getId(), order.getAcceptBy()))
                    .orElse(BigDecimal.ZERO);
        }
        if (maxDeductAmount.compareTo(BigDecimal.ZERO) < 0) {
            maxDeductAmount = BigDecimal.ZERO;
        }

        PlayOrderRevocationLimitsVo limitsVo = new PlayOrderRevocationLimitsVo();
        limitsVo.setOrderId(order.getId());
        limitsVo.setMaxRefundAmount(maxRefundAmount);
        limitsVo.setMaxDeductAmount(maxDeductAmount);
        limitsVo.setDefaultDeductAmount(maxDeductAmount);
        limitsVo.setDeductible(order.getAcceptBy() != null);
        return R.ok(limitsVo);
    }

    /**
     * 管理后台强制取消进行中订单
     */
    @ApiOperation(value = "强制取消订单", notes = "管理员强制取消已接单或服务中的订单")
    @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "操作失败")})
    @PostMapping("/forceCancel")
    public R forceCancel(@ApiParam(value = "取消参数", required = true) @Validated @RequestBody PlayOrderForceCancelVo vo) {
        orderInfoService.forceCancelOngoingOrder("2", CustomSecurityContextHolder.getUserId(), vo.getOrderId(),
                vo.getRefundAmount(), vo.getRefundReason(), vo.getImages());
        return R.ok("操作成功");
    }

    /**
     * 更换店员
     */
    @ApiOperation(value = "更换店员", notes = "修改订单的接单店员")
    @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "操作失败")})
    // @PreAuthorize("@customSs.hasPermission('order:order:update')")
    @PostMapping("/orderEditAcceptBy")
    public R orderEditAcceptBy(
            @ApiParam(value = "更换店员信息", required = true) @Validated @RequestBody PlayOrderEditAcceptByVo vo) {
        orderInfoService.updateStateTo1("2", CustomSecurityContextHolder.getUserId(), vo.getAcceptBy(),
                vo.getOrderId());
        PlayClerkUserInfoEntity clerkUserInfo = playClerkUserInfoService.selectById(vo.getAcceptBy());
        PlayOrderInfoEntity orderInfo = orderInfoService.selectOrderInfoById(vo.getOrderId());
        PlayCommodityInfoVo commodityInfo = playCommodityInfoService.queryCommodityInfo(orderInfo.getCommodityId(),
                clerkUserInfo.getLevelId());
        wxCustomMpService.sendCreateOrderMessage(
                clerkUserInfo.getTenantId(),
                clerkUserInfo.getOpenid(),
                orderInfo.getOrderNo(),
                orderInfo.getOrderMoney().toString(),
                commodityInfo.getCommodityName(),
                vo.getOrderId(),
                orderInfo.getPlaceType(),
                orderInfo.getRewardType());
        return R.ok("操作成功");
    }

    /**
     * 后台备注
     */
    @ApiOperation(value = "修改后台备注", notes = "修改订单的后台备注信息")
    @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Boolean.class),
            @ApiResponse(code = 500, message = "操作失败")})
    // @PreAuthorize("@customSs.hasPermission('order:order:update')")
    @PostMapping("/orderEditBackendRemark")
    public R orderEditBackendRemark(
            @ApiParam(value = "后台备注信息", required = true) @Validated @RequestBody PlayOrderEditBackendRemarkByVo vo) {
        PlayOrderInfoEntity orderInfo = orderInfoService.selectOrderInfoById(vo.getOrderId());
        PlayOrderInfoEntity updateOrderInfo = new PlayOrderInfoEntity();
        updateOrderInfo.setId(orderInfo.getId());
        updateOrderInfo.setBackendRemark(vo.getBackendRemark());
        return R.ok(orderInfoService.update(updateOrderInfo));
    }

    /**
     * 重新抢单
     */
    @ApiOperation(value = "重新抢单", notes = "将订单重新设置为抢单状态")
    @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Boolean.class),
            @ApiResponse(code = 500, message = "操作失败，包含详细错误信息")})
    // @PreAuthorize("@customSs.hasPermission('order:order:update')")
    @PostMapping("/orderEditRandomSingle")
    public R orderEditRandomSingle(
            @ApiParam(value = "重新抢单信息", required = true) @Validated @RequestBody PlayOrderEditRandomSingleVo vo) {
        PlayOrderInfoEntity orderInfo = orderInfoService.selectOrderInfoById(vo.getOrderId());
        if (!"1".equals(orderInfo.getPlaceType())) {
            throw new CustomException("订单类型错误，无法重新抢单");
        }
        PlayOrderInfoEntity updateOrderInfo = new PlayOrderInfoEntity();
        updateOrderInfo.setSex(vo.getSex());
        updateOrderInfo.setLevelId(vo.getLevelId());
        updateOrderInfo.setExcludeHistory(vo.getExcludeHistory());
        updateOrderInfo.setRemark(vo.getRemark());
        updateOrderInfo.setId(vo.getOrderId());
        updateOrderInfo.setOrderStatus("0");
        updateOrderInfo.setAcceptBy("");
        updateOrderInfo.setEstimatedRevenueRatio(0);
        updateOrderInfo.setEstimatedRevenue(BigDecimal.ZERO);
        updateOrderInfo.setRemark(vo.getRemark());
        return R.ok(orderInfoService.update(updateOrderInfo));
    }

    /**
     * 根据ID查询订单
     */
    @ApiOperation(value = "获取订单详情", notes = "根据ID获取订单详细信息")
    @ApiImplicitParam(name = "id", value = "订单ID", required = true, paramType = "path", dataType = "String", example = "1")
    @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = PlayOrderInfoEntity.class)})
    @GetMapping(value = "/{id}")
    public R getInfo(@PathVariable("id") String id) {
        return R.ok(orderInfoService.selectById(id));
    }

    /**
     * 根据ID修改订单信息
     */
    @ApiOperation(value = "修改订单信息", notes = "根据ID修改订单基本信息")
    @ApiImplicitParam(name = "id", value = "订单ID", required = true, paramType = "path", dataType = "String", example = "1")
    @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败")})
    // @PreAuthorize("@customSs.hasPermission('order:order:update')")
    @Log(title = "修改普通订单", businessType = BusinessType.UPDATE)
    @PostMapping(value = "/update/{id}")
    public R update(@PathVariable String id,
                    @ApiParam(value = "订单信息", required = true) @RequestBody PlayOrderInfoEntity orderInfoEntity) {
        orderInfoEntity.setId(id);
        boolean success = orderInfoService.update(orderInfoEntity);
        if (success) {
            return R.ok();
        }
        return R.error("修改失败");
    }

    /**
     * 删除订单
     */
    @ApiOperation(value = "删除订单", notes = "根据ID批量删除订单信息")
    @ApiImplicitParam(name = "ids", value = "订单ID数组", required = true, paramType = "path", dataType = "String[]", example = "1,2,3")
    @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Integer.class)})
    // @PreAuthorize("@customSs.hasPermission('order:order:delete')")
    @Log(title = "删除订单", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public R remove(@PathVariable String[] ids) {
        return R.ok(orderInfoService.deleteOrderInfoByIds(ids));
    }
}
