package com.erp.customer.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.erp.customer.dto.CustomerStatisticsDTO;
import com.erp.customer.entity.Customer;
import com.erp.customer.entity.CustomerFollowUp;
import com.erp.customer.repository.CustomerFollowUpRepository;
import com.erp.customer.repository.CustomerRepository;
import com.erp.customer.service.CustomerStatisticsService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 客户统计Service实现
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CustomerStatisticsServiceImpl implements CustomerStatisticsService {
    
    private final CustomerRepository customerRepository;
    private final CustomerFollowUpRepository followUpRepository;
    
    @Override
    public CustomerStatisticsDTO getCustomerStatistics(Long tenantId) {
        CustomerStatisticsDTO stats = new CustomerStatisticsDTO();
        
        // 客户总数
        Long total = customerRepository.countByTenantId(tenantId);
        stats.setTotalCustomers(total);
        
        // 各等级客户数
        Long vipCount = countByLevel(tenantId, "VIP");
        Long normalCount = countByLevel(tenantId, "NORMAL");
        Long potentialCount = countByLevel(tenantId, "POTENTIAL");
        stats.setVipCustomers(vipCount);
        stats.setNormalCustomers(normalCount);
        stats.setPotentialCustomers(potentialCount);
        
        // 各状态客户数
        Long activeCount = countByStatus(tenantId, "ACTIVE");
        Long inactiveCount = countByStatus(tenantId, "INACTIVE");
        Long blacklistedCount = countByStatus(tenantId, "BLACKLISTED");
        stats.setActiveCustomers(activeCount);
        stats.setInactiveCustomers(inactiveCount);
        stats.setBlacklistedCustomers(blacklistedCount);
        
        // 客户总余额
        BigDecimal totalBalance = customerRepository.sumBalanceByTenantId(tenantId);
        stats.setTotalBalance(totalBalance != null ? totalBalance : BigDecimal.ZERO);
        
        // 平均余额
        if (total != null && total > 0) {
            BigDecimal avgBalance = totalBalance.divide(BigDecimal.valueOf(total), 2, RoundingMode.HALF_UP);
            stats.setAverageBalance(avgBalance);
        } else {
            stats.setAverageBalance(BigDecimal.ZERO);
        }
        
        // 本月新增客户数
        LocalDateTime monthStart = LocalDateTime.now().withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0);
        stats.setNewCustomersThisMonth(countNewCustomersThisMonth(tenantId, monthStart));
        
        // 超时未联系客户数
        LocalDateTime overdueThreshold = LocalDateTime.now().minusDays(7);
        stats.setOverdueFollowUpCount(countOverdueFollowUps(tenantId, overdueThreshold));
        
        // 今日待跟进客户数
        stats.setTodayFollowUpCount(countTodayFollowUps(tenantId));
        
        // 分布统计
        stats.setLevelDistribution(computeLevelDistribution(tenantId));
        stats.setStatusDistribution(computeStatusDistribution(tenantId));
        stats.setSalesDistribution(computeSalesDistribution(tenantId));
        
        return stats;
    }
    
    @Override
    public CustomerStatisticsDTO getLevelDistribution(Long tenantId) {
        CustomerStatisticsDTO stats = new CustomerStatisticsDTO();
        stats.setLevelDistribution(computeLevelDistribution(tenantId));
        return stats;
    }
    
    @Override
    public CustomerStatisticsDTO getStatusDistribution(Long tenantId) {
        CustomerStatisticsDTO stats = new CustomerStatisticsDTO();
        stats.setStatusDistribution(computeStatusDistribution(tenantId));
        return stats;
    }
    
    @Override
    public CustomerStatisticsDTO getSalesDistribution(Long tenantId) {
        CustomerStatisticsDTO stats = new CustomerStatisticsDTO();
        stats.setSalesDistribution(computeSalesDistribution(tenantId));
        return stats;
    }
    
    @Override
    public CustomerStatisticsDTO getGrowthTrend(Long tenantId) {
        CustomerStatisticsDTO stats = new CustomerStatisticsDTO();
        stats.setGrowthTrend(computeGrowthTrend(tenantId));
        return stats;
    }
    
    @Override
    public CustomerStatisticsDTO getOverdueFollowUpStatistics(Long tenantId, Integer overdueDays) {
        CustomerStatisticsDTO stats = new CustomerStatisticsDTO();
        LocalDateTime overdueThreshold = LocalDateTime.now().minusDays(overdueDays != null ? overdueDays : 7);
        stats.setOverdueFollowUpCount(countOverdueFollowUps(tenantId, overdueThreshold));
        
        // 获取超时未联系的客户列表
        List<Customer> overdueCustomers = customerRepository.findLongTimeNoContact(tenantId, overdueThreshold);
        stats.setOverdueFollowUpCount((long) overdueCustomers.size());
        
        return stats;
    }
    
    @Override
    public CustomerStatisticsDTO getTodayFollowUpStatistics(Long tenantId) {
        CustomerStatisticsDTO stats = new CustomerStatisticsDTO();
        stats.setTodayFollowUpCount(countTodayFollowUps(tenantId));
        return stats;
    }
    
    // ==================== 私有方法 ====================
    
    private Long countByLevel(Long tenantId, String level) {
        LambdaQueryWrapper<Customer> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Customer::getTenantId, tenantId)
                   .eq(Customer::getLevel, level)
                   .isNull(Customer::getDeletedAt);
        return customerRepository.selectCount(queryWrapper);
    }
    
    private Long countByStatus(Long tenantId, String status) {
        LambdaQueryWrapper<Customer> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Customer::getTenantId, tenantId)
                   .eq(Customer::getStatus, status)
                   .isNull(Customer::getDeletedAt);
        return customerRepository.selectCount(queryWrapper);
    }
    
    private Long countNewCustomersThisMonth(Long tenantId, LocalDateTime monthStart) {
        LambdaQueryWrapper<Customer> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Customer::getTenantId, tenantId)
                   .ge(Customer::getCreatedAt, monthStart)
                   .isNull(Customer::getDeletedAt);
        return customerRepository.selectCount(queryWrapper);
    }
    
    private Long countOverdueFollowUps(Long tenantId, LocalDateTime threshold) {
        LambdaQueryWrapper<Customer> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Customer::getTenantId, tenantId)
                   .isNull(Customer::getLastContactAt)
                   .isNull(Customer::getDeletedAt);
        
        List<Customer> noContact = customerRepository.selectList(queryWrapper);
        return (long) noContact.size();
    }
    
    private Long countTodayFollowUps(Long tenantId) {
        LocalDateTime today = LocalDateTime.now();
        List<CustomerFollowUp> todayFollowUps = followUpRepository.findTodayFollowUps(tenantId, today);
        return (long) todayFollowUps.size();
    }
    
    private List<Map<String, Object>> computeLevelDistribution(Long tenantId) {
        List<Object[]> results = customerRepository.countByTenantIdGroupByLevel(tenantId);
        return results.stream().map(row -> {
            Map<String, Object> item = new HashMap<>();
            item.put("level", row[0]);
            item.put("count", row[1]);
            return item;
        }).collect(Collectors.toList());
    }
    
    private List<Map<String, Object>> computeStatusDistribution(Long tenantId) {
        List<Object[]> results = customerRepository.countByTenantIdGroupByStatus(tenantId);
        return results.stream().map(row -> {
            Map<String, Object> item = new HashMap<>();
            item.put("status", row[0]);
            item.put("count", row[1]);
            return item;
        }).collect(Collectors.toList());
    }
    
    private List<Map<String, Object>> computeSalesDistribution(Long tenantId) {
        List<Object[]> results = customerRepository.countByTenantIdGroupBySales(tenantId);
        return results.stream().map(row -> {
            Map<String, Object> item = new HashMap<>();
            item.put("salesId", row[0]);
            item.put("salesName", row[1]);
            item.put("count", row[2]);
            return item;
        }).collect(Collectors.toList());
    }
    
    private List<Map<String, Object>> computeGrowthTrend(Long tenantId) {
        List<Map<String, Object>> trend = new ArrayList<>();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM");
        
        for (int i = 5; i >= 0; i--) {
            LocalDateTime monthStart = LocalDateTime.now().minusMonths(i).withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0);
            LocalDateTime monthEnd = monthStart.plusMonths(1);
            
            LambdaQueryWrapper<Customer> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Customer::getTenantId, tenantId)
                       .ge(Customer::getCreatedAt, monthStart)
                       .lt(Customer::getCreatedAt, monthEnd)
                       .isNull(Customer::getDeletedAt);
            
            Long count = customerRepository.selectCount(queryWrapper);
            
            Map<String, Object> item = new HashMap<>();
            item.put("month", monthStart.format(formatter));
            item.put("count", count);
            trend.add(item);
        }
        
        return trend;
    }
}
