package com.dora.service.impl;

import com.dora.dto.GiftCodeDto;
import com.dora.entity.GiftCode;
import com.dora.entity.GiftCodeUsage;
import com.dora.entity.User;
import com.dora.mapper.GiftCodeMapper;
import com.dora.mapper.GiftCodeUsageMapper;
import com.dora.mapper.UserMapper;
import com.dora.service.GiftCodeService;
import com.dora.service.UserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * 礼品码服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class GiftCodeServiceImpl implements GiftCodeService {

    private final GiftCodeMapper giftCodeMapper;
    private final GiftCodeUsageMapper giftCodeUsageMapper;
    private final UserService userService;
    private final UserMapper userMapper;

    @Override
    @Transactional
    public GiftCodeDto.RedeemResponse redeemGiftCode(Long userId, String code) {
        GiftCodeDto.RedeemResponse response = new GiftCodeDto.RedeemResponse();
        
        try {
            // 1. 查询礼品码
            GiftCode giftCode = giftCodeMapper.selectByCode(code);
            if (giftCode == null) {
                response.setSuccess(false);
                response.setMessage("礼品码不存在");
                return response;
            }

            // 2. 检查礼品码是否有效
            if (giftCode.getIsActive() != 1) {
                response.setSuccess(false);
                response.setMessage("礼品码已禁用");
                return response;
            }

            // 3. 检查礼品码是否过期
            if (giftCode.getExpireTime() != null && giftCode.getExpireTime().isBefore(LocalDateTime.now())) {
                response.setSuccess(false);
                response.setMessage("礼品码已过期");
                return response;
            }

            // 4. 检查礼品码使用次数
            if (giftCode.getUsedCount() >= giftCode.getTotalCount()) {
                response.setSuccess(false);
                response.setMessage("礼品码已被使用完");
                return response;
            }

            // 5. 检查用户是否已使用过该礼品码
            int usedCount = giftCodeUsageMapper.countByUserAndCode(userId, giftCode.getId());
            if (usedCount > 0) {
                response.setSuccess(false);
                response.setMessage("您已使用过该礼品码");
                return response;
            }

            // 6. 获取用户信息
            User user = userService.getUserById(userId);
            if (user == null) {
                response.setSuccess(false);
                response.setMessage("用户不存在");
                return response;
            }

            // 7. 创建使用记录
            GiftCodeUsage usage = new GiftCodeUsage();
            usage.setGiftCodeId(giftCode.getId());
            usage.setUserId(userId);
            usage.setCode(code);
            usage.setType(giftCode.getType());
            usage.setPoints(giftCode.getPoints());
            usage.setPointsExpireDays(giftCode.getPointsExpireDays());
            usage.setTargetRole(giftCode.getTargetRole());
            usage.setDurationDays(giftCode.getDurationDays());
            usage.setOldRole(user.getRole());
            usage.setOldPoints(user.getPoints());
            usage.setOldPointsExpiresAt(user.getPointsExpiresAt());
            usage.setOldExpiresAt(user.getMembershipExpiresAt());

            // 8. 根据礼品码类型处理
            if (giftCode.getType() == 1) {
                // 积分卡
                handlePointsCard(user, giftCode, usage);
            } else if (giftCode.getType() == 2) {
                // 会员卡
                handleMembershipCard(user, giftCode, usage);
            } else {
                response.setSuccess(false);
                response.setMessage("无效的礼品码类型");
                return response;
            }

            // 9. 更新用户信息
            user.setUpdateTime(LocalDateTime.now());
            int updateResult = userMapper.updateById(user);
            if (updateResult <= 0) {
                response.setSuccess(false);
                response.setMessage("用户信息更新失败");
                return response;
            }

            // 10. 更新礼品码使用次数
            int updateCount = giftCodeMapper.updateUsedCount(giftCode.getId(), giftCode.getUsedCount() + 1);
            log.info("更新礼品码使用次数 - giftCodeId: {}, oldUsedCount: {}, newUsedCount: {}, updateResult: {}", 
                    giftCode.getId(), giftCode.getUsedCount(), giftCode.getUsedCount() + 1, updateCount);
            
            if (updateCount <= 0) {
                log.error("更新礼品码使用次数失败 - giftCodeId: {}", giftCode.getId());
                response.setSuccess(false);
                response.setMessage("更新礼品码使用次数失败");
                return response;
            }

            // 11. 保存使用记录
            usage.setStatus(1);
            usage.setCreateTime(LocalDateTime.now());
            giftCodeUsageMapper.insert(usage);

            // 12. 构建响应
            response.setSuccess(true);
            response.setType(giftCode.getType());
            response.setName(giftCode.getName());
            response.setPoints(giftCode.getPoints());
            response.setPointsExpireDays(giftCode.getPointsExpireDays());
            response.setTargetRole(giftCode.getTargetRole());
            response.setDurationDays(giftCode.getDurationDays());
            response.setNewRole(usage.getNewRole());
            response.setNewPoints(usage.getNewPoints());
            response.setNewPointsExpiresAt(usage.getNewPointsExpiresAt() != null ? 
                usage.getNewPointsExpiresAt().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME) : null);
            response.setNewExpiresAt(usage.getNewExpiresAt() != null ? 
                usage.getNewExpiresAt().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME) : null);

            if (giftCode.getType() == 1) {
                response.setMessage("积分充值成功！积分已增加 " + giftCode.getPoints() + " 点");
            } else {
                response.setMessage("兑换成功！您已升级为" + getRoleName(giftCode.getTargetRole()) + "会员");
            }

            log.info("礼品码兑换成功 - userId: {}, code: {}, type: {}", userId, code, giftCode.getType());

        } catch (Exception e) {
            log.error("礼品码兑换失败 - userId: {}, code: {}", userId, code, e);
            response.setSuccess(false);
            response.setMessage("兑换失败：" + e.getMessage());
        }

        return response;
    }

    /**
     * 处理积分卡
     */
    private void handlePointsCard(User user, GiftCode giftCode, GiftCodeUsage usage) {
        // 计算新的积分到期时间
        LocalDateTime newPointsExpiresAt;
        if (user.getPointsExpiresAt() != null && user.getPointsExpiresAt().isAfter(LocalDateTime.now())) {
            // 如果当前积分未过期，在现有基础上延长
            newPointsExpiresAt = user.getPointsExpiresAt().plusDays(giftCode.getPointsExpireDays());
        } else {
            // 如果当前积分已过期，从当前时间开始计算
            newPointsExpiresAt = LocalDateTime.now().plusDays(giftCode.getPointsExpireDays());
        }

        // 更新用户积分和积分到期时间
        user.setPoints(user.getPoints() + giftCode.getPoints());
        user.setPointsExpiresAt(newPointsExpiresAt);
        
        usage.setNewPoints(user.getPoints());
        usage.setNewPointsExpiresAt(newPointsExpiresAt);
        usage.setNewRole(user.getRole());
        usage.setNewExpiresAt(user.getMembershipExpiresAt());
    }

    /**
     * 处理会员卡
     */
    private void handleMembershipCard(User user, GiftCode giftCode, GiftCodeUsage usage) {
        // 计算新的会员到期时间
        LocalDateTime newExpiresAt;
        if (user.getMembershipExpiresAt() != null && user.getMembershipExpiresAt().isAfter(LocalDateTime.now())) {
            // 如果当前会员未过期，在现有基础上延长
            newExpiresAt = user.getMembershipExpiresAt().plusDays(giftCode.getDurationDays());
        } else {
            // 如果当前会员已过期，从当前时间开始计算
            newExpiresAt = LocalDateTime.now().plusDays(giftCode.getDurationDays());
        }

        // 更新用户角色（取最高等级）
        int newRole = Math.max(user.getRole(), giftCode.getTargetRole());
        
        user.setRole(newRole);
        user.setMembershipExpiresAt(newExpiresAt);
        
        usage.setNewRole(newRole);
        usage.setNewExpiresAt(newExpiresAt);
        usage.setNewPoints(user.getPoints());
        usage.setNewPointsExpiresAt(user.getPointsExpiresAt());
    }

    /**
     * 获取角色名称
     */
    private String getRoleName(Integer role) {
        switch (role) {
            case 0: return "游客";
            case 1: return "普通";
            case 2: return "VIP";
            case 3: return "SVIP";
            default: return "未知";
        }
    }
} 