package cn.ysk.cashier.service.impl.order;

import cn.hutool.core.util.ObjectUtil;
import cn.ysk.cashier.dto.order.ReturnGroupOrderDto;
import cn.ysk.cashier.dto.order.TbGroupOrderInfoDto;
import cn.ysk.cashier.dto.order.TbGroupOrderInfoQueryCriteria;
import cn.ysk.cashier.dto.shop.TbMerchantThirdApplyDto;
import cn.ysk.cashier.exception.BadRequestException;
import cn.ysk.cashier.mapper.order.TbGroupOrderInfoMapper;
import cn.ysk.cashier.pojo.order.TbGroupOrderCoupon;
import cn.ysk.cashier.pojo.order.TbGroupOrderInfo;
import cn.ysk.cashier.mybatis.entity.TbOrderPayment;
import cn.ysk.cashier.repository.order.TbGroupOrderInfoRepository;
import cn.ysk.cashier.service.order.TbGroupOrderCouponService;
import cn.ysk.cashier.service.order.TbGroupOrderInfoService;
import cn.ysk.cashier.service.shop.TbMerchantThirdApplyService;
import cn.ysk.cashier.mybatis.service.TbOrderPaymentService;
import cn.ysk.cashier.thirdpay.resp.GroupOrderReturnResp;
import cn.ysk.cashier.thirdpay.resp.OrderReturnResp;
import cn.ysk.cashier.thirdpay.resp.PublicResp;
import cn.ysk.cashier.thirdpay.service.ThirdPayService;
import cn.ysk.cashier.utils.*;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.Map;
import java.io.IOException;
import java.util.Objects;
import javax.servlet.http.HttpServletResponse;

/**
 * @author ww
 * @description 服务实现
 * @date 2024-05-07
 **/
@Service
@Slf4j
@RequiredArgsConstructor
public class TbGroupOrderInfoServiceImpl implements TbGroupOrderInfoService {

    private final TbGroupOrderInfoRepository tbGroupOrderInfoRepository;
    private final TbGroupOrderInfoMapper tbGroupOrderInfoMapper;
    private final TbGroupOrderCouponService orderCouponService;
    private final TbMerchantThirdApplyService thirdApplyService;

    private final ThirdPayService thirdPayService;
    @Autowired
    private TbOrderPaymentService paymentService;

    @Value("${thirdPay.url}")
    private String url;
    @Value("${thirdPay.groupCallBack}")
    private String groupCallBack;

