package com.xy.xyaicpzs.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xy.xyaicpzs.domain.entity.User;
import com.xy.xyaicpzs.domain.entity.VipCode;
import com.xy.xyaicpzs.domain.entity.VipExchangeRecord;
import com.xy.xyaicpzs.mapper.UserMapper;
import com.xy.xyaicpzs.mapper.VipCodeMapper;
import com.xy.xyaicpzs.service.VipCodeService;
import com.xy.xyaicpzs.service.VipExchangeRecordService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Date;
import java.util.UUID;

/**
 * @author XY003
 * @description 针对表【vip_code(会员码表)】的数据库操作Service实现
 * @createDate 2025-01-15 16:41:29
 */
@Slf4j
@Service
public class VipCodeServiceImpl extends ServiceImpl<VipCodeMapper, VipCode> implements VipCodeService {

    @Autowired
    private VipCodeMapper vipCodeMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private VipExchangeRecordService vipExchangeRecordService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean activateVipCode(Long userId, String code) {
        log.info("开始激活会员码，用户ID：{}，会员码：{}", userId, code);

        // 1. 校验参数
        if (userId == null || code == null || code.trim().isEmpty()) {
            throw new IllegalArgumentException("用户ID和会员码不能为空");
        }

        // 2. 查询会员码信息
        QueryWrapper<VipCode> vipCodeQuery = new QueryWrapper<>();
        vipCodeQuery.eq("code", code);
        VipCode vipCode = vipCodeMapper.selectOne(vipCodeQuery);

        if (vipCode == null) {
            throw new IllegalArgumentException("会员码不存在");
        }

        if (vipCode.getIsUse() == 1) {
            throw new IllegalArgumentException("会员码已被使用");
        }

        // 3. 查询用户信息
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new IllegalArgumentException("用户不存在");
        }

        // 4. 根据会员码的vipExpireTime判断会员类型
        String memberType;
        String vipType; // 用户表的vipType字段
        int orderAmount;
        int expireMonths = vipCode.getVipExpireTime();
        if (expireMonths < 12) {
            memberType = "月度会员";
            vipType = "月度会员";
            orderAmount = 10 * expireMonths;
        } else if (expireMonths >= 12) {
            memberType = "年度会员";
            vipType = "年度会员";
            orderAmount = 100 * (expireMonths / 12);
        } else {
            // 支持自定义月份，按比例计算订单金额（10元/月）
            memberType = expireMonths + "个月会员";
            vipType = "月度会员"; // 默认归类为月度会员
            orderAmount = 10 * expireMonths;
        }

        // 5. 先在vip_exchange_record表插入兑换记录
        VipExchangeRecord exchangeRecord = new VipExchangeRecord();
        exchangeRecord.setUserId(userId);
        exchangeRecord.setType(memberType);
        exchangeRecord.setExchangeMode(1); // 1表示会员码兑换
        //生成随机16位订单号
        exchangeRecord.setOrderNo(generateOrderNumber());
        exchangeRecord.setOrderAmount(orderAmount);
        exchangeRecord.setIsUse(1); // 1表示已兑换
        exchangeRecord.setExchangeTime(new Date());
        exchangeRecord.setUpdateTime(new Date());

        boolean recordSaved = vipExchangeRecordService.save(exchangeRecord);
        if (!recordSaved) {
            log.error("保存兑换记录失败，用户ID：{}，会员码：{}", userId, code);
            throw new RuntimeException("保存兑换记录失败");
        }

        log.info("成功插入兑换记录，用户ID：{}，会员类型：{}", userId, memberType);

        // 6. 计算新的会员到期时间
        Date newVipExpire = calculateNewVipExpire(user.getVipExpire(), vipCode.getVipExpireTime());

        // 7. 更新用户会员状态
        User updateUser = new User();
        updateUser.setId(userId);
        updateUser.setIsVip(1); // 设置为会员
        updateUser.setVipExpire(newVipExpire);
        updateUser.setVipType(vipType); // 设置会员类型
        updateUser.setUpdateTime(new Date());

        int userUpdateResult = userMapper.updateById(updateUser);
        if (userUpdateResult == 0) {
            log.error("更新用户会员状态失败，用户ID：{}", userId);
            throw new RuntimeException("更新用户会员状态失败");
        }

        log.info("会员码激活成功，用户ID：{}，会员类型：{}，vipType：{}，新的到期时间：{}", userId, memberType, vipType, newVipExpire);

        // 8. 标记会员码为已使用，并记录使用人信息和使用时间
        Date now = new Date();
        VipCode updateVipCode = new VipCode();
        updateVipCode.setId(vipCode.getId());
        updateVipCode.setIsUse(1);
        updateVipCode.setUpdateTime(now);
        // 添加使用人ID、使用人名称
        updateVipCode.setUsedUserId(userId);
        updateVipCode.setUsedUserName(user.getUserName());

        int vipCodeUpdateResult = vipCodeMapper.updateById(updateVipCode);
        if (vipCodeUpdateResult == 0) {
            log.error("更新会员码状态失败，会员码：{}", code);
            throw new RuntimeException("更新会员码状态失败");
        }

