package beilv.vipCardLog.service.impl;

import beilv.admissionticket.domain.AdmissionTicket;
import beilv.admissionticket.mapper.AdmissionTicketMapper;
import beilv.admissionticket.service.IAdmissionTicketService;
import beilv.carinformation.domain.CarInformation;
import beilv.carinformation.service.ICarInformationService;
import beilv.common.core.domain.AjaxResult;
import beilv.common.core.text.Convert;
import beilv.common.utils.DateUtils;
import beilv.common.utils.DictUtils;
import beilv.common.utils.StringUtils;
import beilv.common.utils.uuid.IdUtils;
import beilv.competition.domain.Competition;
import beilv.competition.service.ICompetitionService;
import beilv.system.service.ISysConfigService;
import beilv.usermembershipcard.domain.UserMembershipCard;
import beilv.usermembershipcard.service.IUserMembershipCardService;
import beilv.vipCard.domain.VipCard;
import beilv.vipCard.service.IVipCardService;
import beilv.vipCardAmountLog.domain.VipCardAmountLog;
import beilv.vipCardAmountLog.mapper.VipCardAmountLogMapper;
import beilv.vipCardLog.domain.VipCardLog;
import beilv.vipCardLog.mapper.VipCardLogMapper;
import beilv.vipCardLog.service.IVipCardLogService;
import beilv.voucher.domain.BeilvVoucherMember;
import beilv.voucher.mapper.BeilvVoucherMemberMapper;
import org.apache.commons.collections4.MapUtils;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Map;

import static beilv.competition.domain.Constant.ORDER_QUEUE;

/**
 * 充值记录Service业务层处理
 *
 * @author LG
 * @date 2025-11-12
 */
@Service
public class VipCardLogServiceImpl implements IVipCardLogService {
    @Resource
    private VipCardLogMapper vipCardLogMapper;

    @Autowired
    private IVipCardService vipCardService;

    @Autowired
    private ICompetitionService competitionService;

    @Autowired
    private IUserMembershipCardService userMembershipCardService;

    @Autowired
    private ICarInformationService carInformationService;

    @Autowired
    private IAdmissionTicketService ticketService;

    @Autowired
    private ISysConfigService configService;

    @Resource
    private VipCardAmountLogMapper amountLogMapper;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private BeilvVoucherMemberMapper beilvVoucherMemberMapper;

    /**
     * 查询充值记录
     *
     * @param id 充值记录主键
     * @return 充值记录
     */
    @Override
    public VipCardLog selectVipCardLogById(String id) {
        return vipCardLogMapper.selectVipCardLogById(id);
    }

    /**
     * 查询充值记录列表
     *
     * @param vipCardLog 充值记录
     * @return 充值记录
     */
    @Override
    public List<VipCardLog> selectVipCardLogList(VipCardLog vipCardLog) {
        List<VipCardLog> list = vipCardLogMapper.selectVipCardLogList(vipCardLog);
        Map<String, String> orderType = DictUtils.getDictCacheToMap("order_type");
        Map<String, String> paymentStatus = DictUtils.getDictCacheToMap("payment_status");
        Map<String, String> paymentType = DictUtils.getDictCacheToMap("payment_type");
        for (VipCardLog var : list) {
            var.setOrderTypeText(MapUtils.getString(orderType, var.getOrderType()));
            var.setPaymentStatusText(MapUtils.getString(paymentStatus, var.getPaymentStatus()));
            var.setPaymentTypeText(MapUtils.getString(paymentType, var.getPaymentType()));
        }
        return list;
    }

    /**
     * 新增充值记录
     *
     * @param vipCardLog 充值记录
     * @return 结果
     */
    @Override
    public int insertVipCardLog(VipCardLog vipCardLog) {
        return vipCardLogMapper.insertVipCardLog(vipCardLog);
    }

    /**
     * 修改充值记录
     *
     * @param vipCardLog 充值记录
     * @return 结果
     */
    @Override
    public int updateVipCardLog(VipCardLog vipCardLog) {
        return vipCardLogMapper.updateVipCardLog(vipCardLog);
    }

    /**
     * 批量删除充值记录
     *
     * @param ids 需要删除的充值记录主键
     * @return 结果
     */
    @Override
    public int deleteVipCardLogByIds(String ids) {
        return vipCardLogMapper.deleteVipCardLogByIds(Convert.toStrArray(ids));
    }

