package org.dromara.main.service.impl;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import io.github.linpeilie.Converter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.main.domain.CsMessage;
import org.dromara.main.domain.CsOrderCard;
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.service.ICsOrderCardService;
import org.dromara.main.service.ICsSessionService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

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

    private final CsOrderCardMapper baseMapper;
    private final CsMessageMapper messageMapper;
    private final ICsSessionService sessionService;
    private final Converter converter;

    @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 状状态
            }
        }
    }

}
