package com.yiqi.admin.controller.order;

import java.math.BigDecimal;
import java.util.Currency;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yiqi.common.exception.ServiceException;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yiqi.app.domain.vo.AppUserInfoVO;
import com.yiqi.app.service.IAppUserService;
import com.yiqi.common.constant.UrlConstants;
import com.yiqi.common.core.domain.R;
import com.yiqi.common.core.domain.entity.SysUser;
import com.yiqi.common.enums.*;
import com.yiqi.common.utils.CurrencyUtil;
import com.yiqi.common.utils.DateUtils;
import com.yiqi.common.utils.SecurityUtils;
import com.yiqi.common.utils.bean.BeanUtils;
import com.yiqi.common.utils.poi.ExcelUtil;
import com.yiqi.order.domain.OrderGoodsRefund;
import com.yiqi.order.domain.dto.*;
import com.yiqi.order.domain.dto.weapp.AppOrderGoodsCancelDTO;
import com.yiqi.order.domain.vo.*;
import com.yiqi.order.service.IOrderGoodsRefundService;
import com.yiqi.recharge.domain.RechargePasswordCard;
import com.yiqi.recharge.service.IRechargePasswordCardService;
import com.yiqi.system.domain.SysStore;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import com.yiqi.common.annotation.Log;
import com.yiqi.common.core.controller.BaseController;
import com.yiqi.common.core.domain.AjaxResult;
import com.yiqi.order.domain.OrderGoods;
import com.yiqi.order.service.IOrderGoodsService;
import com.yiqi.common.core.page.TableDataInfo;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;

/**
 * 零售商品订单Controller
 *
 * @author ruoyi
 * @date 2023-12-06
 */
@Api(tags = "管理后台 - 零售商品订单")
@RestController
@RequestMapping(UrlConstants.managerApi + "/order/goods")
public class OrderGoodsController extends BaseController {
    @Autowired
    private IOrderGoodsService orderGoodsService;

    @Autowired
    private IOrderGoodsRefundService orderGoodsRefundService;

    @Autowired
    private IAppUserService appUserService;

    @Autowired
    private IRechargePasswordCardService rechargePasswordCardService;

    /**
     * 查询零售商品订单列表
     */
    @PreAuthorize("@ss.hasPermi('order:goods:list')")
    @GetMapping("/list")
    @ApiOperation(value = "查询零售商品订单列表")
    public TableDataInfo list(GoodsOrderQueryDTO goodsOrderQueryDTO) {
        startPage();
        List<GoodsOrderQueryVO> orderGoodsList = orderGoodsService.selectOrderGoodsList(goodsOrderQueryDTO);
        return getDataTable(orderGoodsList);
    }