        log.info("会员码激活成功，用户ID：{}，会员类型：{}，新的到期时间：{}", userId, memberType, newVipExpire);
        return true;
    }

    /**
     * 计算新的会员到期时间
     * @param currentVipExpire 当前会员到期时间
     * @param vipExpireTime 会员有效月数
     * @return 新的会员到期时间
     */
    private Date calculateNewVipExpire(Date currentVipExpire, int vipExpireTime) {
        LocalDate baseDate;
        
        // 如果当前已经是会员且未过期，则从当前到期时间开始延长
        if (currentVipExpire != null) {
            LocalDate currentExpireDate = currentVipExpire.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
            LocalDate today = LocalDate.now();
            
            if (currentExpireDate.isAfter(today)) {
                // 当前会员未过期，从到期时间开始延长
                baseDate = currentExpireDate;
            } else {
                // 当前会员已过期，从今天开始计算
                baseDate = today;
            }
        } else {
            // 从未开通过会员，从今天开始计算
            baseDate = LocalDate.now();
        }
        
        // 增加对应的月数
        LocalDate newExpireDate = baseDate.plusMonths(vipExpireTime);
        
        return Date.from(newExpireDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
    }

    @Override
    public int generateVipCodes(int numCodes, int vipExpireTime, Long createdUserId, String createdUserName) {
        log.info("开始生成会员码，数量：{}，有效月数：{}，创建人ID：{}", numCodes, vipExpireTime, createdUserId);

        if (numCodes <= 0) {
            throw new IllegalArgumentException("生成数量必须大于0");
        }

        if (vipExpireTime <= 0) {
            throw new IllegalArgumentException("会员有效月数必须大于0");
        }

        if (numCodes > 1000) {
            throw new IllegalArgumentException("单次生成数量不能超过1000");
        }

        // 获取当前最大的vipNumber
        Integer maxVipNumber = 100000;  // 默认从100001开始（6位数）
        QueryWrapper<VipCode> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByDesc("vipNumber").last("LIMIT 1");
        VipCode maxVipCode = vipCodeMapper.selectOne(queryWrapper);
        if (maxVipCode != null && maxVipCode.getVipNumber() != null) {
            maxVipNumber = Math.max(maxVipNumber, maxVipCode.getVipNumber());
        }

        int successCount = 0;
        Date now = new Date();

        for (int i = 0; i < numCodes; i++) {
            try {
                VipCode vipCode = new VipCode();
                vipCode.setCode(generateUniqueCode());
                vipCode.setVipExpireTime(vipExpireTime);
                
                // 设置会员编号，从最大值+1开始，确保是6位数
                int nextVipNumber = maxVipNumber + i + 1;
                vipCode.setVipNumber(nextVipNumber);
                
                vipCode.setIsUse(0); // 0表示未使用
                vipCode.setCreatedUserId(createdUserId); // 设置创建人ID
                vipCode.setCreatedUserName(createdUserName); // 设置创建人名称
                vipCode.setCreateTime(now);
/*                vipCode.setUpdateTime(now);*/

                int result = vipCodeMapper.insert(vipCode);
                if (result > 0) {
                    successCount++;
                }
            } catch (Exception e) {
                log.error("生成第{}个会员码失败：{}", i + 1, e.getMessage());
            }
        }

        log.info("会员码生成完成，请求生成：{}个，实际成功：{}个", numCodes, successCount);
        return successCount;
    }

    @Override
    public String getAvailableVipCode(int vipExpireTime, Long createdUserId, String createdUserName) {
        log.info("查找可用会员码，有效月数：{}，创建人ID：{}", vipExpireTime, createdUserId);

        if (vipExpireTime <= 0) {
            throw new IllegalArgumentException("会员有效月数必须大于0");
        }

        QueryWrapper<VipCode> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("vipExpireTime", vipExpireTime)
                   .eq("isUse", 0)
                   .orderByAsc("createTime")
                   .last("LIMIT 1");

        VipCode vipCode = vipCodeMapper.selectOne(queryWrapper);
        
        if (vipCode != null) {
            log.info("找到可用会员码：{}", vipCode.getCode());
            return vipCode.getCode();
        } else {
            log.warn("没有找到有效月数为{}的可用会员码", vipExpireTime);
            return null;
        }
    }

    /**
     * 生成唯一的会员码
     * @return 会员码字符串
     */
    private String generateUniqueCode() {
        // 生成16位的随机字符串作为会员码
        String uuid = UUID.randomUUID().toString().replace("-", "");
        return uuid.substring(0, 16).toUpperCase();
    }

    /**
     * 生成16位随机订单号
     * @return 16位订单号
     */
    private Long generateOrderNumber() {
        // 生成16位随机数字订单号
        // 方法1: 时间戳 + 随机数组合（推荐，避免重复）
        long timestamp = System.currentTimeMillis() % 1000000L; // 取6位时间戳
        long random = (long) (Math.random() * 9000000000L) + 1000000000L; // 10位随机数
        return Long.parseLong(String.valueOf(timestamp) + String.valueOf(random));
    }
} 