package com.sundot.airport.exam.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.sundot.airport.common.annotation.Log;
import com.sundot.airport.common.core.controller.BaseController;
import com.sundot.airport.common.core.domain.AjaxResult;
import com.sundot.airport.common.core.page.TableDataInfo;
import com.sundot.airport.common.enums.BusinessType;
import com.sundot.airport.common.utils.SecurityUtils;
import com.sundot.airport.exam.domain.DailyTask;
import com.sundot.airport.exam.domain.DailyTaskDetail;
import com.sundot.airport.exam.mapper.DailyTaskDetailMapper;
import com.sundot.airport.exam.mapper.DailyTaskMapper;
import com.sundot.airport.exam.dto.StartTaskDTO;
import com.sundot.airport.exam.dto.SubmitAnswerDTO;
import com.sundot.airport.exam.dto.SubmitResultDTO;
import com.sundot.airport.exam.service.IDailyAnswerService;
import com.sundot.airport.exam.service.IDailyTaskGenerationService;
import com.sundot.airport.common.core.domain.entity.SysUser;
import com.sundot.airport.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;

/**
 * <b>功能名：</b>DailyTaskController<br>
 * <b>说明：</b> 每日答题任务Controller <br>
 * <b>著作权：</b> Copyright (C) 2025 SUNDOT CORPORATION<br>
 * <b>修改履历：
 *
 * @author Simon Lin
 */
@RestController
@RequestMapping("/exam/daily/task")
public class DailyTaskController extends BaseController {

    @Autowired
    private DailyTaskMapper dailyTaskMapper;

    @Autowired
    private DailyTaskDetailMapper dailyTaskDetailMapper;

    @Autowired
    private IDailyTaskGenerationService dailyTaskGenerationService;

    @Autowired
    private IDailyAnswerService dailyAnswerService;

    @Autowired
    private ISysUserService userService;

    /**
     * 查询当前用户的任务列表（全部任务）
     */
    @GetMapping("/my-tasks")
    public TableDataInfo myTasks() {
        Long userId = SecurityUtils.getUserId();

        LambdaQueryWrapper<DailyTask> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DailyTask::getDtUserId, userId);
        wrapper.eq(DailyTask::getDelStatus, 0);
        wrapper.orderByDesc(DailyTask::getDtBusinessDate);
        wrapper.orderByDesc(DailyTask::getCreateTime);

        startPage();
        List<DailyTask> list = dailyTaskMapper.selectList(wrapper);

        // 为每个任务填充试卷总分和题目总数
        enrichTasksWithScoreAndCount(list);

