package com.gxwebsoft.shop.controller;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.gxwebsoft.cms.entity.Ad;
import com.gxwebsoft.common.core.exception.BusinessException;
import com.gxwebsoft.common.core.security.JwtUtil;
import com.gxwebsoft.common.core.utils.CommonUtil;
import com.gxwebsoft.common.core.utils.RequestUtil;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.common.system.entity.Role;
import com.gxwebsoft.shop.entity.*;
import com.gxwebsoft.shop.service.*;
import com.gxwebsoft.shop.param.OrderParam;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.common.core.web.BatchParam;
import com.gxwebsoft.common.system.entity.User;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import static com.gxwebsoft.shop.consts.OrderPayType.*;

/**
 * 订单控制器
 *
 * @author 科技小王子
 * @since 2024-05-14 13:20:04
 */
@Api(tags = "订单管理")
@RestController
@RequestMapping("/api/shop/order")
public class OrderController extends BaseController {
    @Resource
    private OrderService orderService;
    @Resource
    private OrderInfoService orderInfoService;
    @Resource
    private OrderGoodsService orderGoodsService;
    @Resource
    private CartService cartService;
    @Resource
    private RequestUtil requestUtil;
    @Resource
    private ExpressService expressService;
    @Resource
    private OrderDeliveryService orderDeliveryService;
    @Autowired
    private WeChatController weChatController;
    @Autowired
    private MerchantService merchantService;

    @Value("${config.upload-path}")
    private String uploadPath;

    @ApiOperation("分页查询订单")
    @GetMapping("/page")
    public ApiResult<PageResult<Order>> page(OrderParam param) {
        // 使用关联查询
        if (getLoginUser() != null) {
            param.setLoginUser(getLoginUser());
        }
        return success(orderService.pageRel(param));
    }

    @ApiOperation("查询全部订单")
    @GetMapping()
    public ApiResult<List<Order>> list(OrderParam param) {
        // 使用关联查询
        return success(orderService.listRel(param));
    }

    @PreAuthorize("hasAuthority('shop:order:list')")
    @ApiOperation("根据id查询订单")
    @GetMapping("/{id}")
    public ApiResult<Order> get(@PathVariable("id") Integer id) {
        Order order = orderService.getByIdRel(id);
        if (getLoginUser() != null) {
            for (OrderGoods orderGoods : order.getGoodsList()) {
                Goods goods = orderGoods.getGoods();
                if (getLoginUser().getGradeId().equals(33)) {
                    if (goods.getDealerGift()) goods.setShowGift(true);
                }
                // 会员店
                if (getLoginUser().getGradeId().equals(31)) {
                    if (goods.getPriceGift()) goods.setShowGift(true);
                }
            }
        }
        if (order.getType().equals(0)) {
            if (order.getDeliveryType().equals(0)) {
                OrderDelivery orderDelivery = orderDeliveryService.getByOrderId(order.getOrderId());
                if (orderDelivery != null) {
                    orderDelivery.setExpress(expressService.getById(orderDelivery.getExpressId()));
                    order.setOrderDelivery(orderDelivery);
                }
            } else if (order.getDeliveryType().equals(1) && order.getSelfTakeMerchantId() != null) {
                Merchant merchant = merchantService.getById(order.getSelfTakeMerchantId());
                order.setMerchant(merchant);
            }
        }else if (order.getType().equals(1)) {
            Merchant merchant = merchantService.getById(order.getMerchantId());
            order.setMerchant(merchant);
        }
        return success(order);
    }

    @ApiOperation("根据orderNo查询订单")
    @GetMapping("/getByOrderNo/{orderNo}")
    public ApiResult<Order> getByOrderNo(@PathVariable("orderNo") String orderNo) {
        final User loginUser = getLoginUser();
        if (loginUser == null) {
            return fail("请先登录", null);
        }

        final Order order = orderService.getByOutTradeNo(orderNo);
        if (order != null) {
            final List<OrderInfo> orderInfoList = orderInfoService.list(new LambdaQueryWrapper<OrderInfo>().eq(OrderInfo::getOrderId, order.getOrderId()));
            order.setOrderInfo(orderInfoList);
        }
        return success(order);
    }


