package com.gxwebsoft.cms.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gxwebsoft.cms.entity.CustomerLeadEntity;
import com.gxwebsoft.cms.entity.LeadReferral;
import com.gxwebsoft.cms.mapper.CustomerLeadMapper;
import com.gxwebsoft.cms.mapper.LeadReferralMapper;
import com.gxwebsoft.cms.param.CustomerLeadParam;
import com.gxwebsoft.cms.param.LeadReferralParam;
import com.gxwebsoft.cms.service.CustomerLeadService;
import com.gxwebsoft.cms.service.LeadReferralService;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.common.system.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

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

/**
 * 推荐人服务实现（全民推荐）
 *
 * @author 科技小王子
 * @since 2026-04-14
 */
@Service
public class LeadReferralServiceImpl extends ServiceImpl<LeadReferralMapper, LeadReferral> implements LeadReferralService {

    @Autowired
    private LeadReferralMapper leadReferralMapper;

    @Autowired
    private CustomerLeadMapper customerLeadMapper;

    @Autowired
    private CustomerLeadService customerLeadService;

    @Autowired
    private UserService userService;

    // 默认推荐费比例 5%
    private static final BigDecimal DEFAULT_REFERRAL_RATE = new BigDecimal("0.05");

    /**
     * 获取当前登录用户（与 BaseController.getLoginUser() 逻辑一致）
     */
    private User getLoginUser() {
        try {
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            if (authentication != null) {
                Object principal = authentication.getPrincipal();
                if (principal instanceof User) {
                    return (User) principal;
                }
            }
        } catch (Exception ignored) {
        }
        return null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public LeadReferral anonymousReferral(LeadReferralParam param) {
        // 1. 如果有推荐码，先查询推荐人
        Integer referrerUserId = null;
        if (StringUtils.hasText(param.getReferralCode())) {
            LeadReferral referral = leadReferralMapper.selectByCode(param.getReferralCode());
            if (referral != null) {
                referrerUserId = referral.getReferrerUserId();
            }
        }

        // 2. 创建客资
        CustomerLeadEntity lead = new CustomerLeadEntity();
        lead.setName(param.getCustomerName());
        lead.setPhone(param.getCustomerPhone());
        lead.setCompany(param.getCustomerCompany());
        lead.setNeed(param.getRequirement());
        lead.setSourceType(CustomerLeadEntity.SOURCE_REFERRAL);
        lead.setStatus(CustomerLeadEntity.STATUS_PENDING);
        lead.setReferrerUserId(referrerUserId);
        lead.setFollowCount(0);
        lead.setReferralFee(BigDecimal.ZERO);
        lead.setReferralFeePaid(0);
        
        if (StringUtils.hasText(param.getAppointmentTime())) {
            lead.setAppointmentTime(LocalDateTime.parse(param.getAppointmentTime().replace(" ", "T")));
        }
        
        customerLeadMapper.insert(lead);

        // 3. 创建推荐关系
        LeadReferral referral = new LeadReferral();
        referral.setReferrerUserId(referrerUserId);
        referral.setReferredLeadId(lead.getLeadId());
        referral.setReferralCode(StringUtils.hasText(param.getReferralCode()) ? param.getReferralCode() : null);
        referral.setReferralFee(param.getReferralFee() != null ? param.getReferralFee() : BigDecimal.ZERO);
        referral.setReferralStatus(LeadReferral.STATUS_PENDING); // 待确认
        referral.setCustomerName(param.getCustomerName());
        referral.setCustomerPhone(param.getCustomerPhone());
        referral.setCreateTime(LocalDateTime.now());
        
        leadReferralMapper.insert(referral);

        // 4. 更新客资的推荐费
        lead.setReferralFee(referral.getReferralFee());
        customerLeadMapper.updateById(lead);

        return referral;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public LeadReferral userReferral(LeadReferralParam param) {
        User currentUser = getLoginUser();
        if (currentUser == null) {
            throw new RuntimeException("请先登录");
        }

        // 1. 创建客资
        CustomerLeadEntity lead = new CustomerLeadEntity();
        lead.setName(param.getCustomerName());
        lead.setPhone(param.getCustomerPhone());
        lead.setCompany(param.getCustomerCompany());
        lead.setNeed(param.getRequirement());
        lead.setSourceType(CustomerLeadEntity.SOURCE_REFERRAL);
        lead.setStatus(CustomerLeadEntity.STATUS_PENDING);
        lead.setReferrerUserId(currentUser.getUserId());
        lead.setFollowCount(0);
        lead.setReferralFee(param.getReferralFee() != null ? param.getReferralFee() : BigDecimal.ZERO);
        lead.setReferralFeePaid(0);
        
        if (StringUtils.hasText(param.getAppointmentTime())) {
            lead.setAppointmentTime(LocalDateTime.parse(param.getAppointmentTime().replace(" ", "T")));
        }
        
        customerLeadMapper.insert(lead);

        // 2. 创建推荐关系
        LeadReferral referral = new LeadReferral();
        referral.setReferrerUserId(currentUser.getUserId());
        referral.setReferredLeadId(lead.getLeadId());
        referral.setReferralCode(this.generateReferralCode()); // 生成推荐码
        referral.setReferralFee(param.getReferralFee() != null ? param.getReferralFee() : BigDecimal.ZERO);
        referral.setReferralStatus(LeadReferral.STATUS_PENDING);
        referral.setCustomerName(param.getCustomerName());
        referral.setCustomerPhone(param.getCustomerPhone());
        referral.setCreateTime(LocalDateTime.now());
        
        leadReferralMapper.insert(referral);

        return referral;
    }

    @Override
    public Map<String, Object> getReferralPage(CustomerLeadParam param) {
        Page<LeadReferral> page = new Page<>(param.getPageNum(), param.getPageSize());
        List<LeadReferral> list = leadReferralMapper.selectReferralPage(param);
        
        Map<String, Object> result = new HashMap<>();
        result.put("list", list);
        result.put("total", page.getTotal());
        result.put("pageNum", param.getPageNum());
        result.put("pageSize", param.getPageSize());
        
        return result;
    }

    @Override
    public Map<String, Object> getReferralStats(Integer userId) {
        Map<String, Object> stats = new HashMap<>();
        
        stats.put("totalCount", leadReferralMapper.countUserReferrals(userId, null));
        stats.put("pendingCount", leadReferralMapper.countUserReferrals(userId, LeadReferral.STATUS_PENDING));
        stats.put("validCount", leadReferralMapper.countUserReferrals(userId, LeadReferral.STATUS_VALID));
        stats.put("settledCount", leadReferralMapper.countUserReferrals(userId, LeadReferral.STATUS_SETTLED));
        stats.put("pendingAmount", leadReferralMapper.sumPendingFee(userId));
        
        return stats;
    }

    @Override
    public String generateReferralCode() {
        return "RF" + System.currentTimeMillis() + (int)(Math.random() * 100);
    }

    @Override
    public Map<String, Object> getReferrerByCode(String referralCode) {
        LeadReferral referral = leadReferralMapper.selectByCode(referralCode);
        if (referral == null || referral.getReferrerUserId() == null) {
            return null;
        }

        User referrer = userService.getByIdRel(referral.getReferrerUserId());
        if (referrer == null) {
            return null;
        }

        Map<String, Object> result = new HashMap<>();
        result.put("referrerId", referrer.getUserId());
        result.put("referrerName", referrer.getNickname());
        result.put("referrerPhone", referrer.getPhone());
        result.put("referralCode", referralCode);
        
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean confirmReferral(Integer referralId) {
        LeadReferral referral = this.getById(referralId);
        if (referral == null) {
            throw new RuntimeException("推荐记录不存在");
        }

        referral.setReferralStatus(LeadReferral.STATUS_VALID);
        return this.updateById(referral);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean invalidateReferral(Integer referralId, String reason) {
        LeadReferral referral = this.getById(referralId);
        if (referral == null) {
            throw new RuntimeException("推荐记录不存在");
        }

        referral.setReferralStatus(LeadReferral.STATUS_INVALID);
        
        // 同步更新客资推荐费状态
        CustomerLeadEntity lead = customerLeadMapper.selectById(referral.getReferredLeadId());
        if (lead != null) {
            lead.setReferralFeePaid(-1); // 标记为已作废
            customerLeadMapper.updateById(lead);
        }
        
        return this.updateById(referral);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean settleReferral(Integer referralId) {
        LeadReferral referral = this.getById(referralId);
        if (referral == null) {
            throw new RuntimeException("推荐记录不存在");
        }

        if (referral.getReferralStatus() != LeadReferral.STATUS_VALID) {
            throw new RuntimeException("只有有效的推荐才能结算");
        }

        referral.setReferralStatus(LeadReferral.STATUS_SETTLED);
        referral.setSettlementTime(LocalDateTime.now());
        
        // 同步更新客资推荐费状态
        CustomerLeadEntity lead = customerLeadMapper.selectById(referral.getReferredLeadId());
        if (lead != null) {
            lead.setReferralFeePaid(1); // 已支付
            customerLeadMapper.updateById(lead);
        }
        
        return this.updateById(referral);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> batchSettleReferrals(Integer[] referralIds) {
        Map<String, Object> result = new HashMap<>();
        int successCount = 0;
        int failCount = 0;
        List<String> errors = new ArrayList<>();

        for (Integer id : referralIds) {
            try {
                this.settleReferral(id);
                successCount++;
            } catch (Exception e) {
                failCount++;
                errors.add("ID[" + id + "]: " + e.getMessage());
            }
        }

        result.put("successCount", successCount);
        result.put("failCount", failCount);
        result.put("errors", errors);
        
        return result;
    }

    @Override
    public BigDecimal calculateReferralFee(BigDecimal dealAmount) {
        if (dealAmount == null || dealAmount.compareTo(BigDecimal.ZERO) <= 0) {
            return BigDecimal.ZERO;
        }
        return dealAmount.multiply(DEFAULT_REFERRAL_RATE).setScale(2, RoundingMode.HALF_UP);
    }
}
