package com.example.demo.news.api;

import java.util.List;

import org.modelmapper.ModelMapper;
import org.modelmapper.TypeToken;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
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 com.example.demo.core.configuration.Constants;
import com.example.demo.department.api.DepartmentDto;
import com.example.demo.department.service.DepartmentService;
import com.example.demo.news.model.NewsEntity;
import com.example.demo.news.service.NewsService;

import jakarta.validation.Valid;

@Controller
@RequestMapping(NewsAdminController.URL)
public class NewsAdminController {
    public static final String URL = Constants.ADMIN_PREFIX + "/news";
    private static final String NEWS_URL = NewsController.URL;
    private static final String NEWS_EDIT_VIEW = "new-edit";
    private static final String NEWS_ATTRIBUTE = "news";
    private static final String DEPARTMENT_ATTRIBUTE = "departments";
    private final NewsService newsService;
    private final ModelMapper modelMapper;
    private final DepartmentService departmentService;

    public NewsAdminController(NewsService newsService, ModelMapper modelMapper, DepartmentService departmentService) {
        this.newsService = newsService;
        this.modelMapper = modelMapper;
        this.departmentService = departmentService;
    }

    private NewsDto toDto(NewsEntity entity) {
        return modelMapper.map(entity, NewsDto.class);
    }

    private NewsEntity toEntity(NewsDto dto) {
        final NewsEntity entity = modelMapper.map(dto, NewsEntity.class);
        entity.setDepartment(departmentService.get(dto.getDepartmentId()));
        return entity;
    }

    private List<DepartmentDto> getDepartments(){
       return modelMapper.map(departmentService.getAll(), new TypeToken<List<DepartmentDto>>(){}.getType());
    }

    @GetMapping("/edit/")
    public String create(Model model) {
        model.addAttribute(NEWS_ATTRIBUTE, new NewsDto());
        model.addAttribute(DEPARTMENT_ATTRIBUTE, getDepartments());
        return NEWS_EDIT_VIEW;
    }

    @PostMapping("/edit/")
    public String create(
            @ModelAttribute(name = NEWS_ATTRIBUTE) @Valid NewsDto newItem,
            BindingResult bindingResult,
            Model model) {
        if (bindingResult.hasErrors()) {
            return NEWS_EDIT_VIEW;
        }
        newsService.create(toEntity(newItem));
        return Constants.REDIRECT_VIEW + NEWS_URL;
    }

    @PostMapping("/delete/{id}")
    public String delete(
            @PathVariable(name = "id") Long id) {
        newsService.delete(id);
        return Constants.REDIRECT_VIEW + NEWS_URL;
    }

    @GetMapping("/edit/{id}")
    public String update(
            @PathVariable(name = "id") Long id,
            Model model) {
        if (id <= 0) {
            throw new IllegalArgumentException();
        }
        model.addAttribute(NEWS_ATTRIBUTE, toDto(newsService.get(id)));
        model.addAttribute(DEPARTMENT_ATTRIBUTE, getDepartments());
        return NEWS_EDIT_VIEW;
    }

    @PostMapping("/edit/{id}")
    public String update(
            @PathVariable(name = "id") Long id,
            @ModelAttribute(name = NEWS_ATTRIBUTE) @Valid NewsDto newItem,
            BindingResult bindingResult,
            Model model) {
        if (bindingResult.hasErrors()) {
            return NEWS_EDIT_VIEW;
        }
        if (id <= 0) {
            throw new IllegalArgumentException();
        }
        newsService.update(id, toEntity(newItem));
        return Constants.REDIRECT_VIEW + NEWS_URL;
    }
}