        return getDataTable(list);
    }

    /**
     * 查询当前用户的当天有效任务（未过期的任务）
     * 筛选条件：当前时间 < dt_expire_time
     */
    @GetMapping("/my-tasks-today")
    public TableDataInfo myTasksToday() {
        Long userId = SecurityUtils.getUserId();

        LambdaQueryWrapper<DailyTask> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DailyTask::getDtUserId, userId);
        wrapper.eq(DailyTask::getDelStatus, 0);
        // 筛选未过期的任务：当前时间 < 过期时间
        wrapper.gt(DailyTask::getDtExpireTime, new java.util.Date());
        wrapper.orderByDesc(DailyTask::getDtBusinessDate);
        wrapper.orderByDesc(DailyTask::getCreateTime);

        startPage();
        List<DailyTask> list = dailyTaskMapper.selectList(wrapper);

        // 为每个任务填充试卷总分和题目总数
        enrichTasksWithScoreAndCount(list);

        return getDataTable(list);
    }

    /**
     * 查询我的已过期任务列表
     * 筛选条件：过期时间 <= 当前时间
     */
    @GetMapping("/my-tasks-expired")
    public TableDataInfo myTasksExpired() {
        Long userId = SecurityUtils.getUserId();

        LambdaQueryWrapper<DailyTask> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DailyTask::getDtUserId, userId);
        wrapper.eq(DailyTask::getDelStatus, 0);
        // 已过期: expire_time <= now
        wrapper.le(DailyTask::getDtExpireTime, new java.util.Date());
        wrapper.orderByDesc(DailyTask::getDtBusinessDate);
        wrapper.orderByDesc(DailyTask::getCreateTime);

        startPage();
        List<DailyTask> list = dailyTaskMapper.selectList(wrapper);

        // 为每个任务填充试卷总分和题目总数
        enrichTasksWithScoreAndCount(list);

        return getDataTable(list);
    }

    /**
     * 查询我的已完成任务列表
     * 筛选条件：任务状态为 COMPLETED
     */
    @GetMapping("/my-tasks-completed")
    public TableDataInfo myTasksCompleted() {
        Long userId = SecurityUtils.getUserId();

        LambdaQueryWrapper<DailyTask> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DailyTask::getDtUserId, userId);
        wrapper.eq(DailyTask::getDelStatus, 0);
        wrapper.eq(DailyTask::getDtStatus, "COMPLETED"); // 已完成的任务
        wrapper.orderByDesc(DailyTask::getDtBusinessDate);
        wrapper.orderByDesc(DailyTask::getCreateTime);

        startPage();
        List<DailyTask> list = dailyTaskMapper.selectList(wrapper);

        // 为每个任务填充试卷总分和题目总数
        enrichTasksWithScoreAndCount(list);

        return getDataTable(list);
    }

    /**
     * 查询任务详情（包含题目列表）
     * 所有登录用户可访问（已移除权限控制）
     */
    @GetMapping("/{taskId}")
    public AjaxResult getTaskDetail(@PathVariable String taskId) {
        // 查询任务主记录（taskId是业务主键dt_id）
        LambdaQueryWrapper<DailyTask> taskWrapper = new LambdaQueryWrapper<>();
        taskWrapper.eq(DailyTask::getDtId, taskId);
        taskWrapper.eq(DailyTask::getDelStatus, 0);
        DailyTask task = dailyTaskMapper.selectOne(taskWrapper);

        if (task == null) {
            return error("任务不存在");
        }

        // 验证权限：只能查看自己的任务
        Long userId = SecurityUtils.getUserId();
        if (!task.getDtUserId().equals(userId)) {
            return error("无权查看该任务");
        }

        // 查询任务明细
        LambdaQueryWrapper<DailyTaskDetail> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DailyTaskDetail::getDtdTaskId, taskId);
        wrapper.eq(DailyTaskDetail::getDelStatus, 0);
        wrapper.orderByAsc(DailyTaskDetail::getDtdQuestionNo);
        List<DailyTaskDetail> details = dailyTaskDetailMapper.selectList(wrapper);

        // 组装返回结果
        AjaxResult result = AjaxResult.success();
        result.put("task", task);
        result.put("details", details);
        return result;
    }

    /**
     * 手动触发任务生成
     *
     * @param userNames 可选参数，指定用户名列表，例如：["AJ307","AJ308"]
     *                  如果不传或为空，则为当前登录用户生成任务
     *                  如果传了用户名列表，则为这些用户批量生成任务
     */
