package com.dora.service.impl;

import com.dora.dto.PointsConsumptionDto;
import com.dora.entity.PointsConsumptionLog;
import com.dora.entity.User;
import com.dora.mapper.PointsConsumptionLogMapper;
import com.dora.mapper.UserMapper;
import com.dora.service.PointsConsumptionService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 积分消费查询服务实现
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class PointsConsumptionServiceImpl implements PointsConsumptionService {

    private final UserMapper userMapper;
    private final PointsConsumptionLogMapper pointsConsumptionLogMapper;

    @Override
    public PointsConsumptionDto.BalanceResponse getBalance(Long userId) {
        // 查询用户信息
        User user = userMapper.findById(userId);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }

        Integer currentPoints = user.getPoints() != null ? user.getPoints() : 0;
        LocalDateTime pointsExpiresAt = user.getPointsExpiresAt();

        // 计算是否即将过期和剩余天数
        boolean willExpireSoon = false;
        Long daysUntilExpire = null;

        if (pointsExpiresAt != null) {
            LocalDateTime now = LocalDateTime.now();
            if (pointsExpiresAt.isAfter(now)) {
                daysUntilExpire = ChronoUnit.DAYS.between(now, pointsExpiresAt);
                willExpireSoon = daysUntilExpire <= 30; // 30天内过期视为即将过期
            } else {
                // 已过期
                daysUntilExpire = 0L;
                willExpireSoon = false;
            }
        }

        return PointsConsumptionDto.BalanceResponse.builder()
                .currentPoints(currentPoints)
                .pointsExpiresAt(pointsExpiresAt)
                .willExpireSoon(willExpireSoon)
                .daysUntilExpire(daysUntilExpire)
                .build();
    }

    @Override
    public PointsConsumptionDto.ConsumptionLogPageResponse getConsumptionLogs(
            Long userId, Integer page, Integer size, String changeType) {
        
        // 参数校验和默认值
        if (page == null || page < 1) page = 1;
        if (size == null || size < 1) size = 10;
        if (size > 100) size = 100; // 限制最大每页数量

        int offset = (page - 1) * size;

        // 查询记录
        List<PointsConsumptionLog> logs;
        Long total;

        if (changeType != null && !changeType.trim().isEmpty()) {
            // 按类型查询
            if ("consume".equals(changeType)) {
                // 查询有效的消费记录（排除已退款的消费）
                logs = pointsConsumptionLogMapper.selectEffectiveConsumeByUserId(userId, offset, size);
                total = pointsConsumptionLogMapper.countEffectiveConsumeByUserId(userId);
            } else {
                // 其他类型正常查询
                logs = pointsConsumptionLogMapper.selectByUserIdAndType(userId, changeType, offset, size);
                // 注意：这里需要额外实现 countByUserIdAndType，暂时使用全部统计
                total = pointsConsumptionLogMapper.countByUserId(userId);
            }
        } else {
            // 查询全部
            logs = pointsConsumptionLogMapper.selectByUserId(userId, offset, size);
            total = pointsConsumptionLogMapper.countByUserId(userId);
        }

        // 转换为DTO
        List<PointsConsumptionDto.ConsumptionLogResponse> records = logs.stream()
                .map(this::convertToResponse)
                .collect(Collectors.toList());

        // 计算总页数
        int totalPages = (int) Math.ceil((double) total / size);

        // 计算汇总数据
        PointsConsumptionDto.SummaryData summary = calculateSummary(userId);

        return PointsConsumptionDto.ConsumptionLogPageResponse.builder()
                .records(records)
                .total(total)
                .page(page)
                .size(size)
                .totalPages(totalPages)
                .summary(summary)
                .build();
    }

    @Override
    public PointsConsumptionDto.ConsumptionStatsResponse getConsumptionStats(Long userId) {
        // 查询用户信息
        User user = userMapper.findById(userId);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }

        Integer currentPoints = user.getPoints() != null ? user.getPoints() : 0;
        LocalDateTime pointsExpiresAt = user.getPointsExpiresAt();

        // 查询所有记录用于统计
        List<PointsConsumptionLog> allLogs = pointsConsumptionLogMapper.selectByUserId(userId, 0, Integer.MAX_VALUE);
        
        // 查询有效的消费记录（排除已退款的消费）
        List<PointsConsumptionLog> effectiveConsumeLogs = pointsConsumptionLogMapper.selectEffectiveConsumeByUserId(userId, 0, Integer.MAX_VALUE);

        // 统计各类型积分
        int totalRechargePoints = 0;
        int totalConsumePoints = 0;
        int totalRefundPoints = 0;

        // 统计充值和退款
        for (PointsConsumptionLog consumptionLog : allLogs) {
            String type = consumptionLog.getChangeType();
            int amount = consumptionLog.getChangeAmount();

            switch (type) {
                case "recharge":
                    totalRechargePoints += amount;
                    break;
                case "refund":
                    totalRefundPoints += amount;
                    break;
                // 其他类型如 admin_adjust 不单独统计
            }
        }
        
        // 统计有效消费（排除已退款的）
        for (PointsConsumptionLog consumptionLog : effectiveConsumeLogs) {
            int amount = consumptionLog.getChangeAmount();
            totalConsumePoints += Math.abs(amount); // 消费通常是负数，取绝对值
        }

        return PointsConsumptionDto.ConsumptionStatsResponse.builder()
                .currentPoints(currentPoints)
                .totalRechargePoints(totalRechargePoints)
                .totalConsumePoints(totalConsumePoints)
                .totalRefundPoints(totalRefundPoints)
                .pointsExpiresAt(pointsExpiresAt)
                .build();
    }

    // ==================== 私有方法 ====================

    /**
     * 转换为响应DTO
     */
    private PointsConsumptionDto.ConsumptionLogResponse convertToResponse(PointsConsumptionLog consumptionLog) {
        return PointsConsumptionDto.ConsumptionLogResponse.builder()
                .id(consumptionLog.getId())
                .taskNo(consumptionLog.getTaskNo())
                .changeType(consumptionLog.getChangeType())
                .changeTypeName(getChangeTypeName(consumptionLog.getChangeType()))
                .changeAmount(consumptionLog.getChangeAmount())
                .balanceBefore(consumptionLog.getBalanceBefore())
                .balanceAfter(consumptionLog.getBalanceAfter())
                .description(consumptionLog.getDescription())
                .createTime(consumptionLog.getCreateTime())
                .build();
    }

    /**
     * 获取变动类型名称
     */
    private String getChangeTypeName(String changeType) {
        if (changeType == null) return "未知";
        
        switch (changeType) {
            case "recharge":
                return "充值";
            case "consume":
                return "消费";
            case "refund":
                return "退款";
            case "admin_adjust":
                return "管理员调整";
            default:
                return "其他";
        }
    }
    
    /**
     * 计算积分汇总数据
     */
    private PointsConsumptionDto.SummaryData calculateSummary(Long userId) {
        // 查询用户信息
        User user = userMapper.findById(userId);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }

        Integer currentPoints = user.getPoints() != null ? user.getPoints() : 0;
        LocalDateTime pointsExpiresAt = user.getPointsExpiresAt();

        // 查询所有记录用于统计
        List<PointsConsumptionLog> allLogs = pointsConsumptionLogMapper.selectByUserId(userId, 0, Integer.MAX_VALUE);
        
        // 查询有效的消费记录（排除已退款的消费）
        List<PointsConsumptionLog> effectiveConsumeLogs = pointsConsumptionLogMapper.selectEffectiveConsumeByUserId(userId, 0, Integer.MAX_VALUE);

        // 统计各类型积分
        int totalRechargePoints = 0;
        int totalConsumePoints = 0;
        int totalRefundPoints = 0;

        // 统计充值和退款
        for (PointsConsumptionLog consumptionLog : allLogs) {
            String type = consumptionLog.getChangeType();
            int amount = consumptionLog.getChangeAmount();

            switch (type) {
                case "recharge":
                    totalRechargePoints += amount;
                    break;
                case "refund":
                    totalRefundPoints += amount;
                    break;
                // 其他类型如 admin_adjust 不单独统计
            }
        }
        
        // 统计有效消费（排除已退款的）
        for (PointsConsumptionLog consumptionLog : effectiveConsumeLogs) {
            int amount = consumptionLog.getChangeAmount();
            totalConsumePoints += Math.abs(amount); // 消费通常是负数，取绝对值
        }

        return PointsConsumptionDto.SummaryData.builder()
                .currentPoints(currentPoints)
                .totalRechargePoints(totalRechargePoints)
                .totalConsumePoints(totalConsumePoints)
                .totalRefundPoints(totalRefundPoints)
                .pointsExpiresAt(pointsExpiresAt)
                .build();
    }
}

