package com.pig4cloud.pig.statistics.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pig4cloud.pig.common.core.exception.BusinessException;
import com.pig4cloud.pig.statistics.api.dto.retention.GetFreshnessTrendDTO;
import com.pig4cloud.pig.statistics.api.dto.retention.GetRetentionTrendDTO;
import com.pig4cloud.pig.statistics.api.dto.retention.PageQueryRetentionDTO;
import com.pig4cloud.pig.statistics.api.entity.user.MktStatActiveUser;
import com.pig4cloud.pig.statistics.api.entity.user.MktStatNewUser;
import com.pig4cloud.pig.statistics.api.vo.retention.GetFreshnessTrendVO;
import com.pig4cloud.pig.statistics.api.vo.retention.GetRetentionTrendVO;
import com.pig4cloud.pig.statistics.api.vo.retention.PageQueryRetentionVO;
import com.pig4cloud.pig.statistics.mapper.MktStatActiveUserMapper;
import com.pig4cloud.pig.statistics.mapper.MktStatNewUserMapper;
import com.pig4cloud.pig.statistics.service.RetentionAnalyseService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.List;

import static com.pig4cloud.pig.common.core.util.stat.TimeUtil.*;

/**
 * @author: lwh
 * @date: 2025-08-22
 * @description:
 */
@Slf4j
@Service
@AllArgsConstructor
public class RetentionAnalyseServiceImpl implements RetentionAnalyseService {

	private final MktStatNewUserMapper newUserMapper;

	private final MktStatActiveUserMapper activeUserMapper;

	/**
	 * 分页查询留存用户详情
	 * @param reqDto 分页参数
	 * @return Page<PageQueryRetentionVO>
	 */
	@Override
	public Page<PageQueryRetentionVO> pageRetentionDetail(PageQueryRetentionDTO reqDto) {
		if ("day".equals(reqDto.getTimeUnit())){
			reqDto.setToDate(reqDto.getToDate().minusDays(1));
		}else if ("week".equals(reqDto.getTimeUnit())){
			reqDto.setToDate(reqDto.getToDate().minusWeeks(1));
		}else if ("month".equals(reqDto.getTimeUnit())){
			reqDto.setToDate(reqDto.getToDate().minusMonths(1));
		}

		Page<PageQueryRetentionVO> page = new Page<>(reqDto.getCurrent(), reqDto.getSize());
		// 生成时间坐标轴
		List<String> dates = generatePageTimeAxis(reqDto.getFromDate(), reqDto.getToDate(), reqDto.getTimeUnit(), reqDto.getCurrent(), reqDto.getSize());
		// 设置总条数
		page.setTotal(calculateTotalCount(reqDto.getFromDate(), reqDto.getToDate(), reqDto.getTimeUnit()));

		// 获取渠道和版本
		List<String> channel = reqDto.getChannel();
		String version = null;
		if (reqDto.getVersion() != null && !reqDto.getVersion().isEmpty()){
			version = reqDto.getVersion().get(0);
		}

		for (String date : dates) {
			LocalDateTime startTime = getStartTime(date, reqDto.getTimeUnit());
			LocalDateTime endTime = getEndTime(date, reqDto.getTimeUnit());
			List<String> userList;
			PageQueryRetentionVO result = new PageQueryRetentionVO();
			result.setDate(date);
			if ("newUser".equals(reqDto.getType())) {
				// 查询新增用户数量
				userList = getNewUserIdList(startTime, endTime, reqDto.getAppId(), version, channel);
				result.setNewUser(userList.size());
			}
			else if ("activeUser".equals(reqDto.getType())) {
				// 查询活跃用户数量
				userList = getActiveUserIdList(startTime, endTime, reqDto.getAppId(), version, channel);
				result.setActiveUser(userList.size());
			}

			// 计算留存率
			// 计算一天后的留存率
			// 计算2天后的留存率
			// 计算3天后的留存率
			// 计算4天后的留存率
			// 计算5天后的留存率
			// 计算6天后的留存率
			// 计算7天后的留存率
			// 计算14天后的留存率
			// 计算30天后的留存率
		}

		return null;
	}

