package org.dromara.main.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import io.github.linpeilie.Converter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.main.config.WxPayConfig;
import org.dromara.main.domain.*;
import org.dromara.main.domain.bo.CsOrderCardBo;
import org.dromara.main.domain.vo.CsOrderCardVo;
import org.dromara.main.mapper.CsMessageMapper;
import org.dromara.main.mapper.CsOrderCardMapper;
import org.dromara.main.mapper.MainOrderMapper;
import org.dromara.main.mapper.MainStudentMapper;
import org.dromara.main.service.ICsOrderCardService;
import org.dromara.main.service.ICsSessionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;

@Slf4j
@RequiredArgsConstructor
@Service
public class CsOrderCardServiceImpl implements ICsOrderCardService {

    private final CsOrderCardMapper baseMapper;
    private final CsMessageMapper messageMapper;
    private final ICsSessionService sessionService;
    private final Converter converter;
    private final MainOrderMapper orderMapper;
    private final MainStudentMapper studentMapper;
    @Autowired
    private WxPayConfig wxPayConfig;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public CsOrderCardVo sendOrderCard(CsOrderCardBo bo) {
        CsMessage message = new CsMessage();
        message.setSessionId(bo.getSessionId());
        message.setMsgNo(bo.getMsgNo());
        message.setSenderType(2);
        message.setSenderId(bo.getSenderId());
        message.setMsgType("order_card");
        message.setStatus(1);
        message.setIsRead(0);
        message.setSendTime(LocalDateTime.now());
        messageMapper.insert(message);

        CsOrderCard orderCard = new CsOrderCard();
        orderCard.setMsgId(message.getId());
        orderCard.setSessionId(bo.getSessionId());
        orderCard.setOrderName(bo.getOrderName());
        orderCard.setOrderPrice(bo.getOrderPrice());
        orderCard.setOrderType(bo.getOrderType());
        orderCard.setStatus("pending");
        orderCard.setExpireTime(LocalDateTime.now().plusSeconds(60));
        orderCard.setCreateTime(LocalDateTime.now());
        baseMapper.insert(orderCard);

        Map<String, Object> payload = new HashMap<>();
        payload.put("orderCardId", orderCard.getId());
        payload.put("name", orderCard.getOrderName());
        payload.put("price", orderCard.getOrderPrice().toString());
        payload.put("status", "pending");
        payload.put("expireTime", orderCard.getExpireTime().toString());
        payload.put("countdownSeconds", 60);
        message.setPayload(JSONUtil.toJsonStr(payload));
        messageMapper.updateById(message);

        sessionService.updateLastMessage(bo.getSessionId(), "[结算单]" + bo.getOrderName());

        CsOrderCardVo vo = converter.convert(orderCard, CsOrderCardVo.class);
        if (vo != null) {
            vo.setCountdownSeconds(60L);
        }
        return vo;
    }

