package com.czg.service.market.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson2.JSONArray;
import com.czg.account.entity.ShopInfo;
import com.czg.account.service.ShopInfoService;
import com.czg.constants.PpPackageConstants;
import com.czg.constants.SystemConstants;
import com.czg.enums.OrderNoPrefixEnum;
import com.czg.exception.CzgException;
import com.czg.market.dto.PpPackageOrderDTO;
import com.czg.market.entity.PpPackage;
import com.czg.market.entity.PpPackageOrder;
import com.czg.market.service.PpHelpRecordService;
import com.czg.market.service.PpPackageOrderService;
import com.czg.market.service.PpPackageService;
import com.czg.market.vo.PpOrderListVO;
import com.czg.market.vo.PpPackageVO;
import com.czg.order.dto.GbOrderQueryParam;
import com.czg.order.vo.GbOrderCountVO;
import com.czg.sa.StpKit;
import com.czg.service.market.mapper.PpPackageOrderMapper;
import com.czg.utils.CzgRandomUtils;
import com.czg.utils.PageUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.update.UpdateChain;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 套餐推广订单 服务层实现。
 *
 * @author gyj
 * @since 2025-12-18
 */
@Slf4j
@DubboService
public class PpPackageOrderServiceImpl extends ServiceImpl<PpPackageOrderMapper, PpPackageOrder> implements PpPackageOrderService {

    @Resource
    private PpPackageService ppPackageService;

    @Resource
    private PpHelpRecordService ppHelpRecordService;

    @DubboReference
    private ShopInfoService shopInfoService;

    @Override
    public Long createPackageOrder(Long packageId, Long shopId) {
        PpPackage aPackage = ppPackageService.getPackageById(packageId);
        if (aPackage == null) {
            throw new CzgException("套餐不存在");
        }

        if (!aPackage.getOnlineStatus().equals(SystemConstants.OneZero.ONE)) {
            throw new CzgException("套餐已下架");
        }

        PpPackageOrder order = new PpPackageOrder()
                .setShopId(shopId)
                .setPackageId(packageId)
                .setUserId(StpKit.USER.getLoginIdAsLong())
                .setShareNum(0)
                .setOrderNo(CzgRandomUtils.randomNumber(OrderNoPrefixEnum.PPO, 12, false))
                .setStatus(PpPackageConstants.OrderStatus.PROCESSING)
                .setExpireTime(LocalDateTime.now().plusHours(aPackage.getExpireHours() == null ? 72 : aPackage.getExpireHours()));
        save(order);

        return order.getId();
    }

    @Override
    public PpPackageOrderDTO getOrderDetailById(Long orderId, Long userId) {
        PpPackageOrder order = getById(orderId);
        if (order == null) {
            throw new CzgException("订单不存在");
        }

        PpPackageOrderDTO orderDto = BeanUtil.copyProperties(order, PpPackageOrderDTO.class);

        orderDto.setIsMyself(order.getUserId().equals(userId) ? SystemConstants.OneZero.ONE : SystemConstants.OneZero.ZERO);
        if (PpPackageConstants.OrderStatus.PROCESSING.equals(order.getStatus())) {
            if (orderDto.getIsMyself().equals(SystemConstants.OneZero.ZERO)) {
                boolean canHelp = ppHelpRecordService.canHelp(userId, orderId);
                orderDto.setCanHelp(canHelp ? SystemConstants.OneZero.ONE : SystemConstants.OneZero.ZERO);
            } else {
                orderDto.setCanHelp(SystemConstants.OneZero.ZERO);
            }
        } else {
            orderDto.setCanHelp(0);
        }

        ShopInfo shopInfo = shopInfoService.getById(order.getShopId());
        if (shopInfo != null) {
            orderDto.setShopName(shopInfo.getShopName());
            orderDto.setShopAddress(shopInfo.getAddress());
        }

        PpPackage aPackage = ppPackageService.getById(order.getPackageId());
        aPackage.setShopId(order.getShopId());
        orderDto.setPackageInfo(ppPackageService.convertPackageToVo(aPackage));

        return orderDto;
    }

    @Override
    @Transactional
    public boolean helpOrder(Long orderId) {
        PpPackageOrder order = getById(orderId);
        if (order == null) {
            throw new CzgException("订单不存在");
        }

        if (!PpPackageConstants.OrderStatus.PROCESSING.equals(order.getStatus())) {
            throw new CzgException("订单已结束");
        }

        long loginUserId = StpKit.USER.getLoginIdAsLong();
        if (order.getUserId().equals(loginUserId)) {
            throw new CzgException("不能助力自己");
        }

        if (!ppHelpRecordService.help(loginUserId, orderId)) {
            return false;
        }
        return UpdateChain.of(PpPackageOrder.class)
                .set(PpPackageOrder::getShareNum, order.getShareNum() + 1)
                .eq(PpPackageOrder::getId, orderId)
                .update();
    }

    @Override
    public Page<PpOrderListVO> queryOrderList(Long shopId, Long userId, GbOrderQueryParam param) {
        PageHelper.startPage(param.getPage(), param.getSize());
        List<PpOrderListVO> result = mapper.getOrderList(shopId, userId, param);
        result.forEach(vo -> {
            vo.setImages(vo.getImagesStr() == null ? null : JSONArray.parseArray(vo.getImagesStr(), String.class));
            vo.setTieredDiscount(vo.getTieredDiscountStr() == null ? null : JSONArray.parseArray(vo.getTieredDiscountStr(), PpPackageVO.TieredDiscount.class));
        });
        return PageUtil.convert(new PageInfo<>(result));
    }