    /**
     * 删除充值记录信息
     *
     * @param id 充值记录主键
     * @return 结果
     */
    @Override
    public int deleteVipCardLogById(String id) {
        return vipCardLogMapper.deleteVipCardLogById(id);
    }


    @Override
    public int updateVipCardLogByOrderId(VipCardLog vipCardLog) {
        //验证订单编号是否为空
        if (StringUtils.isEmpty(vipCardLog.getId())) {
            return 0;
        }
        //拉去订单信息
        VipCardLog orderInfo = vipCardLogMapper.selectVipCardLogById(vipCardLog.getId());
        //充值订单和其他订单处理方式不同
        if ("chongzhi".equals(orderInfo.getOrderType())) {
            charging(vipCardLog, orderInfo);
        } else {
            other(vipCardLog, orderInfo);
        }
        //更新订单状态
        return vipCardLogMapper.updateVipCardLog(vipCardLog);
    }

    /**
     * 充值回调
     *
     * @param vipCardLog 订单请求信息
     * @param orderInfo  原订单信息
     * @return
     */
    private void charging(VipCardLog vipCardLog, VipCardLog orderInfo) {
        if ("payment_status_have_paid".equals(vipCardLog.getPaymentStatus())) {
            //拉取订单信息
//            VipCardLog orderInfo = vipCardLogMapper.selectVipCardLogById(vipCardLog.getId());
            //获取会员卡信息
            VipCard vipCard = vipCardService.selectVipCardByUserId(orderInfo.getUserId());
            //获取当前余额
            BigDecimal balance = BigDecimal.ZERO;
            String vipCardId;
            if (null == vipCard) {
                //true 没有会员卡; 新增会员卡, 并且设置本次充值金额
                vipCardId = vipCardService.insertVipCard(new VipCard(Long.parseLong(orderInfo.getUserId()), orderInfo.getOriginalPrice(), BigDecimal.ZERO));
            } else {
                balance = vipCard.getBalance();
                vipCardId = vipCard.getId();
                //false 有会员卡,
                vipCardService.updateVipCard(new VipCard(Long.parseLong(orderInfo.getUserId()), orderInfo.getOriginalPrice().add(vipCard.getBalance()).setScale(2, RoundingMode.HALF_UP), vipCard.getScore()));
            }
            //设定支付时间
            vipCardLog.setPaymentTime(DateUtils.getNowDate());
            //写入会员卡流水
            insertAmountLog(new VipCardAmountLog(orderInfo.getUserId(), vipCardId, orderInfo.getId(), balance, orderInfo.getOriginalPrice(), "1"));

            //支付成功移除定时任务
            stringRedisTemplate.delete(ORDER_QUEUE + orderInfo.getId());
        } else if ("payment_status_cancelled".equals(vipCardLog.getPaymentStatus())) {
            //如果是取消, 设置支付状态为取消支付
            vipCardLog.setCancellationTime(DateUtils.getNowDate());
        }
    }

    /**
     * 其他支付回调
     *
     * @param vipCardLog
     * @return
     */
    private void other(VipCardLog vipCardLog, VipCardLog orderInfo) {
        //拉取订单信息
//        VipCardLog orderInfo = vipCardLogMapper.selectVipCardLogById(vipCardLog.getId());
        if ("payment_status_have_paid".equals(vipCardLog.getPaymentStatus())) {
            //支付成功流程
            //设置支付时间
            vipCardLog.setPaymentTime(DateUtils.getNowDate());
            //获取订单类型
            String orderType = orderInfo.getOrderType();
            if ("gouka".equals(orderType)) {
                //如果是购买次卡订单, 拉去卡种信息
                CarInformation carInformation = carInformationService.selectCarInformationById(Long.valueOf(orderInfo.getBusId()));
                //购卡订单, 支付成功, 生成卡片写入到次卡表
                userMembershipCardService.insertUserMembershipCard(new UserMembershipCard(orderInfo.getUserId(), vipCardLog.getId(), carInformation.getTotalNumber(), "0", "3", DateUtils.getNowDate(), orderInfo.getBusId()));
            }

            if ("yueqiu".equals(orderType)) {
                //如果是约球订单
                AdmissionTicket admissionTicket = new AdmissionTicket();
                admissionTicket.setId(orderInfo.getBusId());
                //创建场次定时任务, 到时间自动核销
                ticketService.createTask(admissionTicket);
            }
        } else if ("payment_status_cancelled".equals(vipCardLog.getPaymentStatus())) {
            //如果是取消订单,设置支付状态为取消支付
            vipCardLog.setCancellationTime(DateUtils.getNowDate());
            if ("yueqiu".equals(orderInfo.getOrderType())) {
                //如果是约球订单, 修改球场信息
                AdmissionTicket admissionTicket = new AdmissionTicket();
                admissionTicket.setId(orderInfo.getBusId());
                admissionTicket.setAdmissionTicketStatus("0");
                ticketService.updateBeilvAdmissionTicket(admissionTicket);
            }
        }
    }