    /**
     * 导出零售商品订单列表
     */
    @PreAuthorize("@ss.hasPermi('order:goods:export')")
    @Log(title = "零售商品订单订单", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    @ApiOperation(value = "导出零售商品订单列表")
    public void export(HttpServletResponse response, GoodsOrderQueryDTO goodsOrderQueryDTO) {
        goodsOrderQueryDTO.setPageSizeExport(10000);
        List<GoodsOrderQueryVO> list = orderGoodsService.selectOrderGoodsList(goodsOrderQueryDTO);
        ExcelUtil<GoodsOrderQueryVO> util = new ExcelUtil<GoodsOrderQueryVO>(GoodsOrderQueryVO.class);
        util.exportExcel(response, list, "商品订单数据");
    }

    /**
     * 获取零售商品订单详细信息1
     */
    @GetMapping(value = "/{id}")
    @ApiOperation(value = "获取零售商品订单详细信息")
    public R<GoodsOrderInfoVO> getInfo(@PathVariable("id") Long id) {
        GoodsOrderInfoVO goodsOrderInfoVO = new GoodsOrderInfoVO();
        OrderGoods orderGoods = orderGoodsService.getById(id);
        BeanUtils.copyProperties(orderGoods, goodsOrderInfoVO);
        goodsOrderInfoVO.setOrderGoodsSkuList(orderGoodsService.selectOrderGoodsById(id));
        AppUserInfoVO userInfo = appUserService.getAppUserInfoById(orderGoods.getAppUserId());
        if (userInfo != null) {
            BeanUtils.copyProperties(userInfo, goodsOrderInfoVO);
        }
        return R.ok(goodsOrderInfoVO);
    }

    /**
     * 获取零售商品订单详细信息
     */
    @GetMapping(value = "/refund/{id}")
    @ApiOperation(value = "获取零售商品订单详细信息")
    public R<GoodsOrderInfoVO> getRefundInfo(@PathVariable("id") Long id) {
        GoodsOrderInfoVO goodsOrderInfoVO = new GoodsOrderInfoVO();
        OrderGoodsRefund orderGoodsRefund = orderGoodsRefundService.getById(id);
        OrderGoods orderGoods = orderGoodsService.getByOrderNo(orderGoodsRefund.getOrderNo());
        BeanUtils.copyProperties(orderGoods, goodsOrderInfoVO);
        goodsOrderInfoVO.setOrderGoodsSkuList(orderGoodsService.selectOrderGoodsById(id));
        AppUserInfoVO userInfo = appUserService.getAppUserInfoById(orderGoods.getAppUserId());
        if (userInfo != null) {
            BeanUtils.copyProperties(userInfo, goodsOrderInfoVO);
        }
        return R.ok(goodsOrderInfoVO);
    }

    /**
     * 获取零售商品订单详细信息
     */
    @GetMapping(value = "/print/{id}")
    @ApiOperation(value = "商品订单打印")
    public R<OrderGoodsPrintVO> getPrintInfo(@PathVariable("id") Long id) {
        OrderGoodsPrintVO goodsOrderInfoVO = new OrderGoodsPrintVO();
        OrderGoods orderGoods = orderGoodsService.getById(id);
        BeanUtils.copyProperties(orderGoods, goodsOrderInfoVO);
        goodsOrderInfoVO.setOrderGoodsSkuList(orderGoodsService.selectOrderGoodsById(id));
        AppUserInfoVO userInfo = appUserService.getAppUserInfoById(orderGoods.getAppUserId());
        goodsOrderInfoVO.setAppUserInfoVO(userInfo);
        RechargePasswordCard rechargePasswordCard = rechargePasswordCardService.selectTotalBalanceGroupByAppUser(orderGoods.getAppUserId(), OrderType.goods.getCode());
        if (orderGoods.getPayType().equals(PayType.BALANCE.getCode())) {
            goodsOrderInfoVO.setMemberBeforeBalance(CurrencyUtil.add(rechargePasswordCard.getTotalBalance(), orderGoods.getPayAmount()));
            goodsOrderInfoVO.setMemberAfterBalance(rechargePasswordCard.getTotalBalance());
            goodsOrderInfoVO.setMemberChangeAmount(orderGoods.getPayAmount());
        } else {
            goodsOrderInfoVO.setMemberBeforeBalance(rechargePasswordCard.getTotalBalance());
            goodsOrderInfoVO.setMemberAfterBalance(rechargePasswordCard.getTotalBalance());
            goodsOrderInfoVO.setMemberChangeAmount(BigDecimal.ZERO);
        }
        return R.ok(goodsOrderInfoVO);
    }


    /**
     * 新增零售商品订单-下单
     */
    @Log(title = "创建商品订单", businessType = BusinessType.INSERT)
    @PostMapping("/insertRetailOrderGoods")
    @ApiOperation(value = "新增零售商品订单-下单")
    public R<OrderGoods> insertRetailOrderGoods(@RequestBody @Valid OrderGoodsInsertDTO orderGoodsInsertDTO) {
        OrderGoodsDTO orderGoodsDTO = new OrderGoodsDTO();
        BeanUtils.copyProperties(orderGoodsInsertDTO, orderGoodsDTO);
        orderGoodsDTO.setOrderSource(OrderSourceType.OFFLINE.getCode());
        // 设置总价
        List<OrderGoodsSkuInfoVO> orderGoodsSkuInfoVOS = orderGoodsService.getOrderSkuInfoByOrderSkuId(orderGoodsDTO);
        BigDecimal totalPrice = orderGoodsSkuInfoVOS.stream().map(item -> item.getSalePrice().multiply(new BigDecimal(item.getBuyNum())))
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        if (BigDecimal.ZERO.equals(totalPrice)) {
            error("商品总价不能为0");
        }
        orderGoodsDTO.setTotalPrice(totalPrice);

        // 设置门店线下参数
        SysUser user = SecurityUtils.getLoginUser().getUser();
        orderGoodsDTO.setGoodsType(orderGoodsInsertDTO.getGoodsType() == null ? GoodsType.NORMAL.getCode() : orderGoodsInsertDTO.getGoodsType());
        orderGoodsDTO.setSourceType(user.getUserType());
        orderGoodsDTO.setOrgId(user.getStoreId());
        orderGoodsDTO.setSendTime(DateUtils.getNowDate());
        orderGoodsDTO.setFinishTime(DateUtils.getNowDate());
        if (orderGoodsDTO.getDeductAmount() == null) {
            orderGoodsDTO.setDeductAmount(BigDecimal.ZERO);
        }
        return R.ok(orderGoodsService.cereateRetailOrderGoods(orderGoodsDTO, orderGoodsSkuInfoVOS));
    }

    /**
     * 新增零售商品订单-下单
     */
    @PostMapping("/orderGoodsPay")
    @ApiOperation(value = "新增零售商品订单-支付")
    public R<OrderPayResultVO> orderGoodsPay(@RequestBody @Valid OrderGoodsPayDTO orderGoodsPayDTO) {
        orderGoodsPayDTO.setOrderSource(OrderSourceType.OFFLINE.getCode());
        OrderPayResultVO resultVO = orderGoodsService.orderGoodsPay(orderGoodsPayDTO);
        return R.ok(resultVO);
    }

    /**
     * 零售商品订单-取消订单
     */
    @Transactional(rollbackFor = Exception.class)
    @PostMapping("/cancelOrder")
    @ApiOperation(value = "零售商品订单-取消订单")
    public AjaxResult cancelOrder(@RequestBody AppOrderGoodsCancelDTO appOrderGoodsCancelDTO) {
        return toAjax(orderGoodsService.cancelOrder(appOrderGoodsCancelDTO));
    }

    /**
     * 零售商品订单-重新支付
     */
    @Transactional(rollbackFor = Exception.class)
    @PostMapping("/rePayOrder")
    @ApiOperation(value = "零售商品订单-重新支付")
    public R<OrderPayResultVO> rePayOrder(@RequestBody OrderGoodsDTO orderGoodsDTO) {
        return R.ok(orderGoodsService.rePayOrder(orderGoodsDTO));
    }

    /**
     * 零售商品订单-总部出货
     */
    @Transactional(rollbackFor = Exception.class)
    @PostMapping("/outOrderGoods")
    @ApiOperation(value = "零售商品订单-总部出货")
    public AjaxResult outOrderGoods(@RequestBody @Valid OrderGoodsOutGoodsDTO orderGoodsOutGoodsDTO) throws Exception {
        return toAjax(orderGoodsService.outOrderGoods(orderGoodsOutGoodsDTO));
    }

    /**
     * 生活服务/汽车美容-总部接单
     */
    @GetMapping("/receiveOrder")
    @ApiOperation(value = "生活服务/汽车美容订单-总部接单")
    public AjaxResult receiveOrder(@RequestParam("orderId") Long orderId) {
        return toAjax(orderGoodsService.receiveOrder(orderId));
    }

    /**
     * 生活服务/汽车美容-确认完成
     */
    @GetMapping("/confirmFinish")
    @ApiOperation(value = "生活服务/汽车美容订单-确认完成")
    public AjaxResult confirmFinish(@RequestParam("orderId") Long orderId) {
        return toAjax(orderGoodsService.confirmFinish(orderId));
    }

    /**
     * 商品订单-总部撤单
     */
    @Transactional(rollbackFor = Exception.class)
    @PostMapping("/refundOrderGoods")
    @ApiOperation(value = "商品订单退款-总部撤单")
    public R refundOrderGoods(@RequestBody OrderGoodsRefundDTO orderGoodsRefundDTO) {
        return R.ok(orderGoodsService.refundOrderGoodsApply(orderGoodsRefundDTO, SourceType.MANAGER.getCode()));
    }

    /**
     * 商品订单退款审核，审批同意
     */
    @Transactional(rollbackFor = Exception.class)
    @GetMapping("/refundApprovalPass")
    @ApiOperation(value = "商品订单退款审核，审批同意")
    public R refundApprovalPass(@RequestParam("orderId") Long orderId) {
        // 操作人校验
        if (!SecurityUtils.getLoginUser().getSourceType().equals(SourceType.MANAGER.getCode())) {
            throw new ServiceException("当前登录人没有权限操作");
        }
        return R.ok(orderGoodsService.refundApprovalPass(orderId));
    }

    /**
     * 商品订单退款审核，审批驳回
     */
    @Transactional(rollbackFor = Exception.class)
    @GetMapping("/refundApprovalReject")
    @ApiOperation(value = "商品订单退款审核，审批驳回")
    public R refundApprovalReject(@RequestParam("orderId") Long orderId) {
        // 操作人校验
        if (!SecurityUtils.getLoginUser().getSourceType().equals(SourceType.MANAGER.getCode())) {
            throw new ServiceException("当前登录人没有权限操作");
        }
        return R.ok(orderGoodsService.refundApprovalReject(orderId));
    }

    @PostMapping(value = "/getMemberOrderGoodsInfo")
    @ApiOperation(value = "获取会员商品订单信息")
    public R<Page<OrderGoods>> getMemberOrderGoodsInfo(@RequestBody MemberOrderQueryDTO memberOrderQueryDTO) {
        LambdaQueryWrapper<OrderGoods> queryWrapper = new QueryWrapper<OrderGoods>().lambda()
                .eq(OrderGoods::getDelFlag, DeleteStatus.OK.getCode())
                .eq(OrderGoods::getAppUserId, memberOrderQueryDTO.getAppUserId())
                .ne(OrderGoods::getRefundStatus, OrderRefundStatus.REFUND_SUCCESS.getCode());
        if (SourceType.STORE.getCode().equals(SecurityUtils.getLoginUser().getSourceType())) {
            queryWrapper.eq(OrderGoods::getSourceType, SourceType.STORE.getCode());
            queryWrapper.eq(OrderGoods::getOrgId, SecurityUtils.getLoginUser().getOrgId());
        }
        queryWrapper.orderByDesc(OrderGoods::getCreateTime);
        return R.ok(orderGoodsService.page(new Page<>(memberOrderQueryDTO.getPageNum()
                        , memberOrderQueryDTO.getPageSize())
                , queryWrapper));
    }

    /**
     * 查询退款商品订单列表
     */
    @PreAuthorize("@ss.hasPermi('order:goods:list')")
    @GetMapping("/refundOrderGoodsList")
    @ApiOperation(value = "查询退款商品订单列表")
    public TableDataInfo refundOrderGoodsList(GoodsOrderRefundQueryDTO goodsOrderRefundQueryDTO) {
        startPage();
        List<GoodsOrderRefundQueryVO> orderGoodsList = orderGoodsService.getRefundOrderGoodsList(goodsOrderRefundQueryDTO);
        List<Long> appUserIdList = orderGoodsList.stream().map(GoodsOrderRefundQueryVO::getAppUserId).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(appUserIdList)) {
            List<AppUserInfoVO> userInfoList = appUserService.getAppUserInfoByIds(appUserIdList);
            Map<Long, AppUserInfoVO> userInfoVOMap = userInfoList.stream().collect(Collectors.toMap(AppUserInfoVO::getAppUserId, AppUserInfoVO -> AppUserInfoVO));
            for (GoodsOrderRefundQueryVO vo : orderGoodsList) {
                if (userInfoVOMap.containsKey(vo.getAppUserId())) {
                    BeanUtils.copyProperties(userInfoVOMap.get(vo.getAppUserId()), vo);
                }
            }
        }
        return getDataTable(orderGoodsList);
    }