    @PreAuthorize("hasAuthority('shop:order:verification')")
    @ApiOperation("根据orderNo核销订单")
    @GetMapping("/verification/{orderNo}")
    public ApiResult<Order> verification(@PathVariable("orderNo") String orderNo, HttpServletRequest request) {
        final User loginUser = getLoginUser();
        if (loginUser == null) {
            return fail("请先登录", null);
        }

        final Set<String> collect = loginUser.getRoles().stream().map(Role::getRoleCode).collect(Collectors.toSet());
        final boolean merchant = Arrays.asList(collect).contains("merchant");
        final boolean merchantClerk = Arrays.asList(collect).contains("merchantClerk");

        if (merchant || merchantClerk) {
            System.out.println("merchant = " + merchant);
            System.out.println("merchantClerk = " + merchantClerk);
            final Order order = orderService.getByOutTradeNo(orderNo);
            if (order != null) {
                final List<OrderInfo> orderInfoList = orderInfoService.list(new LambdaQueryWrapper<OrderInfo>().eq(OrderInfo::getOrderId, order.getOrderId()));
                order.setOrderInfo(orderInfoList);
            }
            return success(order);
        }
        return fail("核销失败", null);
    }

    @ApiOperation("代付")
    @PostMapping("/friend-pay")
    public ApiResult<?> friendPay(@RequestBody Order orderTmp, HttpServletRequest request) throws IOException, WxErrorException {
        Order order = orderService.getById(orderTmp.getOrderId());
        String access_token = JwtUtil.getAccessToken(request);
        // 记录当前登录用户id
        User loginUser = getLoginUser();
        if (loginUser == null) {
            return fail("请先登录");
        }
        // 微信openid(必填)
        if (StrUtil.isBlank(loginUser.getOpenid())) {
            return fail("微信openid(必填)");
        }
        // 微信支付(商品金额不能为0)
        if (order.getPayType().equals(PAY_TYPE_WECHAT)) {
            if (order.getTotalPrice().compareTo(BigDecimal.ZERO) == 0) {
                return fail("商品金额不能为0");
            }
        }
        order.setFriendPayType(orderTmp.getFriendPayType());
        order.setOpenid(loginUser.getOpenid());
        order.setOrderNo(Long.toString(IdUtil.getSnowflakeNextId()));
        order.setAccessToken(access_token);
        order.setPayUserId(loginUser.getUserId());
        orderService.updateById(order);
        order.setLoginUser(loginUser);
        // 调起支付
        order.setNotClearData(true);
        return onPay(request, order);
    }

