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

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.red.circle.other.app.dto.cmd.SpinsTaskProgressUpdateCmd;
import com.red.circle.other.infra.database.rds.dao.task.SpinsTaskConfigDAO;
import com.red.circle.other.infra.database.rds.dao.task.SpinsUserTaskProgressDAO;
import com.red.circle.other.infra.database.rds.entity.task.SpinsTaskConfig;
import com.red.circle.other.infra.database.rds.entity.task.SpinsUserTaskProgress;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;

/**
 * 更新任务进度执行器
 *
 * @author system
 * @date 2025-01-21
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class SpinsTaskProgressUpdateExe {

    private final SpinsTaskConfigDAO spinsTaskConfigDAO;
    private final SpinsUserTaskProgressDAO spinsUserTaskProgressDAO;

    /**
     * 执行更新任务进度
     *
     * @param cmd 更新命令
     */
    @Transactional(rollbackFor = Exception.class)
    public void execute(SpinsTaskProgressUpdateCmd cmd) {
        Long userId = cmd.getUserId();
        String taskCode = cmd.getTaskCode();
        Integer progressValue = cmd.getProgressValue();

        // 1. 查询任务配置
        List<SpinsTaskConfig> taskConfigs =  spinsTaskConfigDAO.selectList(
                new LambdaQueryWrapper<SpinsTaskConfig>()
                        .eq(SpinsTaskConfig::getTaskCode, taskCode)
                        .eq(SpinsTaskConfig::getStatus, 1)
        );

        if (taskConfigs.isEmpty()) {
            log.warn("任务配置不存在或已下线, taskCode={}", taskCode);
            return;
        }
        SpinsTaskConfig taskConfig = taskConfigs.get(0);

          // 2. 获取或创建用户任务进度
        String cycleKey = getCurrentCycleKey(taskConfig.getCycleType());
        SpinsUserTaskProgress progress = getOrCreateProgress(userId, taskConfig, cycleKey);

        // 3. 校验任务状态，如果已完成或已领取，则不更新
        if (progress.getTaskStatus() != null && progress.getTaskStatus() >= 1) {
            log.info("任务已完成，无需更新进度, userId={}, taskCode={}, taskStatus={}", 
                    userId, taskCode, progress.getTaskStatus());
            return;
        }

        // 4. 更新进度值
        progress.setCurrentValue(progressValue);
        
        // 5. 计算进度百分比
        BigDecimal progressRate = calculateProgressRate(progressValue, taskConfig.getTargetValue());
        progress.setProgressRate(progressRate);

        // 6. 检查是否完成
        if (progressValue >= taskConfig.getTargetValue() && progress.getTaskStatus() == 0) {
            progress.setTaskStatus(1);
            progress.setCompleteTime(new Timestamp(System.currentTimeMillis()));
            progress.setCompleteTimes(progress.getCompleteTimes() + 1);
            log.info("任务完成, userId={}, taskCode={}, progressValue={}", userId, taskCode, progressValue);
        }

        progress.setUpdateTime(new Timestamp(System.currentTimeMillis()));
        spinsUserTaskProgressDAO.updateById(progress);

        log.info("任务进度更新成功, userId={}, taskCode={}, progressValue={}, progressRate={}", 
                userId, taskCode, progressValue, progressRate);
    }

    /**
     * 获取或创建用户任务进度
     */
    private SpinsUserTaskProgress getOrCreateProgress(Long userId, SpinsTaskConfig taskConfig, String cycleKey) {
        List<SpinsUserTaskProgress> progressList = spinsUserTaskProgressDAO.selectList(
                new LambdaQueryWrapper<SpinsUserTaskProgress>()
                        .eq(SpinsUserTaskProgress::getUserId, userId)
                        .eq(SpinsUserTaskProgress::getTaskCode, taskConfig.getTaskCode())
                        .eq(SpinsUserTaskProgress::getCycleKey, cycleKey)
        );

        SpinsUserTaskProgress progress = null;
        if (!progressList.isEmpty()) {
          progress =  progressList.get(0);
        }

        if (progress == null) {
            progress = new SpinsUserTaskProgress();
            progress.setUserId(userId);
            progress.setTaskId(taskConfig.getId());
            progress.setTaskCode(taskConfig.getTaskCode());
            progress.setCurrentValue(0);
            progress.setTargetValue(taskConfig.getTargetValue());
            progress.setProgressRate(BigDecimal.ZERO);
            progress.setTaskStatus(0);
            progress.setCycleType(taskConfig.getCycleType());
            progress.setCycleDate(LocalDate.now());
            progress.setCycleKey(cycleKey);
            progress.setCompleteTimes(0);
            progress.setRewardType(taskConfig.getRewardType());
            progress.setRewardValue(taskConfig.getRewardValue());
            progress.setCreateTime(new Timestamp(System.currentTimeMillis()));
            progress.setUpdateTime(new Timestamp(System.currentTimeMillis()));
            spinsUserTaskProgressDAO.insert(progress);
        }

        return progress;
    }

    /**
     * 计算进度百分比
     */
    private BigDecimal calculateProgressRate(Integer currentValue, Integer targetValue) {
        if (targetValue == null || targetValue == 0) {
            return BigDecimal.ZERO;
        }
        return BigDecimal.valueOf(currentValue)
                .divide(BigDecimal.valueOf(targetValue), 4, RoundingMode.HALF_UP)
                .multiply(BigDecimal.valueOf(100))
                .setScale(2, RoundingMode.HALF_UP);
    }

    /**
     * 获取当前周期key
     */
    private String getCurrentCycleKey(Integer cycleType) {
        LocalDate now = LocalDate.now();
        if (cycleType == 1) {
            // 每日任务：格式 yyyyMMdd
            return now.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        } else if (cycleType == 2) {
            // 每周任务：格式 yyyyWw（例如：2025W03）
            int weekOfYear = now.getDayOfYear() / 7 + 1;
            return now.getYear() + "W" + String.format("%02d", weekOfYear);
        } else {
            // 一次性任务：固定标识
            return "ONCE";
        }
    }
}
