package com.ruoyi.web.modules.industryservice.service;

import java.util.Date;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.SysConfig;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.web.modules.industryservice.domain.vo.IotDataIncrementalSyncResultVo;
import com.ruoyi.web.modules.industryservice.mapper.BizEnvMonitoringRecordMapper;
import com.ruoyi.web.modules.industryservice.mapper.BizYakCollarLocationMapper;
import com.ruoyi.web.modules.industryservice.mapper.BizYakEarTagRecordMapper;
import com.ruoyi.web.modules.industryservice.mapper.BizYakWeighingRecordMapper;
import com.ruoyi.web.modules.industryservice.support.FarmingSyncSupport;
import com.ruoyi.web.modules.industryservice.support.IotSyncSupport;
import com.ruoyi.web.modules.industryservice.support.IotSyncSupport.SyncQuery;

/**
 * IoT 数据同步编排服务。
 * <p>
 * 每日凌晨 1:00 由 {@link com.ruoyi.web.modules.industryservice.task.IotDataIncrementalSyncTask} 触发。
 * </p>
 *
 * <h3>全量 / 增量策略（按表独立判断）</h3>
 * <ul>
 *   <li>{@code countRecords() == 0}：全量分页拉取（不传时间参数与水印）</li>
 *   <li>否则：按最大事件时间增量拉取，并附带 sys_config 水印 {@code updatedAfter}</li>
 * </ul>
 */
@Service
public class IotDataIncrementalSyncService
{
    private static final Logger LOGGER = LoggerFactory.getLogger(IotDataIncrementalSyncService.class);

    private final Object syncLock = new Object();

    @Autowired
    private YakWeighingSyncService yakWeighingSyncService;

    @Autowired
    private YakEarTagSyncService yakEarTagSyncService;

    @Autowired
    private YakCollarLocationSyncService yakCollarLocationSyncService;

    @Autowired
    private EnvMonitoringSyncService envMonitoringSyncService;

    @Autowired
    private BizYakWeighingRecordMapper weighingRecordMapper;

    @Autowired
    private BizYakEarTagRecordMapper earTagRecordMapper;

    @Autowired
    private BizYakCollarLocationMapper collarLocationMapper;

    @Autowired
    private BizEnvMonitoringRecordMapper envMonitoringRecordMapper;

    @Autowired
    private ISysConfigService configService;

    /** 执行 IoT 四类数据同步（空表全量，否则增量） */
    public IotDataIncrementalSyncResultVo syncIncremental()
    {
        synchronized (syncLock)
        {
            Date endTime = new Date();
            Date configUpdatedAfter = IotSyncSupport.parseConfigSyncTime(
                    configService.selectConfigByKey(IotSyncSupport.CONFIG_KEY_LAST_SYNC_TIME));

            SyncQuery weighingQuery = IotSyncSupport.resolveSyncQuery(
                    weighingRecordMapper.countRecords(),
                    weighingRecordMapper.selectMaxWeighingTime(), endTime, configUpdatedAfter);
            SyncQuery earTagQuery = IotSyncSupport.resolveSyncQuery(
                    earTagRecordMapper.countRecords(),
                    earTagRecordMapper.selectMaxReportTime(), endTime, configUpdatedAfter);
            SyncQuery collarQuery = IotSyncSupport.resolveSyncQuery(
                    collarLocationMapper.countRecords(),
                    collarLocationMapper.selectMaxReportTime(), endTime, configUpdatedAfter);
            SyncQuery envQuery = IotSyncSupport.resolveSyncQuery(
                    envMonitoringRecordMapper.countRecords(),
                    envMonitoringRecordMapper.selectMaxMonitoringTime(), endTime, configUpdatedAfter);

            logSyncMode("称重", weighingQuery);
            logSyncMode("耳标温度步数", earTagQuery);
            logSyncMode("定位项圈", collarQuery);
            logSyncMode("环境监测", envQuery);

            IotDataIncrementalSyncResultVo result = new IotDataIncrementalSyncResultVo();
            result.setSyncTime(endTime);
            result.setWindowEnd(endTime);
            result.setWindowStart(earliest(
                    weighingQuery.isFullSync() ? null : weighingQuery.getStartTime(),
                    earTagQuery.isFullSync() ? null : earTagQuery.getStartTime(),
                    collarQuery.isFullSync() ? null : collarQuery.getStartTime(),
                    envQuery.isFullSync() ? null : envQuery.getStartTime()));
            try
            {
                result.setWeighing(yakWeighingSyncService.syncIncremental(weighingQuery));
                result.setEarTag(yakEarTagSyncService.syncIncremental(earTagQuery));
                result.setCollarLocation(yakCollarLocationSyncService.syncIncremental(collarQuery));
                result.setEnvMonitoring(envMonitoringSyncService.syncIncremental(envQuery));
            }
            catch (ServiceException e)
            {
                throw e;
            }
            catch (Exception e)
            {
                throw new ServiceException("IoT 数据同步失败：" + e.getMessage());
            }
            persistLastSyncTime(endTime);
            return result;
        }
    }

    private static void logSyncMode(String label, SyncQuery query)
    {
        if (query.isFullSync())
        {
            LOGGER.info("IoT 同步 [{}] 模式=全量（本地表无数据）", label);
            return;
        }
        LOGGER.info("IoT 同步 [{}] 模式=增量, start={}, end={}, updatedAfter={}",
                label,
                IotSyncSupport.formatParamTime(query.getStartTime()),
                IotSyncSupport.formatParamTime(query.getEndTime()),
                IotSyncSupport.formatParamTime(query.getUpdatedAfter()));
    }

    private static Date earliest(Date... times)
    {
        Date min = null;
        for (Date time : times)
        {
            if (time == null)
            {
                continue;
            }
            if (min == null || time.before(min))
            {
                min = time;
            }
        }
        return min;
    }

    private void persistLastSyncTime(Date syncTime)
    {
        String value = IotSyncSupport.formatParamTime(syncTime);
        if (StringUtils.isEmpty(value))
        {
            return;
        }
        SysConfig query = new SysConfig();
        query.setConfigKey(IotSyncSupport.CONFIG_KEY_LAST_SYNC_TIME);
        List<SysConfig> configs = configService.selectConfigList(query);
        if (configs != null && !configs.isEmpty())
        {
            SysConfig existing = configs.get(0);
            existing.setConfigValue(value);
            existing.setUpdateBy(FarmingSyncSupport.SYNC_BY);
            configService.updateConfig(existing);
            return;
        }
        SysConfig row = new SysConfig();
        row.setConfigName("第三方 IoT 上次增量同步时间");
        row.setConfigKey(IotSyncSupport.CONFIG_KEY_LAST_SYNC_TIME);
        row.setConfigValue(value);
        row.setConfigType("Y");
        row.setCreateBy(FarmingSyncSupport.SYNC_BY);
        configService.insertConfig(row);
    }
}