    @ApiOperation("下单")
    @PostMapping()
    public ApiResult<?> save(@RequestBody Order order, HttpServletRequest request) throws IOException, WxErrorException {
        String access_token = JwtUtil.getAccessToken(request);
        // 记录当前登录用户id
        User loginUser = getLoginUser();
        if (loginUser == null) {
            return fail("请先登录");
        }
        // 微信openid(必填)
        if (StrUtil.isBlank(loginUser.getOpenid())) {
            return fail("微信openid(必填)");
        }
        // 商品描述(必填)
        if (StrUtil.isBlank(order.getComments())) {
            return fail("商品描述(必填)");
        }
        // 微信支付(商品金额不能为0)
        if (order.getPayType().equals(PAY_TYPE_WECHAT)) {
            if (order.getTotalPrice().compareTo(BigDecimal.ZERO) == 0) {
                return fail("商品金额不能为0");
            }
        }

        // 已下过订单
        if (order.getOrderId() != null) {
            Order order1 = orderService.getByIdRel(order.getOrderId());
            order1.setPayType(order.getPayType());
            order1.setOpenid(loginUser.getOpenid());
            order1.setOrderNo(Long.toString(IdUtil.getSnowflakeNextId()));
            order1.setAccessToken(access_token);
            order1.setLoginUser(loginUser);
            order1.setPayUserId(loginUser.getUserId());
            // 调起支付
            return onPay(request, order1);
        }

        // 创建订单
        long timeMillis = System.currentTimeMillis();
        long orderNo = IdUtil.getSnowflakeNextId();
        String name = loginUser.getRealName();
        String phone = loginUser.getPhone();
        String address = "";
        if (order.getRealName() != null) {
            name = order.getRealName();
        }
        if (order.getPhone() != null) {
            phone = order.getPhone();
        }
        if (order.getAddress() != null) {
            address = order.getAddress();
        }
        order.setOrderNo(Long.toString(orderNo));
        order.setUserId(loginUser.getUserId());
        order.setOpenid(loginUser.getOpenid());
        order.setRealName(name);
        order.setPhone(phone);
        order.setAddress(address);
        order.setUserId(loginUser.getUserId());
        order.setLoginUser(loginUser);
        order.setPayUserId(loginUser.getUserId());
        order.setAccessToken(access_token);
        order.setExpirationTime(DateUtil.offset(DateUtil.date(), DateField.MINUTE, 1));
        if (order.getOrderInfo() != null) {
            order.setTotalNum(order.getOrderInfo().size());
        }
        if (order.getGoodsList() != null) {
            order.setTotalNum(order.getGoodsList().size());
        }
        if (order.getDeliveryType().equals(1)) {
            order.setSelfTakeCode(RandomUtil.randomString(4));
        }

        if (orderService.save(order)) {
            // 商城订单
            if (ObjectUtil.isNotEmpty(order.getGoodsList())) {
                order.getGoodsList().forEach(d -> {
                    d.setOrderId(order.getOrderId());
                    d.setTimeFlag(timeMillis);
                    d.setVersion(10);
                    d.setDateTime(DateUtil.date());
                    d.setUserId(getLoginUser().getUserId());
                    d.setExpirationTime(order.getExpirationTime());
                });
                orderGoodsService.saveBatch(order.getGoodsList());
            }
            // 预定订单
            if (ObjectUtil.isNotEmpty(order.getOrderInfo())) {
                if (ObjectUtil.isNotEmpty(order.getOrderInfo())) {
                    order.getOrderInfo().forEach(d -> {
                        d.setOrderId(order.getOrderId());
                        d.setTimeFlag(timeMillis);
                        d.setVersion(10);
                        d.setUserId(getLoginUser().getUserId());
                        d.setDateTime(d.getDateTime());
                        d.setExpirationTime(order.getExpirationTime());
                        d.setTenantId(order.getTenantId());
                    });
                    orderInfoService.saveBatch(order.getOrderInfo());
                }
            }
            // 调起支付
            return onPay(request, order);
        }
        return fail("下单失败");
    }

    private ApiResult<?> onPay(HttpServletRequest request, Order order) throws IOException, WxErrorException {
        // 余额支付
        if (order.getPayType().equals(PAY_TYPE_BALANCE)) {
            order.setAccessToken(order.getAccessToken());
            final User loginUser = order.getLoginUser();
            if (loginUser.getBalance().compareTo(order.getTotalPrice()) < 0) {
                throw new BusinessException("余额不足");
            }
            if (order.getNotClearData() == null) {
                // 清空购物车
                final Set<Integer> cartIds = order.getGoodsList().stream().map(OrderGoods::getGoodsId).collect(Collectors.toSet());
                cartService.remove(new LambdaQueryWrapper<Cart>().eq(Cart::getUserId, order.getUserId()).in(Cart::getGoodsId, cartIds));
                // 外卖订单
                if (!order.getMerchantId().equals(0)) {
                    cartService.remove(new LambdaQueryWrapper<Cart>().eq(Cart::getUserId, order.getUserId()).eq(Cart::getType, 1));
                }
            }
            return success("下单成功", requestUtil.balancePay(order));
        }

        //  微信统一下单接口
        if (order.getPayType().equals(PAY_TYPE_WECHAT)) {
            // 清空购物车
            if (order.getNotClearData() == null) {
                final Set<Integer> cartIds = order.getGoodsList().stream().map(OrderGoods::getGoodsId).collect(Collectors.toSet());
                cartService.remove(new LambdaQueryWrapper<Cart>().eq(Cart::getUserId, order.getUserId()).in(Cart::getGoodsId, cartIds));
                // 外卖订单
                if (!order.getMerchantId().equals(0)) {
                    cartService.remove(new LambdaQueryWrapper<Cart>().eq(Cart::getUserId, order.getUserId()).eq(Cart::getType, 1));
                }
            }
            return success("下单成功", orderService.createWxOrder(order));
        }

        //  代付
        if (order.getPayType().equals(PAY_TYPE_FRIEND)) {
            if (order.getFriendPayType() != null) {
                if (order.getFriendPayType().equals(PAY_TYPE_BALANCE)) {
                    order.setAccessToken(order.getAccessToken());
                    final User loginUser = order.getLoginUser();
                    if (loginUser.getBalance().compareTo(order.getTotalPrice()) < 0) {
                        throw new BusinessException("余额不足");
                    }
                    return success("下单成功", requestUtil.balancePay(order));
                }
                if (order.getFriendPayType().equals(PAY_TYPE_WECHAT)) {
                    return success("下单成功", orderService.createWxOrder(order));
                }
            }
            String filepath = uploadPath + "qrcode/" + getTenantId();
            if (!FileUtil.exist(filepath)) FileUtil.mkdir(filepath);
            String filename = "/friendPay_" + order.getOrderId() + ".png";
            weChatController.makeQr(request, filepath + filename, "orderId=" + order.getOrderId(), "package/order/friendPay");
            return success("下单成功", "file/qrcode/" + getTenantId() + filename);
        }
        return fail("支付失败");
    }

