package ru.ulstu.students.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import ru.ulstu.deadline.model.Deadline;
import ru.ulstu.students.model.Task;
import ru.ulstu.students.model.TaskDto;
import ru.ulstu.students.model.TaskFilterDto;
import ru.ulstu.students.service.TaskService;
import ru.ulstu.tags.model.Tag;
import springfox.documentation.annotations.ApiIgnore;

import javax.validation.Valid;
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;

import static org.springframework.util.StringUtils.isEmpty;
import static ru.ulstu.students.controller.Navigation.REDIRECT_TO;
import static ru.ulstu.students.controller.Navigation.TASKS_PAGE;
import static ru.ulstu.students.controller.Navigation.TASK_PAGE;

@Controller()
@RequestMapping(value = "/students")
@ApiIgnore
public class TaskController {

    private final TaskService taskService;

    public TaskController(TaskService taskService) {
        this.taskService = taskService;
    }

    @GetMapping("/dashboard")
    public void getDashboard(ModelMap modelMap) {
        modelMap.put("tasks", taskService.findAllDto());
    }

    @GetMapping("/tasks")
    public void getTask(ModelMap modelMap) {
        modelMap.put("filteredTasks", new TaskFilterDto(taskService.findAllDto(), null, null, null));
    }

    @GetMapping("/task")
    public void getTask(ModelMap modelMap, @RequestParam(value = "id") Integer id) {
        if (id != null && id > 0) {
            modelMap.put("taskDto", taskService.findOneDto(id));
        } else {
            modelMap.put("taskDto", new TaskDto());
        }
    }

    @PostMapping("/tasks")
    public void filterTasks(@Valid TaskFilterDto taskFilterDto, ModelMap modelMap) {
        modelMap.put("filteredTasks", new TaskFilterDto(taskService.filter(taskFilterDto),
                taskFilterDto.getStatus(),
                taskFilterDto.getTag(),
                taskFilterDto.getOrder()));
    }

    @PostMapping(value = "/task", params = "save")
    public String save(@Valid TaskDto taskDto, Errors errors) throws IOException {
        filterEmptyDeadlines(taskDto);
        if (taskDto.getDeadlines().isEmpty()) {
            errors.rejectValue("deadlines", "errorCode", "Не может быть пустым");
        }
        if (errors.hasErrors()) {
            return TASK_PAGE;
        }
        taskService.save(taskDto);
        return String.format(REDIRECT_TO, TASKS_PAGE);
    }

    @PostMapping(value = "/task", params = "addDeadline")
    public String addDeadline(@Valid TaskDto taskDto, Errors errors) {
        filterEmptyDeadlines(taskDto);
        if (errors.hasErrors()) {
            return TASK_PAGE;
        }
        taskDto.getDeadlines().add(new Deadline());
        return TASK_PAGE;
    }

    @GetMapping("/delete/{task-id}")
    public String delete(@PathVariable("task-id") Integer taskId) throws IOException {
        taskService.delete(taskId);
        return String.format(REDIRECT_TO, TASKS_PAGE);
    }


    @ModelAttribute("allStatuses")
    public List<Task.TaskStatus> getTaskStatuses() {
        return taskService.getTaskStatuses();
    }

    @ModelAttribute("allTags")
    public List<Tag> getTags() {
        return taskService.getTags();
    }

    private void filterEmptyDeadlines(TaskDto taskDto) {
        taskDto.setDeadlines(taskDto.getDeadlines().stream()
                .filter(dto -> dto.getDate() != null || !isEmpty(dto.getDescription()))
                .collect(Collectors.toList()));
    }
}