package de.champonthis.buntspecht.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.util.StringUtils;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import de.champonthis.buntspecht.businesslogic.UserManager;
import de.champonthis.buntspecht.controller.model.UserPasswordModel;
import de.champonthis.buntspecht.controller.support.EntityResponseStatusException;
import de.champonthis.buntspecht.controller.support.RequestBodyErrors;
import de.champonthis.buntspecht.controller.validation.PasswordModelValidator;
import de.champonthis.buntspecht.model.User;
import jakarta.transaction.Transactional;

@RestController
@RequestMapping("/users")
public class UserController extends BaseController {

	@Autowired
	private UserManager userManager;
	@Autowired
	private PasswordEncoder passwordEncoder;
	@Autowired
	private PasswordModelValidator passwordModelValidator;

	@PreAuthorize("isAuthenticated()")
	@GetMapping("/user")
	@Transactional
	public User get() {
		return userManager.getByUsername(getCurrentUsername());
	}

	@PreAuthorize("isAuthenticated()")
	@PatchMapping("/user")
	@Transactional
	public User updateUser(@RequestBody User user) {
		if (!getCurrentUsername().equals(user.getUsername())) {
			throw new EntityResponseStatusException(HttpStatus.UNPROCESSABLE_ENTITY);
		}

		User orgUser = userManager.getByUsername(user.getUsername());

		orgUser.setName(user.getName());
		orgUser.setAbout(user.getAbout());
		orgUser.setDarkTheme(user.isDarkTheme());
		orgUser.setEmail(user.getEmail());
		orgUser.setLocale(user.getLocale());

		user = userManager.save(orgUser);
		return user;
	}

	@PreAuthorize("isAuthenticated()")
	@PostMapping("/password")
	public void changePassword(@RequestBody UserPasswordModel passwordModel) {

		Errors errors = new RequestBodyErrors(passwordModel);

		User user = userManager.getByUsername(getCurrentUsername());

		if (!StringUtils.hasText(passwordModel.getOld())
				|| !passwordEncoder.matches(passwordModel.getOld(), userManager.getPasswordHash(user.getUsername()))) {
			errors.rejectValue("old", "UNAUTHORIZED");
		}

		passwordModelValidator.validate(passwordModel, errors);

		if (errors.hasErrors()) {
			throw new EntityResponseStatusException(errors.getAllErrors(), HttpStatus.CONFLICT);
		}

		userManager.setPassword(user.getUsername(), passwordModel.getPassword());
	}

}
