package com.dora.service.impl;

import com.dora.entity.FanPromotionCommission;
import com.dora.entity.Order;
import com.dora.entity.RevenueConfig;
import com.dora.entity.User;
import com.dora.event.UserGainedFanEvent;
import com.dora.event.UserGainedPromotionCommissionEvent;
import com.dora.mapper.FanPromotionCommissionMapper;
import com.dora.mapper.RevenueConfigMapper;
import com.dora.mapper.UserMapper;
import com.dora.service.PromotionCommissionService;
import com.dora.service.UserBalanceService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.List;

/**
 * 推广分成服务实现类
 * 负责实时处理推广分成逻辑，确保数据安全性和性能优化
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class PromotionCommissionServiceImpl implements PromotionCommissionService {

    private final FanPromotionCommissionMapper fanPromotionCommissionMapper;
    private final UserMapper userMapper;
    private final RevenueConfigMapper revenueConfigMapper;
    private final UserBalanceService userBalanceService;
    private final ApplicationEventPublisher eventPublisher;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public FanPromotionCommission processOrderPromotionCommission(Order order) {
        try {
            log.info("开始处理订单推广分成 - orderId: {}, userId: {}, amount: {}", 
                    order.getId(), order.getUserId(), order.getAmount());

            // 1. 获取粉丝用户信息
            User fanUser = userMapper.selectById(order.getUserId());
            if (fanUser == null || fanUser.getInviterId() == null) {
                log.debug("用户没有推广人，跳过推广分成处理 - userId: {}", order.getUserId());
                return null;
            }

            Long promoterId = fanUser.getInviterId();
            
            // 2. 验证推广分成的合法性
            if (!validatePromotionCommission(order, promoterId)) {
                log.warn("推广分成验证失败 - orderId: {}, promoterId: {}", order.getId(), promoterId);
                return null;
            }

            // 3. 检查是否已存在推广分成记录（防重复处理）
            if (isCommissionAlreadyExists(order.getId())) {
                log.warn("推广分成记录已存在，跳过处理 - orderId: {}, promoterId: {}", order.getId(), promoterId);
                return null;
            }

            // 4. 获取推广人信息
            User promoter = userMapper.selectById(promoterId);
            if (promoter == null) {
                log.error("推广人不存在 - promoterId: {}", promoterId);
                return null;
            }

            // 5. 直接使用推广人当前等级（不再重复计算，提高性能）
            Integer currentPromotionLevel = promoter.getPromotionLevel();
            if (currentPromotionLevel == null) {
                currentPromotionLevel = 1; // 默认等级
                log.warn("推广人等级为空，使用默认等级1 - promoterId: {}", promoterId);
            }
            
            log.debug("推广分成处理 - promoterId: {}, currentLevel: {}", promoterId, currentPromotionLevel);
            
            // 6. 获取当前等级对应的提成比例
            BigDecimal commissionRate = getCommissionRateByLevel(currentPromotionLevel);
            if (commissionRate.compareTo(BigDecimal.ZERO) <= 0) {
                log.warn("推广等级{}提成比例为0，跳过分成 - promoterId: {}, currentLevel: {}", 
                        currentPromotionLevel, promoterId, currentPromotionLevel);
                return null;
            }

            log.info("推广分成计算 - promoterId: {}, currentLevel: {}, commissionRate: {}", 
                    promoterId, currentPromotionLevel, commissionRate);

            // 7. 计算推广分成金额
            BigDecimal commissionAmount = calculateCommissionAmount(order.getAmount(), commissionRate);

            // 8. 创建推广分成记录（使用当前等级）
            FanPromotionCommission commission = createCommissionRecord(
                    order, promoterId, fanUser.getId(), commissionRate, commissionAmount, currentPromotionLevel);

            // 9. 实时结算：直接增加推广人余额
            settleCommissionImmediately(commission);

            // 12. 发布推广分成事件
            publishPromotionCommissionEvent(commission);

            log.info("推广分成处理完成 - orderId: {}, promoterId: {}, commissionAmount: {}, level: {}", 
                    order.getId(), promoterId, commissionAmount, currentPromotionLevel);

            return commission;

        } catch (DuplicateKeyException e) {
            log.warn("推广分成记录重复，跳过处理 - orderId: {}", order.getId());
            return null;
        } catch (Exception e) {
            log.error("处理订单推广分成失败 - orderId: {}", order.getId(), e);
            throw new RuntimeException("处理推广分成失败", e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean establishPromotionRelationship(Long fanUserId, String inviteCode) {
        try {
            log.info("建立推广关系 - fanUserId: {}, inviteCode: {}", fanUserId, inviteCode);

            if (fanUserId == null || inviteCode == null || inviteCode.trim().isEmpty()) {
                return false;
            }

            // 1. 查找推广人
            User promoter = userMapper.selectByInviteCode(inviteCode.trim());
            if (promoter == null) {
                log.warn("推广码不存在 - inviteCode: {}", inviteCode);
                return false;
            }

            // 2. 防止自己推广自己
            if (promoter.getId().equals(fanUserId)) {
                log.warn("用户不能推广自己 - userId: {}", fanUserId);
                return false;
            }

            // 3. 检查粉丝是否已有推广人
            User fanUser = userMapper.selectById(fanUserId);
            if (fanUser != null && fanUser.getInviterId() != null) {
                log.warn("用户已有推广人，不能重复设置 - userId: {}, existingInviterId: {}", 
                        fanUserId, fanUser.getInviterId());
                return false;
            }

            // 4. 建立推广关系
            int updateResult = userMapper.updateInviterId(fanUserId, promoter.getId());
            if (updateResult <= 0) {
                log.error("更新推广关系失败 - fanUserId: {}, promoterId: {}", fanUserId, promoter.getId());
                return false;
            }

            // 5. 更新邀请人推广等级（基于新的粉丝数）
            try {
                boolean levelUpdated = checkAndUpdatePromoterLevel(promoter.getId());
                if (levelUpdated) {
                    log.info("邀请人推广等级已更新 - promoterId: {}, fanUserId: {}", promoter.getId(), fanUserId);
                }
            } catch (Exception e) {
                log.warn("更新邀请人推广等级失败，但不影响推广关系建立 - promoterId: {}, fanUserId: {}", 
                        promoter.getId(), fanUserId, e);
            }

            // 6. 发布获得粉丝事件（暂时标记为非付费粉丝）
            publishUserGainedFanEvent(promoter.getId(), fanUserId, false);

            log.info("推广关系建立成功 - fanUserId: {}, promoterId: {}", fanUserId, promoter.getId());
            return true;

        } catch (Exception e) {
            log.error("建立推广关系失败 - fanUserId: {}, inviteCode: {}", fanUserId, inviteCode, e);
            return false;
        }
    }

  /**
     * 检查并更新推广人等级
     * 
     * @deprecated 此方法已废弃。根据新的设计，推广等级仅在用户注册时更新，
     *             其他时候直接使用数据库中的promotion_level字段。
     *             如需更新推广等级，请使用PromotionLevelCalculator.updateUserPromotionLevelOnRegistration()
     * @param promoterId 推广人ID
     * @return 始终返回true，保持接口兼容性
     */
    @Override
    @Deprecated
    public boolean checkAndUpdatePromoterLevel(Long promoterId) {
        // 为了保持向后兼容，此方法不再执行实际的等级更新操作
        // 推广等级现在仅在用户注册时更新，以提高系统性能
        log.debug("checkAndUpdatePromoterLevel方法已废弃，不再执行等级更新操作 - promoterId: {}", promoterId);
        return true; // 返回true以保持兼容性，避免影响现有业务流程
    }

    @Override
    public List<FanPromotionCommission> getUserPromotionCommissions(Long userId) {
        return fanPromotionCommissionMapper.selectByPromoterId(userId);
    }

    @Override
    public BigDecimal calculateCommissionAmount(BigDecimal orderAmount, BigDecimal commissionRate) {
        if (orderAmount == null || commissionRate == null) {
            return BigDecimal.ZERO;
        }
        return orderAmount.multiply(commissionRate).setScale(2, RoundingMode.HALF_UP);
    }

    @Override
    public boolean validatePromotionCommission(Order order, Long promoterId) {
        // 1. 订单基本验证
        if (order == null || order.getStatus() != 1 || order.getAmount() == null) {
            return false;
        }

        // 2. 推广人验证
        if (promoterId == null) {
            return false;
        }

        // 3. 防止自己给自己推广分成
        if (promoterId.equals(order.getUserId())) {
            log.warn("推广人不能是订单用户本人 - promoterId: {}, userId: {}", promoterId, order.getUserId());
            return false;
        }

        // 4. 订单金额验证
        if (order.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
            return false;
        }

        return true;
    }

    /**
     * 检查推广分成记录是否已存在
     */
    private boolean isCommissionAlreadyExists(Long orderId) {
        try {
            // 检查是否已为该订单创建过分成记录
            return fanPromotionCommissionMapper.existsByOrderId(orderId);
        } catch (Exception e) {
            log.error("检查推广分成记录是否存在失败 - orderId: {}", orderId, e);
            return true; // 异常时返回true，避免重复创建
        }
    }

    /**
     * 根据推广等级获取提成比例
     */
    private BigDecimal getCommissionRateByLevel(Integer level) {
        if (level == null || level <= 0) {
            return BigDecimal.ZERO;
        }

        try {
            RevenueConfig config = revenueConfigMapper.selectByConfigTypeAndLevel("promotion", level);
            return config != null ? config.getCommissionRate() : BigDecimal.ZERO;
        } catch (Exception e) {
            log.error("获取推广等级提成比例失败 - level: {}", level, e);
            return BigDecimal.ZERO;
        }
    }

    /**
     * 创建推广分成记录
     */
    private FanPromotionCommission createCommissionRecord(Order order, Long promoterId, Long fanId, 
                                                         BigDecimal commissionRate, BigDecimal commissionAmount, 
                                                         Integer commissionLevel) {
        FanPromotionCommission commission = new FanPromotionCommission();
        commission.setPromoterId(promoterId);
        commission.setFanId(fanId);
        commission.setOrderId(order.getId());
        commission.setOrderAmount(order.getAmount());
        commission.setCommissionRate(commissionRate);
        commission.setCommissionLevel(commissionLevel);
        commission.setCommissionAmount(commissionAmount);
        commission.setStatus(0); // 先设为待结算
        commission.setCreateTime(LocalDateTime.now());
        commission.setIsDeleted(0);

        fanPromotionCommissionMapper.insert(commission);
        return commission;
    }

    /**
     * 实时结算推广分成
     */
    private void settleCommissionImmediately(FanPromotionCommission commission) {
        try {
            // 1. 增加推广人余额
            // 获取粉丝用户信息
            User fanUser = userMapper.selectById(commission.getFanId());
            String fanUsername = fanUser != null ? fanUser.getUsername() : "未知用户";
            
            userBalanceService.increaseBalance(
                    commission.getPromoterId(),
                    commission.getCommissionAmount(),
                    "promotion",
                    commission.getId(),
                    String.format("【推广收益】粉丝 %s 购买会员获得Lv%d推广分成 - 订单金额%.2f元，分成%.2f元(%.1f%%)", 
                            fanUsername, commission.getCommissionLevel(), commission.getOrderAmount(),
                            commission.getCommissionAmount(), commission.getCommissionRate().multiply(new BigDecimal("100")))
            );

            // 2. 更新分成记录为已结算
            commission.setStatus(1);
            commission.setSettledAt(LocalDateTime.now());
            fanPromotionCommissionMapper.updateStatus(commission.getId(), 1, commission.getSettledAt());

            log.info("推广分成实时结算完成 - commissionId: {}, promoterId: {}, amount: {}", 
                    commission.getId(), commission.getPromoterId(), commission.getCommissionAmount());

        } catch (Exception e) {
            log.error("推广分成实时结算失败 - commissionId: {}", commission.getId(), e);
            throw new RuntimeException("推广分成结算失败", e);
        }
    }

    /**
     * 计算推广等级（基于总粉丝数）
     * 
     * @deprecated 此方法已废弃。现在使用PromotionLevelCalculator.calculatePromotionLevelByTotalFans()
     *             来统一处理推广等级计算，避免重复代码。
     * @param totalFansCount 总粉丝数
     * @return 推广等级，默认返回1
     */
    @Deprecated
    private int calculatePromotionLevel(int totalFansCount) {
        // 为了保持向后兼容，返回默认等级1
        // 实际的等级计算现在由PromotionLevelCalculator统一处理
        log.debug("calculatePromotionLevel方法已废弃，返回默认等级1 - totalFansCount: {}", totalFansCount);
        return 1;
    }

    /**
     * 发布推广分成事件
     */
    private void publishPromotionCommissionEvent(FanPromotionCommission commission) {
        try {
            UserGainedPromotionCommissionEvent event = new UserGainedPromotionCommissionEvent(
                    this, commission.getPromoterId(), commission.getId(), commission.getCommissionAmount());
            eventPublisher.publishEvent(event);
        } catch (Exception e) {
            log.error("发布推广分成事件失败 - commissionId: {}", commission.getId(), e);
        }
    }

    /**
     * 发布用户获得粉丝事件
     */
    private void publishUserGainedFanEvent(Long promoterId, Long fanId, boolean isPaidFan) {
        try {
            UserGainedFanEvent event = new UserGainedFanEvent(this, promoterId, fanId, isPaidFan);
            eventPublisher.publishEvent(event);
        } catch (Exception e) {
            log.error("发布用户获得粉丝事件失败 - promoterId: {}, fanId: {}", promoterId, fanId, e);
        }
    }
}