    @Override
    public Map<String, Object> queryAll(TbGroupOrderInfoQueryCriteria criteria, Pageable pageable) {
        Page<TbGroupOrderInfo> page = tbGroupOrderInfoRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder), pageable);
        return PageUtil.toPage(page.map(tbGroupOrderInfoMapper::toDto));
    }

    @Override
    public List<TbGroupOrderInfoDto> queryAll(TbGroupOrderInfoQueryCriteria criteria) {
        return tbGroupOrderInfoMapper.toDto(tbGroupOrderInfoRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder)));
    }

    @Override
    @Transactional
    public TbGroupOrderInfoDto findById(Integer id) {
        TbGroupOrderInfo tbGroupOrderInfo = tbGroupOrderInfoRepository.findById(id).orElseGet(TbGroupOrderInfo::new);
        ValidationUtil.isNull(tbGroupOrderInfo.getId(), "TbGroupOrderInfo", "id", id);
        TbGroupOrderInfoDto dto = tbGroupOrderInfoMapper.toDto(tbGroupOrderInfo);
        dto.setCoupons(orderCouponService.queryAll(dto.getId()));
        return dto;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public TbGroupOrderInfoDto create(TbGroupOrderInfo resources) {
        return tbGroupOrderInfoMapper.toDto(tbGroupOrderInfoRepository.save(resources));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(TbGroupOrderInfo resources) {
        TbGroupOrderInfo tbGroupOrderInfo = tbGroupOrderInfoRepository.findById(resources.getId()).orElseGet(TbGroupOrderInfo::new);
        ValidationUtil.isNull(tbGroupOrderInfo.getId(), "TbGroupOrderInfo", "id", resources.getId());
        tbGroupOrderInfo.copy(resources);
        tbGroupOrderInfoRepository.save(tbGroupOrderInfo);
    }

    @Override
    public void deleteAll(Integer[] ids) {
        for (Integer id : ids) {
            tbGroupOrderInfoRepository.deleteById(id);
        }
    }

    @Override
    public void download(List<TbGroupOrderInfoDto> all, HttpServletResponse response) throws IOException {
//        List<Map<String, Object>> list = new ArrayList<>();
//        for (TbGroupOrderInfoDto tbGroupOrderInfo : all) {
//            Map<String,Object> map = new LinkedHashMap<>();
//            map.put("订单编号", tbGroupOrderInfo.getOrderNo());
//            map.put(" merchantId",  tbGroupOrderInfo.getMerchantId());
//            map.put("商户Id", tbGroupOrderInfo.getShopId());
//            map.put("用户id", tbGroupOrderInfo.getUserId());
//            map.put("商品id", tbGroupOrderInfo.getProId());
//            map.put("商品图", tbGroupOrderInfo.getProImg());
//            map.put("商品名称", tbGroupOrderInfo.getProName());
//            map.put("团购卷到期日期", tbGroupOrderInfo.getExpDate());
//            map.put("订单类型 预留字段", tbGroupOrderInfo.getOrderType());
//            map.put("支付方式 wechatPay微信支付，aliPay支付宝支付", tbGroupOrderInfo.getPayType());
//            map.put("订单金额", tbGroupOrderInfo.getOrderAmount());
//            map.put("优惠金额", tbGroupOrderInfo.getSaveAmount());
//            map.put("实付金额", tbGroupOrderInfo.getPayAmount());
//            map.put("退单金额", tbGroupOrderInfo.getRefundAmount());
//            map.put("退单数量", tbGroupOrderInfo.getRefundNumber());
//            map.put("数量", tbGroupOrderInfo.getNumber());
//            map.put("订单状态
//                    状态: unpaid-待付款;unused-待使用;closed-已完成;refunding-退款中;refund-已退款;cancelled-已取消;", tbGroupOrderInfo.getStatus());
//            map.put("备注", tbGroupOrderInfo.getRemark());
//            map.put("手机号", tbGroupOrderInfo.getPhone());
//            map.put("付款时间", tbGroupOrderInfo.getPayTime());
//            map.put("是否支持退款 0：不支持 1：支持", tbGroupOrderInfo.getRefundAble());
//            map.put("创建时间", tbGroupOrderInfo.getCreateTime());
//            map.put("卷码核销员", tbGroupOrderInfo.getVerifier());
//            map.put("更新时间", tbGroupOrderInfo.getUpdateTime());
//            map.put("支付订单号", tbGroupOrderInfo.getPayOrderNo());
//            map.put("交易日期", tbGroupOrderInfo.getTradeDay());
//            map.put("原订单id 退单", tbGroupOrderInfo.getSource());
//            list.add(map);
//        }
//        FileUtil.downloadExcel(list, response);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity<Object> returnOrder(ReturnGroupOrderDto param) {
        TbGroupOrderInfo groupOrderInfo = tbGroupOrderInfoRepository.getById(param.getOrderId());
        List<TbGroupOrderCoupon> tbGroupOrderCoupons = orderCouponService.queryNoRefundByOrderId(param.getOrderId());
        if (param.getNum() > tbGroupOrderCoupons.size()) {
            throw new BadRequestException("可退数量不足");
        }
        for (int i = 0; i < param.getNum(); i++) {
            TbGroupOrderCoupon coupon = tbGroupOrderCoupons.get(i);
            coupon.setIsRefund(1);
            coupon.setRefundAmount(param.getRefundAmount());
            coupon.setRefundDesc(param.getRefundDesc());
            coupon.setRefundReason(param.getRefundReason());
            orderCouponService.update(coupon);
        }
        TbMerchantThirdApplyDto thirdApply = thirdApplyService.findById(groupOrderInfo.getMerchantId());
        if (Objects.isNull(thirdApply)) {
            throw new BadRequestException("支付参数配置错误");
        }
        QueryWrapper<TbOrderPayment> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("order_id", param.getOrderId());
        TbOrderPayment payment = paymentService.getOne(queryWrapper);
        PublicResp<OrderReturnResp> publicResp = thirdPayService.returnOrder(
                url,
                thirdApply.getAppId(),
                groupOrderInfo.getOrderNo(),
                payment.getTradeNumber(),
                null,
                "团购卷订单退款",
                param.getRefundAmount().setScale(2, RoundingMode.DOWN).multiply(new BigDecimal(100)).longValue(),
                groupCallBack,
                null,
                thirdApply.getAppToken());

        if (ObjectUtil.isNotNull(publicResp) && ObjectUtil.isNotEmpty(publicResp)) {
            GroupOrderReturnResp returnInfo = JSONUtil.parseJSONStr2T(publicResp.getBizData(), GroupOrderReturnResp.class);
            if ("000000".equals(publicResp.getCode())) {
                //TRADE_REFUND
                if (!"SUCCESS".equals(returnInfo.getState()) && !"TRADE_SUCCESS".equals(returnInfo.getState()) && !returnInfo.getState().equals("ING")) {
                    throw new BadRequestException("退款渠道调用失败,"+returnInfo.getNote());
                }
            } else {
                throw new BadRequestException("退款渠道调用失败:" + publicResp.getMsg());
            }
        }
        groupOrderInfo.setRefundNumber(groupOrderInfo.getRefundNumber() + param.getNum());
        if (groupOrderInfo.getRefundAmount() == null) {
            groupOrderInfo.setRefundAmount(param.getRefundAmount());
        }else {
            groupOrderInfo.setRefundAmount(groupOrderInfo.getRefundAmount().add(param.getRefundAmount()));
        }
        if (groupOrderInfo.getNumber().equals(groupOrderInfo.getRefundNumber())) {
            groupOrderInfo.setRefundAble(0);
            groupOrderInfo.setStatus("refund");
        }
        tbGroupOrderInfoRepository.save(groupOrderInfo);
        return new ResponseEntity<>(HttpStatus.OK);
    }
}