    @Override
    public CsOrderCardVo queryById(Long orderCardId) {
        CsOrderCard entity = baseMapper.selectById(orderCardId);
        CsOrderCardVo vo = converter.convert(entity, CsOrderCardVo.class);
        if (vo != null && "pending".equals(vo.getStatus())) {
            long seconds = Duration.between(LocalDateTime.now(), vo.getExpireTime()).getSeconds();
            vo.setCountdownSeconds(Math.max(0, seconds));
        }
        return vo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean payOrderCard(Long orderCardId, Long userId) {
        CsOrderCard orderCard = baseMapper.selectById(orderCardId);
        if (orderCard == null) {
            throw new RuntimeException("结算单不存在");
        }
        if (!"pending".equals(orderCard.getStatus())) {
            throw new RuntimeException("结算单状态异常");
        }
        if (LocalDateTime.now().isAfter(orderCard.getExpireTime())) {
            orderCard.setStatus("expired");
            baseMapper.updateById(orderCard);
            throw new RuntimeException("结算单已过期");
        }

        orderCard.setStatus("paid");
        orderCard.setPayTime(LocalDateTime.now());
        return baseMapper.updateById(orderCard) > 0;
    }

    @Override
    public Boolean cancelOrderCard(Long orderCardId) {
        CsOrderCard update = new CsOrderCard();
        update.setId(orderCardId);
        update.setStatus("cancelled");
        return baseMapper.updateById(update) > 0;
    }

    @Override
    public void checkExpiredOrderCards() {
        List<CsOrderCard> expiredCards = baseMapper.selectList(Wrappers.<CsOrderCard>lambdaQuery()
                .eq(CsOrderCard::getStatus, "pending")
                .le(CsOrderCard::getExpireTime, LocalDateTime.now()));
        if (!expiredCards.isEmpty()) {
            for (CsOrderCard card : expiredCards) {
                card.setStatus("expired");
                baseMapper.updateById(card);
                // 这里可以根据情况扩展同步改变消息 payload 状状态
            }
        }
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String,Object>createPayOrder(Long orderCardId,Long userId) {
        CsOrderCard orderCard = baseMapper.selectById(orderCardId);
        if (orderCard == null) {
            throw new RuntimeException("结算单不存在");
        }
        if (!"pending".equals(orderCard.getStatus())) {
            throw new RuntimeException("结算单状态异常");
        }
//        if(LocalDateTime.now().isAfter(orderCard.getCreateTime())){
//            orderCard.setStatus("expired");
//            baseMapper.updateById(orderCard);
//            throw new RuntimeException("结算单已过期");
//        }


        MainStudent student = studentMapper.selectById(userId);
        if (student == null) {
            throw new ServiceException("用户不存在");
        }
        if(StringUtils.isEmpty(student.getOpenid())){
            throw new ServiceException("用户未绑定微信");
        }
        MainOrder mainOrder= new MainOrder();

        mainOrder.setOrderNo(generateOrderNo());
        mainOrder.setOrderType(2);
        mainOrder.setBuyerType(2);
        mainOrder.setBuyerId(userId);
        mainOrder.setBuyerName(student.getName());
        mainOrder.setSource("miniapp");
        mainOrder.setSellerId(1L);
        mainOrder.setTotalAmount(defaultAmount(orderCard.getOrderPrice()));
        mainOrder.setPaidAmount(BigDecimal.ZERO);
        mainOrder.setRefundAmount(BigDecimal.ZERO);
        mainOrder.setOrderStatus(0);
        mainOrder.setPayStatus(0);
        mainOrder.setBusinessId(orderCard.getId());
        mainOrder.setProductId(orderCard.getId());
        mainOrder.setTenantId(student.getTenantId());
        mainOrder.setRemark(orderCard.getOrderName());
        log.info("创建订单 - 结算单ID: {}, 结算单价格: {}, 转换后的订单价格: {}", orderCard.getId(), orderCard.getOrderPrice(), mainOrder.getTotalAmount());
        orderMapper.insert(mainOrder);

        try {
            log.info("生成微信支付参数 - OpenID: {}, 传入价格: {}, 订单号: {}", student.getOpenid(), orderCard.getOrderPrice(), mainOrder.getOrderNo());
            Map<String, String> wxPayParams = wxPayConfig.createJsapiPayParams(
                student.getOpenid(),
                orderCard.getOrderPrice(),
                orderCard.getOrderName(),
                mainOrder.getOrderNo()
            );

            // 更新订单的预支付ID
            mainOrder.setWechatOrderId(wxPayParams.get("prepayId"));
            orderMapper.updateById(mainOrder);

            // 原有的返回格式保持不变
            Map<String, Object> result = new LinkedHashMap<>();
            result.put("success", true);
            result.put("orderCardId", orderCard.getId());
            result.put("orderId", mainOrder.getId());
            result.put("orderNo", mainOrder.getOrderNo());
            result.put("amount", mainOrder.getTotalAmount());
            result.put("wechatPayParams", wxPayParams); // 新增：返回微信支付参数
            result.put("message", "支付请求成功");
            return result;

        } catch (Exception e) {
            log.error("创建微信支付失败", e);
            Map<String, Object> result = new LinkedHashMap<>();
            result.put("success", false);
            result.put("message", "创建支付失败：" + e.getMessage());
            return result;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void handlePaySuccess(String orderNo) {
        log.info("处理支付成功，订单号：{}", orderNo);

        // 查找主订单
        MainOrder mainOrder = orderMapper.selectOne(
            Wrappers.<MainOrder>lambdaQuery().eq(MainOrder::getOrderNo, orderNo)
        );
        if (mainOrder == null) {
            log.error("支付回调：找不到订单，订单号：{}", orderNo);
            return;
        }

        // 防重复处理
        if (mainOrder.getPayStatus() == 1) {
            log.info("订单已处理过支付成功，订单号：{}", orderNo);
            return;
        }

        // 更新主订单状态（按你的业务逻辑）
        mainOrder.setPayStatus(1); // 已支付
        mainOrder.setOrderStatus(1); // 已完成
        mainOrder.setPaidAmount(mainOrder.getTotalAmount());
        orderMapper.updateById(mainOrder);

        // 更新结算单状态（按你的业务逻辑）
        CsOrderCard orderCard = baseMapper.selectById(mainOrder.getBusinessId());
        if (orderCard != null) {
            orderCard.setStatus("paid");
            orderCard.setPayTime(LocalDateTime.now());
            baseMapper.updateById(orderCard);

            log.info("支付成功处理完成，订单号：{}，结算单ID：{}", orderNo, orderCard.getId());
        }
    }





    private String generateOrderNo() {
        return "ORD" + DateUtil.format(new Date(), "yyyyMMddHHmmss") + RandomUtil.randomNumbers(4);
    }

    private BigDecimal defaultAmount(BigDecimal amount) {
        return amount == null ? BigDecimal.ZERO : amount;
    }


}
