package com.red.circle.other.app.command.activity.query;

import com.red.circle.other.app.dto.clientobject.activity.HistoricalTop1ListCO;
import com.red.circle.other.app.dto.clientobject.activity.HistoricalWeekTop1CO;
import com.red.circle.other.app.dto.clientobject.activity.RankingActivityRecordCO;
import com.red.circle.other.app.dto.cmd.activity.HistoricalTop1QueryCmd;
import com.red.circle.other.app.dto.cmd.activity.RankingListQueryCmd;
import com.red.circle.other.app.service.activity.RankingActivityService;
import com.red.circle.other.domain.ranking.RankingActivityType;
import com.red.circle.other.domain.ranking.RankingCycleType;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.time.temporal.WeekFields;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Objects;

/**
 * 历史Top1查询执行器
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class HistoricalTop1QryExe {

    private final RankingListQryExe rankingListQryExe;

    /**
     * 执行查询
     */
    public HistoricalTop1ListCO execute(HistoricalTop1QueryCmd cmd) {
        // 获取活动类型
        RankingActivityType activityType = RankingActivityType.getByCode(cmd.getActivityType());
        if (Objects.isNull(activityType)) {
            throw new IllegalArgumentException("无效的活动类型");
        }

        // 构建结果
        HistoricalTop1ListCO result = new HistoricalTop1ListCO();
        result.setActivityType(activityType.getCode());
        result.setActivityTypeName(activityType.getName());

        // 查询最近10周的Top1
        List<HistoricalWeekTop1CO> historicalList = new ArrayList<>();
        for (int i = 1; i <= 10; i++) {
            // 获取往前推i周的周一cycleKey
            String cycleKey = getWeekMondayCycleKey(i);

            // 查询该周的Top1
            RankingListQueryCmd queryCmd = new RankingListQueryCmd();
            queryCmd.setActivityType(cmd.getActivityType());
            queryCmd.setCycleType(RankingCycleType.WEEKLY.getCode());
            queryCmd.setCycleKey(cycleKey);
            queryCmd.setUserSex(cmd.getUserSex());
            queryCmd.setTopN(1); // 只查询Top1
            queryCmd.setReqSysOrigin(cmd.getReqSysOrigin());
            queryCmd.setIncludeCurrentUser(false); // 不需要查询当前用户排名

            try {
                var rankingList = rankingListQryExe.execute(queryCmd);

                // 如果有数据，添加到结果中
                if (Objects.nonNull(rankingList) &&
                    Objects.nonNull(rankingList.getRankingList()) &&
                    !rankingList.getRankingList().isEmpty()) {

                    HistoricalWeekTop1CO weekTop1 = new HistoricalWeekTop1CO();
                    weekTop1.setCycleKey(cycleKey);
                    weekTop1.setCycleDisplay(generateWeekEndDate(cycleKey));
                    weekTop1.setTopUser(rankingList.getRankingList().get(0));
                    historicalList.add(weekTop1);
                }
            } catch (Exception e) {
                log.warn("查询历史Top1失败, cycleKey={}", cycleKey, e);
            }
        }

        result.setHistoricalList(historicalList);
        return result;
    }

    /**
     * 获取往前推N周的周一cycleKey
     * 
     * @param weeksAgo 往前推的周数（0表示本周）
     * @return cycleKey（格式：yyyyMMdd）
     */
    private String getWeekMondayCycleKey(int weeksAgo) {
        // 使用亚洲/利雅得时区
        ZoneId riyadhZone = ZoneId.of("Asia/Riyadh");
        ZonedDateTime now = ZonedDateTime.now(riyadhZone);
        
        // 获取本周周一
        LocalDate monday = now.toLocalDate().with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
        
        // 往前推N周
        if (weeksAgo > 0) {
            monday = monday.minusWeeks(weeksAgo);
        }
        
        // 格式化为yyyyMMdd
        return monday.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
    }

    /**
     * 根据任意日期，返回其所在 ISO 周的周日（即该周最后一天）
     * ISO 周：周一为第一天，周日为最后一天
     *
     * @param dateKey 任意日期，格式 yyyyMMdd
     * @return 该 ISO 周周日的日期，格式 yyyy-MM-dd
     */
    private String generateWeekEndDate(String dateKey) {
        try {
            LocalDate inputDate = LocalDate.parse(dateKey, DateTimeFormatter.ofPattern("yyyyMMdd"));

            // 获取该日期所在 ISO 周的周一
            LocalDate monday = inputDate.with(DayOfWeek.MONDAY);
            // 周一 + 6 天 = 周日
            LocalDate sunday = monday.plusDays(6);

            return sunday.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        } catch (Exception e) {
            log.warn("生成周结束日期失败, dateKey={}", dateKey, e);
            return dateKey;
        }
    }
}
