/*
 * Queue - A Queueing system that can be used to handle labs in higher education
 * Copyright (C) 2016-2024  Delft University of Technology
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */
package nl.tudelft.queue.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;

import nl.tudelft.labracore.api.ModuleControllerApi;
import nl.tudelft.labracore.api.dto.EditionDetailsDTO;
import nl.tudelft.labracore.api.dto.ModuleCreateDTO;
import nl.tudelft.librador.dto.DTOConverter;
import nl.tudelft.queue.cache.EditionCacheManager;
import nl.tudelft.queue.cache.ModuleCacheManager;
import nl.tudelft.queue.dto.create.QueueModuleCreateDTO;

@Controller
public class ModuleController {

	@Autowired
	private ModuleCacheManager mCache;

	@Autowired
	private EditionCacheManager eCache;

	@Autowired
	private ModuleControllerApi mApi;

	@Autowired
	private DTOConverter converter;

	/**
	 * Gets the creation page for a module in the given edition. This sets up page attributes and returns the
	 * thymeleaf template to resolve.
	 *
	 * @param  editionId The id of the edition the module should be in.
	 * @param  model     The model to fill out for Thymeleaf template resolution.
	 * @return           The Thymeleaf template to resolve.
	 */
	@GetMapping("/edition/{editionId}/modules/create")
	@PreAuthorize("@permissionService.canManageModules(#editionId)")
	public String getModuleCreatePage(@PathVariable Long editionId, Model model) {
		return addCreateModuleAttributes(editionId, new QueueModuleCreateDTO(editionId), model);
	}

	/**
	 * Creates a module from the given DTO in the edition with the given id.
	 *
	 * @param  editionId The id of the edition to create the module in.
	 * @param  dto       The creation DTO containing all information needed to create a new module.
	 * @param  model     The model to fill out for Thymeleaf template resolution.
	 * @return           A redirect back to the modules page or the module create page if something goes
	 *                   wrong.
	 */
	@PostMapping("/edition/{editionId}/modules/create")
	@PreAuthorize("@permissionService.canManageModules(#editionId)")
	public String createModule(@PathVariable Long editionId, QueueModuleCreateDTO dto, Model model) {
		// Ensure the DTO contains the right edition ID, as malicious users can inject a different ID in the form
		dto.setEditionId(editionId);

		ModuleCreateDTO create = dto.apply(converter);
		if (dto.hasErrors()) {
			return addCreateModuleAttributes(editionId, dto, model);
		}

		mApi.addModule(create).block();

		return "redirect:/edition/" + editionId + "/modules";
	}

	/**
	 * Gets the module removal page. This page is only to confirm that the user does indeed want to remove the
	 * module and all attached assignments/student groups.
	 *
	 * @param  moduleId The id of the module to remove.
	 * @param  model    The model to fill out for Thymeleaf template resolution.
	 * @return          The Thymeleaf template to resolve.
	 */
	@GetMapping("/module/{moduleId}/remove")
	@PreAuthorize("@permissionService.canManageModule(#moduleId)")
	public String getModuleRemovePage(@PathVariable Long moduleId,
			Model model) {
		var module = mCache.getRequired(moduleId);
		var edition = eCache.getRequired(module.getEdition().getId());

		model.addAttribute("edition", edition);
		model.addAttribute("_module", module);

		return "module/remove";
	}

	/**
	 * Removes the module with the given id.
	 *
	 * @param  moduleId The id of the module to delete.
	 * @return          A redirect back to the edition modules page.
	 */
	@PostMapping("/module/{moduleId}/remove")
	@PreAuthorize("@permissionService.canManageModule(#moduleId)")
	public String removeModule(@PathVariable Long moduleId) {
		var module = mCache.getRequired(moduleId);
		var edition = eCache.getRequired(module.getEdition().getId());

		mApi.deleteModule(moduleId).block();

		return "redirect:/edition/" + edition.getId() + "/modules";
	}

	/**
	 * Fills in page attributes for the module creation page with the id of the edition and the initial module
	 * creation DTO object.
	 *
	 * @param  editionId The id of the edition to add the module to.
	 * @param  dto       The initial creation DTO for the module.
	 * @param  model     The model to fill out for Thymeleaf template resolution.
	 * @return           The Thymeleaf template to resolve.
	 */
	private String addCreateModuleAttributes(Long editionId, QueueModuleCreateDTO dto, Model model) {
		EditionDetailsDTO edition = eCache.getRequired(editionId);

		model.addAttribute("edition", edition);
		model.addAttribute("dto", dto);

		return "module/create";
	}

}