    /**
     * 导出退款商品订单列表
     */
    @PreAuthorize("@ss.hasPermi('order:goods:export')")
    @Log(title = "退款商品订单", businessType = BusinessType.EXPORT)
    @PostMapping("/exportByRefund")
    @ApiOperation(value = "导出退款商品订单列表")
    public void exportByRefund(HttpServletResponse response, GoodsOrderRefundQueryDTO goodsOrderRefundQueryDTO) {
        goodsOrderRefundQueryDTO.setPageSizeExport(50000);
        List<GoodsOrderRefundQueryVO> orderGoodsList = orderGoodsService.getRefundOrderGoodsList(goodsOrderRefundQueryDTO);
        List<Long> appUserIdList = orderGoodsList.stream().map(GoodsOrderRefundQueryVO::getAppUserId).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(appUserIdList)) {
            List<AppUserInfoVO> userInfoList = appUserService.getAppUserInfoByIds(appUserIdList);
            Map<Long, AppUserInfoVO> userInfoVOMap = userInfoList.stream().collect(Collectors.toMap(AppUserInfoVO::getAppUserId, AppUserInfoVO -> AppUserInfoVO));
            for (GoodsOrderRefundQueryVO vo : orderGoodsList) {
                if (userInfoVOMap.containsKey(vo.getAppUserId())) {
                    BeanUtils.copyProperties(userInfoVOMap.get(vo.getAppUserId()), vo);
                }
            }
        }
        ExcelUtil<GoodsOrderRefundQueryVO> util = new ExcelUtil<GoodsOrderRefundQueryVO>(GoodsOrderRefundQueryVO.class);
        util.exportExcel(response, orderGoodsList, "商品退款订单数据");
    }

    /**
     * 查询订单物流轨迹
     */
    @GetMapping("/getDeliveryPath")
    @ApiOperation(value = "查询订单物流轨迹")
    public R<OrderDeliveryPathVO> getDeliveryPath(@RequestParam("orderId") Long orderId) throws Exception {
        return R.ok(orderGoodsService.getDeliveryPath(orderId));
    }

    /**
     * 查询商品销售统计列表
     */
    @PreAuthorize("@ss.hasPermi('order:goods:statistics')")
    @GetMapping("/statistics")
    @ApiOperation(value = "查询商品销售统计列表")
    public TableDataInfo statistics(GoodsStatisticsQueryDTO queryDTO) {
        startPage();
        List<GoodsStatisticsVO> list = orderGoodsService.getGoodsStatisticsList(queryDTO);
        return getDataTable(list);
    }

    /**
     * 导出商品销售统计列表
     */
    @PreAuthorize("@ss.hasPermi('order:goods:export')")
    @Log(title = "商品销售统计", businessType = BusinessType.EXPORT)
    @PostMapping("/statistics/export")
    @ApiOperation(value = "导出商品销售统计列表")
    public void exportStatistics(HttpServletResponse response, GoodsStatisticsQueryDTO queryDTO) {
        List<GoodsStatisticsVO> list = orderGoodsService.getGoodsStatisticsList(queryDTO);
        ExcelUtil<GoodsStatisticsVO> util = new ExcelUtil<GoodsStatisticsVO>(GoodsStatisticsVO.class);
        util.exportExcel(response, list, "商品销售统计数据");
    }
}