    @Override
    public int getRegistrantsNumber(VipCardLog vipCardLog) {
        return vipCardLogMapper.getRegistrantsNumber(vipCardLog);
    }

    @Override
    public AjaxResult refundById(VipCardLog vipCardLog, boolean isOnline, boolean executeUpdate) {


        if (StringUtils.isEmpty(vipCardLog.getId())) {
            return AjaxResult.error("订单编号不能为空!");
        }

        //拉去订单信息
        VipCardLog orderInfo = vipCardLogMapper.selectVipCardLogById(vipCardLog.getId());

        if ("payment_status_to_be_paid".equals(orderInfo.getPaymentStatus())) {
            return AjaxResult.error("订单未支付, 无需退款!");
        }

        if ("payment_status_cancelled".equals(orderInfo.getPaymentStatus())) {
            return AjaxResult.error("订单已取消, 无需退款!");
        }

        if ("payment_status_refunded".equals(orderInfo.getPaymentStatus())) {
            return AjaxResult.error("订单已退款, 无需重复操作!");
        }

        if ("payment_status_verification".equals(orderInfo.getPaymentStatus())) {
            return AjaxResult.error("订单已核销, 无法退款!");
        }

        //退款金额
        BigDecimal refundPrice = BigDecimal.valueOf(0);

        int refundSum = 0;

        if ("yueqiu".equals(orderInfo.getOrderType())) {

            if (isOnline) {
                // 获取设定的取消时间范围(分钟)
                long cancelMinutes = Long.parseLong(configService.selectConfigByKey("cancel.minutes"));
                // 根据订单获取约场的开始时间
                AdmissionTicket admissionTicket = ticketService.selectBeilvAdmissionTicketById(orderInfo.getBusId());
                String format = new SimpleDateFormat("yyyy-MM-dd").format(admissionTicket.getTicketDate());
                String startTime = admissionTicket.getSession().split("-")[0]; // 10:00

                // 当前时间
                LocalDateTime now = LocalDateTime.now();

                // 定义日期时间格式器
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");

                if (startTime.length() == 4) {
                    startTime = "0" + startTime; // 将 8:00 补充成 08:00
                }

                // 将 startTime 转换为 LocalDateTime
                LocalDateTime startDateTime = LocalDateTime.parse(format + " " + startTime, formatter);

                // 计算 startTime 减去 cancelMinutes 后的时间
                LocalDateTime cancelTime = startDateTime.minus(cancelMinutes, ChronoUnit.MINUTES);

                // 判断当前时间是否可以退款
                if (cancelTime.isBefore(now)) {
                    return AjaxResult.error("距离开场不足" + cancelMinutes + "分钟, 不允许线上退款!如需退款请线下联系工作人员!");
                }
            }


            if ("numCard".equals(orderInfo.getPaymentType())) {
                refundSum++;
            } else {
                refundPrice = refundPrice.add(orderInfo.getPracticalMoney());
            }

        } else if ("gouka".equals(orderInfo.getOrderType())) {
            //根据订单id查询会员卡, 用会员卡id验证是否存在未核销的订单, 如果存在不允许退卡.
            if(vipCardLogMapper.hasOrderHavePaid(orderInfo.getId())){
                return AjaxResult.error("次卡存在未核销订单, 无法退款!");
            }

            //拿到次卡信息, 得到剩余使用次数
            UserMembershipCard userMembershipCard = userMembershipCardService.selectUserMembershipCardRecordId(orderInfo.getId());
            //获取原价信息
            CarInformation carInformation = carInformationService.selectCarInformationById(Long.valueOf(orderInfo.getBusId()));

            //计算已使用次数
            BigDecimal useSum = BigDecimal.valueOf(carInformation.getTotalNumber() - userMembershipCard.getRemainingNumber());

            //计算需要支付的金额 = 原价 / 总次数(直接截断，不进行四舍五入) * 已使用次数
            BigDecimal userPrice = carInformation.getOriginalPrice().divide(BigDecimal.valueOf(carInformation.getTotalNumber()), 2, RoundingMode.DOWN).multiply(useSum);

            //实际支付的金额 - 需要支付的金额 = 退款金额
            BigDecimal refundMoner = orderInfo.getPracticalMoney().subtract(userPrice);

            //判断如果退款金额 不大于0, 则设置退款金额为0
            refundMoner = refundMoner.compareTo(BigDecimal.ZERO) > 0 ? refundMoner : BigDecimal.ZERO;

            //计算退款金额
            refundPrice = refundPrice.add(refundMoner);

            userMembershipCard.setState("2");
            userMembershipCardService.updateUserMembershipCard(userMembershipCard);

        } else if ("cansai".equals(orderInfo.getOrderType()) || "menpiao".equals(orderInfo.getOrderType())) {

            //验证赛事状态, 已经开始/已经结束/已经关闭 无法退款
            Competition competition = competitionService.selectCompetitionById(Integer.valueOf(orderInfo.getBusId()));
            if ("competiton_state_5".equals(competition.getCompetitionState())) {
                return AjaxResult.error("赛事已开始, 无法退票!");
            }
            if ("competiton_state_6".equals(competition.getCompetitionState())) {
                return AjaxResult.error("赛事已结束, 无法退票!");
            }
            if ("competiton_state_3".equals(competition.getCompetitionState())) {
                return AjaxResult.error("报名已结束, 无法退票!");
            }
            if ("competiton_state_4".equals(competition.getCompetitionState())) {
                return AjaxResult.error("赛事已关闭, 无法退票!");
            }
            //计算退款金额
            refundPrice = refundPrice.add(orderInfo.getPracticalMoney());
        } else if ("chongzhi".equals(orderInfo.getOrderType())) {
            refundPrice = orderInfo.getPracticalMoney();
        }

        vipCardLog.setRefundPrice(refundPrice);
        orderInfo.setRefundPrice(refundPrice);

        //使用钱包支付的订单, 不走我微信退款
        if (!"weChart".equals(orderInfo.getPaymentType())) {
            executeUpdate = true;
        }
        // executeUpdate=true 时才执行更新操作（包括订单状态、会员卡余额、次卡次数等）
        if (executeUpdate) {
            if ("vipCard".equals(orderInfo.getPaymentType())) {
                //查询会员卡信息
                VipCard vipCard = vipCardService.selectVipCardById(orderInfo.getPaymentId());
                //写入会员卡流水
                VipCardAmountLog vipCardAmountLog = new VipCardAmountLog(orderInfo.getUserId(), orderInfo.getPaymentId(), orderInfo.getId(), vipCard.getBalance(), refundPrice, "1");
                amountLogMapper.insertVipCardAmountLog(vipCardAmountLog);
                vipCard.setBalance(vipCardAmountLog.getRemainingAmount());
                vipCardService.updateVipCard(vipCard);

            } else if ("numCard".equals(orderInfo.getPaymentType())) {
                //查询次卡信息
                UserMembershipCard userMembershipCard = userMembershipCardService.selectUserMembershipCardById(Long.valueOf(orderInfo.getPaymentId()));
                //剩余使用次数+1
                userMembershipCard.setRemainingNumber(userMembershipCard.getRemainingNumber() + refundSum);
                //更新次卡信息
                userMembershipCardService.updateUserMembershipCard(userMembershipCard);
            } else if ("chongzhi".equals(orderInfo.getOrderType())) {
                VipCard vipCard = vipCardService.selectVipCardByUserId(orderInfo.getUserId());
                // 检查余额是否足够退款
                if (vipCard.getBalance().compareTo(orderInfo.getOriginalPrice()) < 0) {
                    return AjaxResult.error("会员卡余额不足，无法完成退款，请前往柜台联系客服!");
                }
                vipCard.setBalance(vipCard.getBalance().subtract(orderInfo.getOriginalPrice()));
                vipCardService.updateVipCard(vipCard);
            }

            vipCardLog.setRefundTime(DateUtils.getNowDate());
            vipCardLog.setPaymentStatus("payment_status_refunded");
            vipCardLogMapper.updateVipCardLog(vipCardLog);

            // 如果是约球订单，更新场次状态
            if ("yueqiu".equals(orderInfo.getOrderType())) {
                AdmissionTicket admissionTicket = new AdmissionTicket();
                admissionTicket.setId(orderInfo.getBusId());
                admissionTicket.setAdmissionTicketStatus("0");
                ticketService.updateBeilvAdmissionTicket(admissionTicket);
            }
            //如果使用了优惠券，释放优惠券
            if (StringUtils.isNotEmpty(orderInfo.getVoucherId())) {
                beilvVoucherMemberMapper.updateBeilvVoucherMember(new BeilvVoucherMember(Long.parseLong(orderInfo.getVoucherId()), "1"));
            }
            return AjaxResult.success("退款成功!");
        }

        // executeUpdate=false 时只返回计算结果，不更新任何状态
        return AjaxResult.success(orderInfo);

    }