//    @PreAuthorize("@ss.hasPermi('exam:daily:task:generate')")
    @Log(title = "手动生成答题任务", businessType = BusinessType.INSERT)
    @PostMapping("/generate")
    public AjaxResult manualGenerate(@RequestParam(value = "user_name", required = false) List<String> userNames) {
        try {
            // 判断是批量生成还是单用户生成
            if (userNames != null && !userNames.isEmpty()) {
                // 批量为指定用户生成任务
                return batchGenerateTasks(userNames);
            } else {
                // 为当前登录用户生成任务
                return generateTaskForCurrentUser();
            }
        } catch (Exception e) {
            logger.error("手动生成任务失败", e);
            return error("任务生成失败：" + e.getMessage());
        }
    }

    /**
     * 为当前登录用户生成任务
     */
    private AjaxResult generateTaskForCurrentUser() {
        Long userId = SecurityUtils.getUserId();
        Long deptId = SecurityUtils.getLoginUser().getUser().getDeptId();

        dailyTaskGenerationService.handleClockInEvent(userId, deptId);
        return success("任务生成成功");
    }

    /**
     * 批量为指定用户生成任务
     *
     * @param userNames 用户名列表
     */
    private AjaxResult batchGenerateTasks(List<String> userNames) {
        List<String> successUsers = new ArrayList<>();
        List<String> failedUsers = new ArrayList<>();

        for (String userName : userNames) {
            try {
                // 根据 user_name 查询用户
                SysUser user = userService.selectUserByUserName(userName);

                if (user == null) {
                    failedUsers.add(userName + "(用户不存在)");
                    logger.warn("用户不存在: {}", userName);
                    continue;
                }

                // 为该用户生成任务
                dailyTaskGenerationService.handleClockInEvent(user.getUserId(), user.getDeptId());
                successUsers.add(userName);
                logger.info("成功为用户 {} 生成任务", userName);

            } catch (Exception e) {
                failedUsers.add(userName + "(" + e.getMessage() + ")");
                logger.error("为用户 {} 生成任务失败", userName, e);
            }
        }

        // 组装返回结果
        AjaxResult result = AjaxResult.success();
        result.put("total", userNames.size());
        result.put("successCount", successUsers.size());
        result.put("failedCount", failedUsers.size());
        result.put("successUsers", successUsers);
        result.put("failedUsers", failedUsers);

        if (failedUsers.isEmpty()) {
            result.put("msg", String.format("批量生成任务成功，共处理 %d 个用户", successUsers.size()));
        } else {
            result.put("msg", String.format("批量生成任务完成，成功 %d 个，失败 %d 个", successUsers.size(), failedUsers.size()));
        }

        return result;
    }

    /**
     * 查询今日是否有待完成任务
     */
    @GetMapping("/has-pending-task")
    public AjaxResult hasPendingTask() {
        Long userId = SecurityUtils.getUserId();
        boolean hasTask = dailyTaskGenerationService.hasTaskToday(userId);
        return AjaxResult.success().put("hasPendingTask", hasTask);
    }

    /**
     * 开始答题
     */
    @Log(title = "开始答题", businessType = BusinessType.UPDATE)
    @PostMapping("/start/{taskId}")
    public AjaxResult startTask(@PathVariable String taskId) {
        Long userId = SecurityUtils.getUserId();

        try {
            StartTaskDTO result = dailyAnswerService.startTask(userId, taskId);
            return AjaxResult.success(result);
        } catch (Exception e) {
            logger.error("开始答题失败 - taskId: {}", taskId, e);
            return error(e.getMessage());
        }
    }

    /**
     * 提交答案
     */
    @Log(title = "提交答案", businessType = BusinessType.UPDATE)
    @PostMapping("/submit")
    public AjaxResult submitAnswer(@Validated @RequestBody SubmitAnswerDTO dto) {
        Long userId = SecurityUtils.getUserId();

        try {
            SubmitResultDTO result = dailyAnswerService.submitAnswer(userId, dto);
            return AjaxResult.success(result);
        } catch (Exception e) {
            logger.error("提交答案失败 - taskId: {}", dto.getTaskId(), e);
            return error(e.getMessage());
        }
    }

    /**
     * 获取任务剩余时间
     */
    @GetMapping("/remaining-time/{taskId}")
    public AjaxResult getRemainingTime(@PathVariable String taskId) {
        Long userId = SecurityUtils.getUserId();

        try {
            Integer remainingTime = dailyAnswerService.getRemainingTime(userId, taskId);
            return AjaxResult.success().put("remainingTime", remainingTime);
        } catch (Exception e) {
            logger.error("获取剩余时间失败 - taskId: {}", taskId, e);
            return error(e.getMessage());
        }
    }

    /**
     * 为任务列表填充试卷总分和题目总数
     *
     * @param tasks 任务列表
     */
    private void enrichTasksWithScoreAndCount(List<DailyTask> tasks) {
        if (tasks == null || tasks.isEmpty()) {
            return;
        }

        for (DailyTask task : tasks) {
            // 查询该任务的所有题目明细
            LambdaQueryWrapper<DailyTaskDetail> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(DailyTaskDetail::getDtdTaskId, task.getDtId());
            wrapper.eq(DailyTaskDetail::getDelStatus, 0);
            List<DailyTaskDetail> details = dailyTaskDetailMapper.selectList(wrapper);

            if (details != null && !details.isEmpty()) {
                // 计算题目总数
                task.setQuestionCount(details.size());

                // 计算试卷总分（所有题目满分之和）
                java.math.BigDecimal totalScore = details.stream()
                        .map(DailyTaskDetail::getDtdScore)
                        .filter(java.util.Objects::nonNull)
                        .reduce(java.math.BigDecimal.ZERO, java.math.BigDecimal::add);
                task.setFullScore(totalScore);
            } else {
                // 没有题目明细，设置为0
                task.setQuestionCount(0);
                task.setFullScore(java.math.BigDecimal.ZERO);
            }
        }
    }
}
