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


import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pig4cloud.pig.marketing.api.dto.MktMgmtPushRecordSaveDTO;
import com.pig4cloud.pig.marketing.api.dto.mongo.PageDeviceInfoDTO;
import com.pig4cloud.pig.marketing.api.dto.mongo.PageMessageDTO;
import com.pig4cloud.pig.marketing.api.dto.mongo.SaveDeviceInfoDTO;
import com.pig4cloud.pig.marketing.api.dto.mongo.SaveTcpMessageDTO;
import com.pig4cloud.pig.marketing.api.entity.mongo.Device;
import com.pig4cloud.pig.marketing.api.entity.mongo.Message;
import com.pig4cloud.pig.marketing.api.vo.mongo.PageDeviceInfoVO;
import com.pig4cloud.pig.marketing.api.vo.mongo.UserStatisticsVO;
import com.pig4cloud.pig.marketing.config.UserStatisticsConfig;
import com.pig4cloud.pig.marketing.repository.MessageRepository;
import com.pig4cloud.pig.marketing.service.MktMgmtPushRecordService;
import com.pig4cloud.pig.marketing.service.TcpDataService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @author: lwh
 * @date: 2025-08-28
 * @description: TCP数据服务实现类
 */

	@Slf4j
	@Service
	@AllArgsConstructor
	public class TcpDataServiceImpl implements TcpDataService {

		private final MongoTemplate mongoTemplate;

		private final MessageRepository messageRepository;

		private final UserStatisticsConfig userStatisticsConfig;

		@Autowired
		private MktMgmtPushRecordService mktMgmtPushRecordService;

	// 定义时间格式器
	private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

	/**
	 * 保存或更新设备信息
	 * @param reqDto
	 * @return
	 */
	@Override
	public String saveOrUpdateDevice(SaveDeviceInfoDTO reqDto) {
		// 根据客户端ID查询设备信息
		Query query = new Query(Criteria.where("clientID").is(reqDto.getClientID()));
		Device existingDevice = mongoTemplate.findOne(query, Device.class);

		if (existingDevice == null) {
			// 无数据时直接新增
			Device device = new Device();
			device.setClientID(reqDto.getClientID());
			device.setDeviceInfo(reqDto.getDeviceInfo());
			device.setHeadInfo(reqDto.getHeadInfo());
			// 设置创建时间和更新时间为当前时间的字符串格式
			String currentTime = LocalDateTime.now().format(DATE_TIME_FORMATTER);
			device.setCreateTime(currentTime);
			device.setUpdateTime(currentTime);
			Device insert = mongoTemplate.insert(device);
			return insert.getId();
		} else {
			// 有数据时对比设备信息是否一致
			if (!Objects.equals(existingDevice.getDeviceInfo(), reqDto.getDeviceInfo())
					|| !Objects.equals(existingDevice.getHeadInfo(), reqDto.getHeadInfo())) {
				// 信息不一致则更新
				Update update = new Update();
				if (!StringUtils.isBlank(reqDto.getDeviceInfo())) {
					update.set("deviceInfo", reqDto.getDeviceInfo());
				}
				if (!StringUtils.isBlank(reqDto.getHeadInfo())) {
					update.set("headInfo", reqDto.getHeadInfo());
				}
				// 设置更新时间为当前时间的字符串格式
				update.set("updateTime", LocalDateTime.now().format(DATE_TIME_FORMATTER));

				mongoTemplate.updateFirst(query, update, Device.class);
				return existingDevice.getId();
			}
		}
		return existingDevice.getId();
	}

	/**
	 * 根据客户端ID查询设备信息
	 * @param clientID 客户端ID
	 * @return 设备信息
	 */
	@Override
	public Device getDeviceByClientID(String clientID) {
		return mongoTemplate.findOne(
				new Query(Criteria.where("clientID").is(clientID)),
				Device.class
		);
	}

	/**
	 * 分页查询设备信息
	 * @param reqDto 入参
	 * @return 设备信息列表
	 */
	@Override
	public Page<PageDeviceInfoVO> pageDeviceInfo(PageDeviceInfoDTO reqDto) {
		// 创建查询条件
		Criteria criteria = new Criteria();

		// 添加clientID条件
		if (reqDto.getClientID() != null && !reqDto.getClientID().trim().isEmpty()) {
			criteria.and("clientID").regex(reqDto.getClientID());
		}

		// 添加时间范围条件
		LocalDateTime startTime = reqDto.getStartTime();
		LocalDateTime endTime = reqDto.getEndTime();

		// 创建时间字段的条件对象
		Criteria timeCriteria = new Criteria("createTime");

		if (startTime != null) {
			String startStr = startTime.format(DATE_TIME_FORMATTER);
			timeCriteria.gte(startStr);
		}

		if (endTime != null) {
			String endStr = endTime.format(DATE_TIME_FORMATTER);
			timeCriteria.lte(endStr);
		}

		// 只有当存在时间条件时，才将时间条件添加到主条件中
		if (startTime != null || endTime != null) {
			criteria.andOperator(timeCriteria);
		}

		// 创建查询对象
		Query query = new Query(criteria);

		// 计算总记录数
		long total = mongoTemplate.count(query, Device.class);

		// 设置分页和排序
		Pageable pageable = PageRequest.of(
				reqDto.getCurrent() - 1,  // MongoDB页码从0开始
				reqDto.getSize(),
				Sort.by(Sort.Direction.DESC, "createTime")
		);
		query.with(pageable);

		// 执行查询
		List<Device> devices = mongoTemplate.find(query, Device.class);

		List<PageDeviceInfoVO> result = new ArrayList<>();
		// 组装数据
		for (Device device : devices) {
			PageDeviceInfoVO info = new PageDeviceInfoVO();
			BeanUtils.copyProperties(device, info);

			// 查询总条数
			Long dataTotal = getMsgDataTotal(device.getClientID());
			info.setTotal(dataTotal);
			result.add(info);
		}

		// 封装分页结果
		Page<PageDeviceInfoVO> page = new Page<>(reqDto.getCurrent(), reqDto.getSize(), total);
		page.setRecords(result);
		return page;
	}

	/******************************************* 消息 *******************************************
	 * 保存上报数据
	 * @param reqDto 入参
	 * @return 数据ID
	 */
	@Override
	public String saveMessage(SaveTcpMessageDTO reqDto) {
		Message message = new Message();
		message.setClientID(reqDto.getClientID());
		message.setMsgData(reqDto.getMsgData());
		message.setReportTime(LocalDateTime.now().format(DATE_TIME_FORMATTER));
		Message save = messageRepository.save(message);
		if (save.getId() != null) {
			MktMgmtPushRecordSaveDTO saveRecordDTO = new MktMgmtPushRecordSaveDTO();
			saveRecordDTO.setPushContent(reqDto.getMsgData());
			saveRecordDTO.setPushIP(reqDto.getClientIP());
			saveRecordDTO.setPushDomain(reqDto.getClientDomain());
			String s = mktMgmtPushRecordService.saveRecord(saveRecordDTO);
			log.info("保存推送记录：{}", s);
		}
		return save.getId();
	}

	/**
	 * 根据ID查询数据详情
	 * @param id 数据ID
	 * @return 数据详情
	 */
	@Override
	public Message getMessagesById(String id) {
		return messageRepository.findById(id)
				.orElse(null);
	}

	/**
	 * 分页查询数据列表
	 * @param reqDto 入参
	 * @return 数据列表
	 */
	@Override
	public Page<Message> pageMsgInfo(PageMessageDTO reqDto) {
		// 创建查询条件
		Criteria criteria = new Criteria();

		// 添加clientID条件
		criteria.and("clientID").is(reqDto.getClientID());

		if (reqDto.getKeyWord() != null && !reqDto.getKeyWord().isEmpty()){
			criteria.and("msgData").regex(reqDto.getKeyWord());
		}

		// 添加时间范围条件
		LocalDateTime startTime = reqDto.getStartTime();
		LocalDateTime endTime = reqDto.getEndTime();

		// 创建时间字段的条件对象
		Criteria timeCriteria = new Criteria("reportTime");

		if (startTime != null) {
			String startStr = startTime.format(DATE_TIME_FORMATTER);
			timeCriteria.gte(startStr);
		}

		if (endTime != null) {
			String endStr = endTime.format(DATE_TIME_FORMATTER);
			timeCriteria.lte(endStr);
		}

		// 只有当存在时间条件时，才将时间条件添加到主条件中
		if (startTime != null || endTime != null) {
			criteria.andOperator(timeCriteria);
		}

		// 创建查询对象
		Query query = new Query(criteria);

		// 计算总记录数
		long total = mongoTemplate.count(query, Message.class);

		// 设置分页和排序
		Pageable pageable = PageRequest.of(
				reqDto.getCurrent() - 1,  // MongoDB页码从0开始
				reqDto.getSize(),
				Sort.by(Sort.Direction.DESC, "reportTime")
		);
		query.with(pageable);

		// 执行查询
		List<Message> messages = mongoTemplate.find(query, Message.class);

		// 封装分页结果
		Page<Message> page = new Page<>(reqDto.getCurrent(), reqDto.getSize(), total);
		page.setRecords(messages);
		return page;
	}


	private Long getMsgDataTotal(String clientId){
		// 创建查询条件
		Criteria criteria = new Criteria();

		// 添加clientID条件
		criteria.and("clientID").is(clientId);

		// 创建查询对象
		Query query = new Query(criteria);

		// 计算总记录数
		return mongoTemplate.count(query, Message.class);

	}

	/**
	 * 统计用户数
	 * @return 用户统计信息
	 */
	@Override
	public UserStatisticsVO getUserStatistics() {
		log.info("开始统计用户数");
		
		try {
			// 1. 统计累计用户数
			Long totalUsers = getTotalUsers();
			
			// 2. 统计活跃用户数
			Long activeUsers = getActiveUsers();
			
			// 3. 构建返回结果
			UserStatisticsVO statisticsVO = new UserStatisticsVO();
			statisticsVO.setTotalUsers(totalUsers);
			statisticsVO.setActiveUsers(activeUsers);
			statisticsVO.setStatisticsTime(LocalDateTime.now().format(DATE_TIME_FORMATTER));
			statisticsVO.setActiveTimeRange(userStatisticsConfig.getActiveTimeRangeMinutes());
			
			log.info("用户统计完成，累计用户数：{}，活跃用户数：{}", totalUsers, activeUsers);
			return statisticsVO;
			
		} catch (Exception e) {
			log.error("统计用户数异常", e);
			// 返回默认值
			UserStatisticsVO statisticsVO = new UserStatisticsVO();
			statisticsVO.setTotalUsers(0L);
			statisticsVO.setActiveUsers(0L);
			statisticsVO.setStatisticsTime(LocalDateTime.now().format(DATE_TIME_FORMATTER));
			statisticsVO.setActiveTimeRange(userStatisticsConfig.getActiveTimeRangeMinutes());
			return statisticsVO;
		}
	}
	
	/**
	 * 获取累计用户数
	 * @return 累计用户数
	 */
	private Long getTotalUsers() {
		// 使用MongoDB的distinct操作获取去重的clientID数量
		List<String> distinctClientIDs = mongoTemplate.findDistinct(
			new Query(), 
			"clientID", 
			Device.class, 
			String.class
		);
		
		// 过滤掉null和空字符串
		long count = distinctClientIDs.stream()
			.filter(clientID -> clientID != null && !clientID.trim().isEmpty())
			.count();
			
		log.debug("累计用户数统计完成，去重后的clientID数量：{}", count);
		return count;
	}
	
	/**
	 * 获取活跃用户数
	 * @return 活跃用户数
	 */
	private Long getActiveUsers() {
		// 计算活跃时间范围
		LocalDateTime activeStartTime = LocalDateTime.now().minusMinutes(userStatisticsConfig.getActiveTimeRangeMinutes());
		String activeStartTimeStr = activeStartTime.format(DATE_TIME_FORMATTER);
		
		// 创建查询条件：时间在活跃时间范围内
		Criteria criteria = Criteria.where("reportTime").gte(activeStartTimeStr);
		Query query = new Query(criteria);
		
		// 使用distinct操作获取去重的clientID数量
		List<String> distinctClientIDs = mongoTemplate.findDistinct(
			query, 
			"clientID", 
			Message.class, 
			String.class
		);
		
		// 过滤掉null和空字符串
		long count = distinctClientIDs.stream()
			.filter(clientID -> clientID != null && !clientID.trim().isEmpty())
			.count();
			
		log.debug("活跃用户数统计完成，时间范围：{} 至现在，去重后的clientID数量：{}", activeStartTimeStr, count);
		return count;
	}
}
