package com.fs.live.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.fs.common.core.domain.R;
import com.fs.common.core.redis.RedisCache;
import com.fs.live.domain.Live;
import com.fs.live.domain.LiveAutoTask;
import com.fs.live.mapper.LiveAutoTaskMapper;
import com.fs.live.mapper.LiveMapper;
import com.fs.live.param.LiveWatchProgressParam;
import com.fs.live.service.ILivePersonalizedPushService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 直播个性化推送Service实现
 *
 * @author 夏伟
 * @date 2025-01-19
 */
@Slf4j
@Service
public class LivePersonalizedPushServiceImpl implements ILivePersonalizedPushService {

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private LiveAutoTaskMapper liveAutoTaskMapper;

    @Autowired
    private LiveMapper liveMapper;

    private static final String PROGRESS_KEY_PREFIX = "live:user:progress:";
    private static final String PUSHED_TASKS_KEY_PREFIX = "live:user:pushed:";

    /**
     * 上报观看进度并获取需要展示的任务
     */
    @Override
    public R reportProgressAndGetTasks(LiveWatchProgressParam param) {
        try {
            if (param.getLiveId() == null || param.getUserId() == null ||
                param.getCurrentProgress() == null || param.getReplayFlag() == null) {
                return R.error("参数不完整");
            }

            if (param.getReplayFlag() == 0) {
                return R.ok();
            }

            Live live = liveMapper.selectLiveByLiveId(param.getLiveId());
            if (live == null) {
                return R.error("直播间不存在");
            }

            if (!(live.getLiveType() == 2 || (live.getLiveType() == 3 && live.getStatus() == 4))) {
                return R.ok();
            }

            // 上次的观看时长
            String progressKey = buildProgressKey(param.getLiveId(), param.getUserId(), param.getReplayFlag());
            Long lastProgress = redisCache.getCacheObject(progressKey);

            if (lastProgress != null && param.getCurrentProgress() < lastProgress) {
                return R.ok();
            }

            redisCache.setCacheObject(progressKey, param.getCurrentProgress(), 2, TimeUnit.HOURS);

            LiveAutoTask queryTask = new LiveAutoTask();
            queryTask.setLiveId(param.getLiveId());
            queryTask.setStatus(1L);
            List<LiveAutoTask> allTasks = liveAutoTaskMapper.selectLiveAutoTaskList(queryTask);

            if (allTasks == null || allTasks.isEmpty()) {
                return R.ok();
            }

            List<JSONObject> tasksToShow = new ArrayList<>();
            Long currentProgress = param.getCurrentProgress();
            String pushedKey = buildPushedKey(param.getLiveId(), param.getUserId(), param.getReplayFlag());

            for (LiveAutoTask task : allTasks) {
                Long taskTriggerSeconds = calculateTaskTriggerSeconds(task);
                if (taskTriggerSeconds == null) {
                    continue;
                }

                if ((lastProgress == null || lastProgress < taskTriggerSeconds) &&
                    currentProgress >= taskTriggerSeconds) {

                    String taskKey = task.getId().toString();
                    if (redisCache.hashGet(pushedKey, taskKey) == null) {

                        redisCache.hashPut(pushedKey, taskKey, "1");

                        JSONObject taskData = new JSONObject();
                        taskData.put("taskId", task.getId());
                        taskData.put("taskType", task.getTaskType());
                        taskData.put("taskName", task.getTaskName());
                        taskData.put("content", task.getContent());
                        taskData.put("triggerProgress", taskTriggerSeconds);

                        tasksToShow.add(taskData);
                    }
                }
            }

            if (!tasksToShow.isEmpty()) {
                redisCache.expire(pushedKey, 2, TimeUnit.HOURS);
            }

            return R.ok().put("tasks", tasksToShow);

        } catch (Exception e) {
            log.error("上报观看进度失败，liveId: {}, userId: {}",
                param.getLiveId(), param.getUserId(), e);
            return R.error("系统异常");
        }
    }

    /**
     * 计算任务的触发进度(秒)
     */
    private Long calculateTaskTriggerSeconds(LiveAutoTask task) {
        try {
            if (task.getTriggerValue() == null) {
                return null;
            }

            Date triggerValue = task.getTriggerValue();

            LocalTime triggerTime = triggerValue.toInstant()
                .atZone(ZoneId.systemDefault())
                .toLocalTime();

            return (long) triggerTime.toSecondOfDay();
        } catch (Exception e) {
            log.error("计算任务触发时间失败，taskId: {}", task.getId(), e);
            return null;
        }
    }

    /**
     * 构建进度缓存Key
     */
    private String buildProgressKey(Long liveId, Long userId, Integer replayFlag) {
        return String.format("%s%d:%d:%d", PROGRESS_KEY_PREFIX, liveId, userId, replayFlag);
    }

    /**
     * 构建已推送任务缓存Key
     */
    private String buildPushedKey(Long liveId, Long userId, Integer replayFlag) {
        return String.format("%s%d:%d:%d", PUSHED_TASKS_KEY_PREFIX, liveId, userId, replayFlag);
    }
}
