package com.reading.platform.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.reading.platform.common.enums.ErrorCode;
import com.reading.platform.common.exception.BusinessException;
import com.reading.platform.common.util.PageUtils;
import com.reading.platform.dto.request.TaskCreateRequest;
import com.reading.platform.dto.request.TaskUpdateRequest;
import com.reading.platform.entity.Task;
import com.reading.platform.entity.TaskCompletion;
import com.reading.platform.entity.TaskTarget;
import com.reading.platform.mapper.TaskCompletionMapper;
import com.reading.platform.mapper.TaskMapper;
import com.reading.platform.mapper.TaskTargetMapper;
import com.reading.platform.service.TaskService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Service
@RequiredArgsConstructor
public class TaskServiceImpl implements TaskService {

    private final TaskMapper taskMapper;
    private final TaskTargetMapper taskTargetMapper;
    private final TaskCompletionMapper taskCompletionMapper;

    @Override
    @Transactional
    public Task createTask(Long tenantId, Long creatorId, String creatorRole, TaskCreateRequest request) {
        Task task = new Task();
        task.setTenantId(tenantId);
        task.setTitle(request.getTitle());
        task.setDescription(request.getDescription());
        task.setType(request.getType() != null ? request.getType() : "homework");
        task.setCourseId(request.getCourseId());
        task.setCreatorId(creatorId);
        task.setCreatorRole(creatorRole);
        task.setStartDate(request.getStartDate());
        task.setDueDate(request.getDueDate());
        task.setStatus("pending");
        task.setAttachments(request.getAttachments());

        taskMapper.insert(task);

        // Create task targets
        if (request.getTargetIds() != null && !request.getTargetIds().isEmpty()) {
            for (Long targetId : request.getTargetIds()) {
                TaskTarget target = new TaskTarget();
                target.setTaskId(task.getId());
                target.setTargetType(request.getTargetType() != null ? request.getTargetType() : "class");
                target.setTargetId(targetId);
                taskTargetMapper.insert(target);
            }
        }

        return task;
    }

    @Override
    @Transactional
    public Task updateTask(Long id, TaskUpdateRequest request) {
        Task task = getTaskById(id);

        if (StringUtils.hasText(request.getTitle())) {
            task.setTitle(request.getTitle());
        }
        if (request.getDescription() != null) {
            task.setDescription(request.getDescription());
        }
        if (request.getType() != null) {
            task.setType(request.getType());
        }
        if (request.getStartDate() != null) {
            task.setStartDate(request.getStartDate());
        }
        if (request.getDueDate() != null) {
            task.setDueDate(request.getDueDate());
        }
        if (StringUtils.hasText(request.getStatus())) {
            task.setStatus(request.getStatus());
        }
        if (request.getAttachments() != null) {
            task.setAttachments(request.getAttachments());
        }

        taskMapper.updateById(task);
        return task;
    }

    @Override
    public Task getTaskById(Long id) {
        Task task = taskMapper.selectById(id);
        if (task == null) {
            throw new BusinessException(ErrorCode.DATA_NOT_FOUND, "Task not found");
        }
        return task;
    }

    @Override
    public Page<Task> getTaskPage(Long tenantId, Integer pageNum, Integer pageSize, String keyword, String type, String status) {
        Page<Task> page = PageUtils.of(pageNum, pageSize);
        LambdaQueryWrapper<Task> wrapper = new LambdaQueryWrapper<>();

        wrapper.eq(Task::getTenantId, tenantId);

        if (StringUtils.hasText(keyword)) {
            wrapper.like(Task::getTitle, keyword);
        }
        if (StringUtils.hasText(type)) {
            wrapper.eq(Task::getType, type);
        }
        if (StringUtils.hasText(status)) {
            wrapper.eq(Task::getStatus, status);
        }
        wrapper.orderByDesc(Task::getCreatedAt);

        return taskMapper.selectPage(page, wrapper);
    }

    @Override
    public Page<Task> getTasksByStudentId(Long studentId, Integer pageNum, Integer pageSize, String status) {
        Page<Task> page = PageUtils.of(pageNum, pageSize);

        // Get task IDs from task_completions for this student
        List<TaskCompletion> completions = taskCompletionMapper.selectList(
                new LambdaQueryWrapper<TaskCompletion>().eq(TaskCompletion::getStudentId, studentId)
        );

        if (completions.isEmpty()) {
            return page;
        }

        List<Long> taskIds = completions.stream()
                .map(TaskCompletion::getTaskId)
                .toList();

        LambdaQueryWrapper<Task> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(Task::getId, taskIds);

        if (StringUtils.hasText(status)) {
            wrapper.eq(Task::getStatus, status);
        }
        wrapper.orderByDesc(Task::getCreatedAt);

        return taskMapper.selectPage(page, wrapper);
    }

    @Override
    @Transactional
    public void deleteTask(Long id) {
        getTaskById(id);
        taskMapper.deleteById(id);
    }

    @Override
    @Transactional
    public void completeTask(Long taskId, Long studentId, String content, String attachments) {
        TaskCompletion completion = taskCompletionMapper.selectOne(
                new LambdaQueryWrapper<TaskCompletion>()
                        .eq(TaskCompletion::getTaskId, taskId)
                        .eq(TaskCompletion::getStudentId, studentId)
        );

        if (completion == null) {
            completion = new TaskCompletion();
            completion.setTaskId(taskId);
            completion.setStudentId(studentId);
            completion.setStatus("completed");
            completion.setCompletedAt(LocalDateTime.now());
            completion.setContent(content);
            completion.setAttachments(attachments);
            taskCompletionMapper.insert(completion);
        } else {
            completion.setStatus("completed");
            completion.setCompletedAt(LocalDateTime.now());
            completion.setContent(content);
            completion.setAttachments(attachments);
            taskCompletionMapper.updateById(completion);
        }
    }

    @Override
    public List<Task> getTasksByClassId(Long classId) {
        List<TaskTarget> targets = taskTargetMapper.selectList(
                new LambdaQueryWrapper<TaskTarget>()
                        .eq(TaskTarget::getTargetType, "class")
                        .eq(TaskTarget::getTargetId, classId)
        );

        if (targets.isEmpty()) {
            return new ArrayList<>();
        }

        List<Long> taskIds = targets.stream()
                .map(TaskTarget::getTaskId)
                .toList();

        return taskMapper.selectList(
                new LambdaQueryWrapper<Task>()
                        .in(Task::getId, taskIds)
                        .orderByDesc(Task::getCreatedAt)
        );
    }

}