	/**
	 * 获取留存趋势
	 * @param reqDto 获取留存趋势参数
	 * @return GetRetentionTrendVO
	 */
	@Override
	public GetRetentionTrendVO getRetentionTrend(GetRetentionTrendDTO reqDto) {
		return null;
	}

	/**
	 * 获取用户新鲜度趋势
	 * @param reqDto 获取用户新鲜度趋势参数
	 * @return GetFreshnessTrendVO
	 */
	@Override
	public GetFreshnessTrendVO getFreshnessTrend(GetFreshnessTrendDTO reqDto) {
		return null;
	}

	/**
	 * 获取用户活跃度趋势
	 * @param reqDto 获取用户活跃度趋势参数
	 * @return GetFreshnessTrendVO
	 */
	@Override
	public GetFreshnessTrendVO getEngagementTrend(GetFreshnessTrendDTO reqDto) {
		return null;
	}


	/************************************** 公用方法 **************************************
	 * 统计指定时间范围内的新增用户数
	 */
	private Long statNewUserCount(LocalDateTime startTime, LocalDateTime endTime, String appId, String version, List<String> channels){
		List<String> newUsers = getNewUserIdList(startTime, endTime, appId, version, channels);
		return newUsers == null ? 0L : newUsers.size();
	}

	/**
	 * 统计指定时间范围内的活跃用户数
	 */
	private Long statActiveUserCount(LocalDateTime startTime, LocalDateTime endTime, String appId, String version, List<String> channels){
		List<String> activeUsers = getActiveUserIdList(startTime, endTime, appId, version, channels);
		return activeUsers == null ? 0L : activeUsers.size();
	}

	/**
	 * 查询指定时间范围内的活跃用户Id列表(去重)
	 */
	private List<String> getActiveUserIdList(LocalDateTime startTime, LocalDateTime endTime, String appId, String version, List<String> channels){
		// 1. 组装查询条件
		LambdaQueryWrapper<MktStatActiveUser> queryWrapper = Wrappers.<MktStatActiveUser>lambdaQuery()
				.eq(MktStatActiveUser::getAppId, appId)
				.ge(startTime != null, MktStatActiveUser::getStatDate, startTime)
				.lt(endTime != null, MktStatActiveUser::getStatDate, endTime)
				.select(MktStatActiveUser::getUserId)
				.groupBy(MktStatActiveUser::getUserId);

		// 2. 添加渠道条件
		if (channels != null && !channels.isEmpty()) {
			queryWrapper.in(MktStatActiveUser::getChannel, channels);
		}
		// 3. 添加版本条件
		if (version != null && !version.isEmpty()){
			queryWrapper.eq(MktStatActiveUser::getVersion, version);
		}
		// 4. 统计活跃用户数，根据userID去重
		List<MktStatActiveUser> activeUsers = activeUserMapper.selectList(queryWrapper);
		return activeUsers.stream().map(MktStatActiveUser::getUserId).toList();
	}

	/**
	 * 查询指定时间范围内的新增用户Id列表（去重）
	 */
	private List<String> getNewUserIdList(LocalDateTime startTime, LocalDateTime endTime, String appId, String version, List<String> channels){

		// 1. 组装查询条件
		LambdaQueryWrapper<MktStatNewUser> queryWrapper = Wrappers.<MktStatNewUser>lambdaQuery()
				.eq(MktStatNewUser::getAppId, appId)
				.ge(startTime != null ,MktStatNewUser::getStatDate, startTime)
				.lt(endTime != null ,MktStatNewUser::getStatDate, endTime)
				.select(MktStatNewUser::getUserId)
				.groupBy(MktStatNewUser::getUserId);

		// 2. 添加渠道条件
		if (channels != null && !channels.isEmpty()) {
			queryWrapper.in(MktStatNewUser::getChannel, channels);
		}
		// 3. 添加版本条件
		if (version != null && !version.isEmpty()){
			queryWrapper.eq(MktStatNewUser::getVersion, version);
		}
		// 4. 统计新增用户数
		List<MktStatNewUser> newUsers = newUserMapper.selectList(queryWrapper);
		return newUsers.stream().map(MktStatNewUser::getUserId).toList();
	}

}