    @ApiOperation("自提")
    @PostMapping("/self-take")
    public ApiResult<?> selfTake(@RequestBody Order order, HttpServletRequest request) {
        String access_token = JwtUtil.getAccessToken(request);
        Order order1 = orderService.getById(order.getOrderId());
//        if (!order1.getSelfTakeCode().equals(order.getSelfTakeCode())) return fail("自提码不正确");
        if (order1.getOrderStatus().equals(1)) return fail("订单已完成");
        order1.setOrderStatus(1);
        orderService.updateById(order1);
        orderService.settle(access_token, getTenantId().toString(), order1);
        return success("提货成功");
    }

    @ApiOperation("外卖确认收货")
    @PostMapping("/out-take-confirm")
    public ApiResult<?> outTakeConfirm(@RequestBody Order order, HttpServletRequest request) {
        String access_token = JwtUtil.getAccessToken(request);
        Order order1 = orderService.getById(order.getOrderId());
        if (order1.getOrderStatus().equals(1)) return fail("订单已完成");
        order1.setOrderStatus(1);
        order1.setHasTakeGift(order.getHasTakeGift());
        orderService.updateById(order1);
        orderService.settle(access_token, getTenantId().toString(), order1);
        return success("外卖确认收货");
    }

    @ApiOperation("修改订单")
    @PutMapping()
    public ApiResult<?> update(@RequestBody Order order) {
        if (order.getOrderStatus().equals(2)) {
            order.setExpirationTime(DateUtil.date());
            orderInfoService.update(new LambdaUpdateWrapper<OrderInfo>().eq(OrderInfo::getOrderId, order.getOrderId()).set(OrderInfo::getExpirationTime, DateUtil.date()));
        }
        if (orderService.updateById(order)) {
            return success("操作成功");
        }
        return fail("操作失败");
    }

    @ApiOperation("删除订单")
    @DeleteMapping("/{id}")
    public ApiResult<?> remove(@PathVariable("id") Integer id) {
        if (orderService.removeById(id)) {
            return success("删除成功");
        }
        return fail("删除失败");
    }

    @ApiOperation("批量添加订单")
    @PostMapping("/batch")
    public ApiResult<?> saveBatch(@RequestBody List<Order> list) {
        if (orderService.saveBatch(list)) {
            return success("添加成功");
        }
        return fail("添加失败");
    }

    @ApiOperation("批量修改订单")
    @PutMapping("/batch")
    public ApiResult<?> removeBatch(@RequestBody BatchParam<Order> batchParam) {
        if (batchParam.update(orderService, "order_id")) {
            return success("修改成功");
        }
        return fail("修改失败");
    }

    @ApiOperation("批量删除订单")
    @DeleteMapping("/batch")
    public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
        if (orderService.removeByIds(ids)) {
            return success("删除成功");
        }
        return fail("删除失败");
    }
}