    @Override
    public GbOrderCountVO orderCount(Long shopId, GbOrderQueryParam param) {
        return mapper.getOrderCount(shopId, param);
    }

    @Override
    @Transactional
    public boolean cancelOrder(Long orderId) {
        PpPackageOrder order = getById(orderId);
        if (order == null) {
            throw new CzgException("订单不存在");
        }

        if (!PpPackageConstants.OrderStatus.PROCESSING.equals(order.getStatus()) && !PpPackageConstants.OrderStatus.TIMEOUT.equals(order.getStatus())) {
            throw new CzgException("不允许取消");
        }

        if (!order.getUserId().equals(StpKit.USER.getLoginIdAsLong())) {
            throw new CzgException("无权限");
        }

        ppHelpRecordService.removeHelpRecord(orderId);

        order.setStatus(PpPackageConstants.OrderStatus.CANCEL);
        order.setCancelTime(LocalDateTime.now());
        order.setCancelReason("用户取消");

        return updateById(order);
    }

    @Override
    @Transactional
    public boolean applyRefund(Long orderId, Long userId, String refundReason) {
        PpPackageOrder order = getById(orderId);
        if (order == null) {
            throw new CzgException("订单不存在");
        }
        if (!PpPackageConstants.OrderStatus.WAIT_VERIFY.equals(order.getStatus())) {
            throw new CzgException("订单状态错误");
        }

        ppHelpRecordService.removeHelpRecord(orderId);

        order.setStatus(PpPackageConstants.OrderStatus.REFUNDING);
        order.setRefundReason(refundReason);
        return updateById(order);
    }

    @Override
    @Transactional
    public void confirmRefund(Long orderId, Long shopId) {
        PpPackageOrder order = getOne(QueryWrapper.create().eq(PpPackageOrder::getId, orderId)
                .eq(PpPackageOrder::getShopId, shopId));
        if (order == null) {
            throw new CzgException("订单不存在");
        }
        if (!PpPackageConstants.OrderStatus.REFUNDING.equals(order.getStatus())
                && !PpPackageConstants.OrderStatus.WAIT_VERIFY.equals(order.getStatus())
                && !PpPackageConstants.OrderStatus.FINISH.equals(order.getStatus())) {
            throw new CzgException("订单状态错误");
        }

        ppHelpRecordService.removeHelpRecord(orderId);

        UpdateChain.of(PpPackageOrder.class)
                .set(PpPackageOrder::getStatus, PpPackageConstants.OrderStatus.REFUND)
                .eq(PpPackageOrder::getId, orderId)
                .update();
    }

    @Override
    @Transactional
    public boolean cancelRefund(Long orderId, Long userId, String refundReason) {
        PpPackageOrder order = getById(orderId);
        if (order == null) {
            throw new CzgException("订单不存在");
        }
        if (!PpPackageConstants.OrderStatus.REFUNDING.equals(order.getStatus())) {
            throw new CzgException("订单状态错误");
        }

        ppHelpRecordService.removeHelpRecord(orderId);

        order.setStatus(PpPackageConstants.OrderStatus.WAIT_VERIFY);
        order.setRefundReason(refundReason);
        return updateById(order);
    }

    @Override
    @Transactional
    public void paySuccess(Long orderId, Long payOrderId) {
        PpPackageOrder order = getById(orderId);

        order.setStatus(PpPackageConstants.OrderStatus.WAIT_VERIFY);
        order.setPayOrderId(payOrderId);
        order.setPayTime(LocalDateTime.now());
        order.setVerifyCode(CzgRandomUtils.randomNumber(12, true));
        updateById(order);

        ppHelpRecordService.removeHelpRecord(orderId);

        PpPackage ppPackage = ppPackageService.getById(order.getPackageId());
        ppPackage.setSaleNum(ppPackage.getSaleNum() + 1);
        ppPackageService.updateById(ppPackage);
    }

    @Override
    public boolean checkout(String verifyCode, Long shopId) {
        PpPackageOrder packageOrder = getOne(QueryWrapper.create().eq(PpPackageOrder::getVerifyCode, verifyCode)
                .eq(PpPackageOrder::getShopId, shopId));
        if (packageOrder == null) {
            throw new CzgException("核销失败，核销码不存在");
        }
        if (!PpPackageConstants.OrderStatus.WAIT_VERIFY.equals(packageOrder.getStatus())
                && !PpPackageConstants.OrderStatus.REFUNDING.equals(packageOrder.getStatus())) {
            throw new CzgException("核销失败，该订单不可核销");
        }

        packageOrder.setStatus(PpPackageConstants.OrderStatus.FINISH);
        packageOrder.setVerifyTime(LocalDateTime.now());

        return updateById(packageOrder);
    }

    @Override
    @Transactional
    public void expiredOrder(Long orderId) {
        PpPackageOrder order = getById(orderId);
        if (order == null) {
            log.info("套餐推广 订单过期 订单不存在：Id == {}", orderId);
            return;
        }

        if (!PpPackageConstants.OrderStatus.PROCESSING.equals(order.getStatus())) {
            log.info("套餐推广 订单过期 订单状态错误：Id == {}", orderId);
            return;
        }

        order.setStatus(PpPackageConstants.OrderStatus.TIMEOUT);
        updateById(order);

        ppHelpRecordService.removeHelpRecord(orderId);
    }
}