    @Override
    public List<Map<String, Object>> selectYueQiuList(VipCardLog vipCardLog) {
        vipCardLog.setOrderType("yueqiu");
        Map<String, String> orderType = DictUtils.getDictCacheToMap("order_type");
        Map<String, String> paymentStatus = DictUtils.getDictCacheToMap("payment_status");
        Map<String, String> paymentType = DictUtils.getDictCacheToMap("payment_type");

        List<Map<String, Object>> maps = vipCardLogMapper.selectYueQiuList(vipCardLog);

        maps.forEach(map -> {
            map.put("orderTypeLabel", MapUtils.getString(orderType, MapUtils.getString(map, "orderType")));
            map.put("paymentStatusLabel", MapUtils.getString(paymentStatus, MapUtils.getString(map, "paymentStatus")));
            map.put("paymentTypeLabel", MapUtils.getString(paymentType, MapUtils.getString(map, "paymentType")));
            map.put("createTime", MapUtils.getString(map, "createTime").replace("T", " "));
            map.put("paymentTime", MapUtils.getString(map, "paymentTime").replace("T", " "));
        });
        return maps;
    }

    @Override
    public List<Map<String, Object>> selectCanSaiList(VipCardLog vipCardLog) {
        List<Map<String, Object>> maps = vipCardLogMapper.selectCanSaiList(vipCardLog);
        Map<String, String> orderType = DictUtils.getDictCacheToMap("order_type");
        Map<String, String> paymentType = DictUtils.getDictCacheToMap("payment_type");
        Map<String, String> competitionState = DictUtils.getDictCacheToMap("competition_state");
        Map<String, String> paymentStatus = DictUtils.getDictCacheToMap("payment_status");
        Map<String, String> competitionType = DictUtils.getDictCacheToMap("competition_type");


        maps.forEach(map -> {
            map.put("orderTypeLabel", MapUtils.getString(orderType, MapUtils.getString(map, "orderType")));
            map.put("paymentTypeLabel", MapUtils.getString(paymentType, MapUtils.getString(map, "paymentType")));
            map.put("competitionStateLabel", MapUtils.getString(competitionState, MapUtils.getString(map, "competitionState")));
            map.put("paymentStatusLabel", MapUtils.getString(paymentStatus, MapUtils.getString(map, "paymentStatus")));
            map.put("publishTime", MapUtils.getString(map, "publishTime").replace("T", " "));
            map.put("applyEndTime", MapUtils.getString(map, "applyEndTime").replace("T", " "));
            map.put("applyStartTime", MapUtils.getString(map, "applyStartTime").replace("T", " "));
            map.put("createTime", MapUtils.getString(map, "createTime").replace("T", " "));
            map.put("paymentTime", MapUtils.getString(map, "paymentTime").replace("T", " "));
            map.put("competitionTypeLabel", MapUtils.getString(competitionType, MapUtils.getString(map, "competitionType")));
        });
        return maps;
    }

    public void insertAmountLog(VipCardAmountLog vipCardAmountLog) {
        amountLogMapper.insertVipCardAmountLog(vipCardAmountLog);
    }
}
