package com.ycwl.basic.service.pc.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2DTO;
import com.ycwl.basic.mapper.ExtraDeviceMapper;
import com.ycwl.basic.model.pc.extraDevice.req.ExtraDevicePageQueryReq;
import com.ycwl.basic.model.pc.extraDevice.resp.ExtraDeviceRespVO;
import com.ycwl.basic.repository.ScenicRepository;
import com.ycwl.basic.service.pc.ExtraDeviceService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * 外部设备服务实现
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ExtraDeviceServiceImpl implements ExtraDeviceService {

    private final ExtraDeviceMapper extraDeviceMapper;
    private final ScenicRepository scenicRepository;
    private final RedisTemplate<String, String> redisTemplate;

    /**
     * Redis Key前缀：ext_device:online:{ident}
     */
    private static final String REDIS_KEY_PREFIX = "ext_device:online:";

    /**
     * 在线判断阈值：5分钟（300秒）
     */
    private static final long ONLINE_THRESHOLD_SECONDS = 300;

    /**
     * 时间格式：yyyy-MM-dd HH:mm:ss
     */
    private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";

    @Override
    public PageInfo<ExtraDeviceRespVO> pageQuery(ExtraDevicePageQueryReq req) {
        // 参数校验与默认值设置
        if (req.getPageNum() == null || req.getPageNum() < 1) {
            req.setPageNum(1);
        }
        if (req.getPageSize() == null || req.getPageSize() < 1) {
            req.setPageSize(20);
        }

        // 使用PageHelper进行分页
        PageHelper.startPage(req.getPageNum(), req.getPageSize());

        // 查询数据库获取设备基础信息
        List<ExtraDeviceRespVO> devices = extraDeviceMapper.pageQuery(req.getScenicId());

        // 遍历设备列表，填充景区名称和在线状态
        for (ExtraDeviceRespVO device : devices) {
            // 1. 填充景区名称
            fillScenicName(device);

            // 2. 填充在线状态和心跳时间
            fillOnlineStatus(device);
        }

        return new PageInfo<>(devices);
    }

    /**
     * 填充景区名称
     * 从景区服务获取景区信息，优先从远程服务获取，失败则降级读取缓存
     */
    private void fillScenicName(ExtraDeviceRespVO device) {
        try {
            if (device.getScenicId() != null) {
                ScenicV2DTO scenic = scenicRepository.getScenicBasic(device.getScenicId());
                if (scenic != null && StringUtils.isNotBlank(scenic.getName())) {
                    device.setScenicName(scenic.getName());
                } else {
                    device.setScenicName("未知景区");
                }
            } else {
                device.setScenicName("未知景区");
            }
        } catch (Exception e) {
            log.warn("获取景区名称失败, scenicId: {}, error: {}", device.getScenicId(), e.getMessage());
            device.setScenicName("未知景区");
        }
    }

    /**
     * 填充在线状态和心跳时间
     * 从Redis获取设备心跳时间戳，判断是否在线（5分钟内有心跳）
     */
    private void fillOnlineStatus(ExtraDeviceRespVO device) {
        try {
            if (StringUtils.isBlank(device.getIdent())) {
                device.setOnline(0);
                device.setKeepaliveAt("");
                return;
            }

            // 从Redis获取心跳时间戳
            String redisKey = REDIS_KEY_PREFIX + device.getIdent();
            String timestampStr = redisTemplate.opsForValue().get(redisKey);

            if (StringUtils.isBlank(timestampStr) || !StringUtils.isNumeric(timestampStr)) {
                // Redis中没有心跳记录或格式不正确
                device.setOnline(0);
                device.setKeepaliveAt("");
                return;
            }

            // 解析时间戳（秒级）
            long keepaliveTimestamp = Long.parseLong(timestampStr);
            long currentTimestamp = System.currentTimeMillis() / 1000;

            // 判断是否在线（5分钟内有心跳）
            boolean isOnline = (currentTimestamp - keepaliveTimestamp) < ONLINE_THRESHOLD_SECONDS;
            device.setOnline(isOnline ? 1 : 0);

            // 格式化心跳时间
            Date keepaliveDate = new Date(keepaliveTimestamp * 1000);
            SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
            device.setKeepaliveAt(sdf.format(keepaliveDate));

        } catch (Exception e) {
            log.warn("获取设备在线状态失败, ident: {}, error: {}", device.getIdent(), e.getMessage());
            device.setOnline(0);
            device.setKeepaliveAt("");
        }
    }
}
