package com.red.circle.other.app.command.task;

import com.red.circle.other.app.dto.clientobject.task.RoomDailyTaskCO;
import com.red.circle.other.app.dto.clientobject.task.RoomDailyTaskListCO;
import com.red.circle.other.app.dto.clientobject.task.RoomDailyTaskTierCO;
import com.red.circle.other.infra.database.rds.entity.task.RoomDailyTaskConfig;
import com.red.circle.other.infra.database.rds.entity.task.RoomDailyTaskProgress;
import com.red.circle.other.infra.database.rds.entity.task.RoomDailyTaskTier;
import com.red.circle.other.infra.database.rds.service.RoomDailyTaskDatabaseService;
import com.red.circle.tool.core.date.ZonedDateTimeAsiaRiyadhUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 查询用户每日任务列表
 */
@Component
@RequiredArgsConstructor
public class RoomDailyTaskQueryExe {

    private final RoomDailyTaskDatabaseService taskDatabaseService;

    public RoomDailyTaskListCO execute(Long userId, Integer taskCategory) {
        List<RoomDailyTaskConfig> configs = taskDatabaseService.listEnabledConfigs(taskCategory);

        RoomDailyTaskListCO result = new RoomDailyTaskListCO();
        result.setCountdown(calcCountdownSeconds());

        if (CollectionUtils.isEmpty(configs)) {
            result.setTasks(new ArrayList<>());
            return result;
        }

        List<String> taskCodes = configs.stream().map(RoomDailyTaskConfig::getTaskCode).collect(Collectors.toList());
        List<RoomDailyTaskTier> allTiers = taskDatabaseService.listTiersByTaskCodes(taskCodes);

        LocalDate today = ZonedDateTimeAsiaRiyadhUtils.now().toLocalDate();
        List<RoomDailyTaskProgress> progressList = taskDatabaseService.listProgressByUser(userId, today);

        Map<String, List<RoomDailyTaskTier>> tierMap = allTiers.stream()
                .collect(Collectors.groupingBy(RoomDailyTaskTier::getTaskCode));
        Map<String, RoomDailyTaskProgress> progressMap = progressList.stream()
                .collect(Collectors.toMap(RoomDailyTaskProgress::getTaskCode, p -> p, (a, b) -> a));

        List<RoomDailyTaskCO> tasks = configs.stream()
                .map(config -> buildTaskCO(config, tierMap.getOrDefault(config.getTaskCode(), new ArrayList<>()), progressMap.get(config.getTaskCode())))
                .collect(Collectors.toList());

        result.setTasks(tasks);
        return result;
    }

    /** 计算沙特时间今日午夜的时间戳 */
    private Timestamp calcCountdownSeconds() {
        ZonedDateTime now = ZonedDateTimeAsiaRiyadhUtils.now();
        ZonedDateTime midnight = now.toLocalDate().plusDays(1).atStartOfDay(now.getZone());
        return Timestamp.from(midnight.toInstant());
    }

    private RoomDailyTaskCO buildTaskCO(RoomDailyTaskConfig config, List<RoomDailyTaskTier> tiers, RoomDailyTaskProgress progress) {
        int currentValue = progress != null ? progress.getCurrentValue() : 0;
        int maxTierCompleted = progress != null ? progress.getMaxTierCompleted() : 0;
        int maxTierClaimed = progress != null ? progress.getMaxTierClaimed() : 0;

        List<RoomDailyTaskTierCO> tierCOs = tiers.stream().map(tier -> {
            RoomDailyTaskTierCO co = new RoomDailyTaskTierCO();
            co.setTierIndex(tier.getTierIndex());
            co.setTargetValue(tier.getTargetValue());
            co.setTargetUnit(tier.getTargetUnit());
            co.setRewardValue(tier.getRewardValue());
            co.setIsCompleted(tier.getTierIndex() <= maxTierCompleted);
            co.setIsClaimed(tier.getTierIndex() <= maxTierClaimed);
            return co;
        }).collect(Collectors.toList());

        RoomDailyTaskCO co = new RoomDailyTaskCO();
        co.setTaskId(config.getId());
        co.setTaskCode(config.getTaskCode());
        co.setTaskName(config.getTaskName());
        co.setTaskCategory(config.getTaskCategory());
        co.setIconUrl(config.getIconUrl());
        co.setCurrentValue(currentValue);
        co.setTiers(tierCOs);
        return co;
    }
}
