package premium_store.controller.controller;

import org.springframework.data.domain.Page;
import org.springframework.security.access.annotation.Secured;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import premium_store.controller.DTO.*;
import premium_store.model.UserRole;
import premium_store.service.GameClientService;
import premium_store.service.TankService;

import javax.validation.Valid;
import java.security.Principal;
import java.util.List;
import java.util.stream.IntStream;

@Controller
@RequestMapping("/clients")
public class GameClientMvcController {
    private final GameClientService gameClientService;
    private final TankService tankService;

    public GameClientMvcController(GameClientService gameClientService, TankService tankService){
        this.gameClientService = gameClientService;
        this.tankService = tankService;
    }

    @GetMapping({"/showUpdate"})
    public String showUpdateUserForm(Principal principal, Model model) {
        ClientDTO clientDTO = new ClientDTO(gameClientService.findByLogin(principal.getName()));
        model.addAttribute("clientDTO", clientDTO);
        return "client-edit";
    }

    @GetMapping
    @Secured({UserRole.AsString.ADMIN})
    public String getClients(@RequestParam(defaultValue = "1") int page,
                             @RequestParam(defaultValue = "5") int size,
                             Principal principal, Model model) {
        final Page<ClientDTO> users = gameClientService.findAllPages(page, size)
                .map(ClientDTO::new);

        model.addAttribute("users", users);

        final int totalPages = users.getTotalPages();

        final List<Integer> pageNumbers = IntStream.rangeClosed(1, totalPages)
                .boxed()
                .toList();

        model.addAttribute("pages", pageNumbers);
        model.addAttribute("totalPages", totalPages);

        return "clients";
    }

    @GetMapping(value = {"/edit", "/edit/{id}"})
    public String editClient(@PathVariable(required = false) Long id, Model model) {
        if(id == null || id <= 0){
            model.addAttribute("supportClientDTO", new SupportClientDTO());
        }
        else {
            model.addAttribute("clientId", id);
            model.addAttribute("supportClientDTO", new SupportClientDTO(gameClientService.findClient(id)));
        }

        List<TankDTO> tanks = tankService.findAllTanks().stream()
                .map(TankDTO::new)
                .toList();

        model.addAttribute("tanks", tanks);

        /*if (bindingResult.hasErrors()) {
            model.addAttribute("errors", bindingResult.getAllErrors());
            return "client-edit";
        }

        try {
            gameClientService.updateClient(userDto);

            @SuppressWarnings("unchecked")
            Collection<SimpleGrantedAuthority> nowAuthorities =
                    (Collection<SimpleGrantedAuthority>) SecurityContextHolder.getContext()
                            .getAuthentication()
                            .getAuthorities();

            UsernamePasswordAuthenticationToken authentication =
                    new UsernamePasswordAuthenticationToken(userDto.getLogin(), nowAuthorities);

            SecurityContextHolder.getContext().setAuthentication(authentication);
        } catch (ValidationException e) {
            model.addAttribute("errors", e.getMessage());
        }*/

        return "client-edit";
    }

    @GetMapping(value = {"/tanksOfClient", "/tanksOfClient/{id}"})
    @Secured({UserRole.AsString.ADMIN})
    public String editTanksOfClient(@PathVariable(required = false) Long id, Model model){
        if(id == null || id <= 0){
            model.addAttribute("clientDTO", new ClientDTO());
        }
        else {
            model.addAttribute("clientId", id);
            model.addAttribute("clientDTO", new ClientDTO(gameClientService.findClient(id)));
        }

        return "tanks-of-client-edit";
    }

    @PostMapping(value = {"", "/{id}"})
    public String saveClient(@PathVariable(required = false) Long id,
                           @ModelAttribute @Valid SupportClientDTO clientDTO,
                           BindingResult bindingResult,
                           Model model){
        if(bindingResult.hasErrors()){
            model.addAttribute("errors", bindingResult.getAllErrors());
            return "client-edit";
        }

        //тут два раза прокидываем пароль, так как метод требует на вход строку с подтверждением пароля
        if(id == null || id <= 0){
            gameClientService.addClient(clientDTO.getLogin(), clientDTO.getPassword(), clientDTO.getEmail(), clientDTO.getBalance(), clientDTO.getPassword(), clientDTO.getRole());
        } else {
            gameClientService.updateClient(clientDTO);
        }

        return "redirect:/clients";
    }

    @PostMapping("/delete/{id}")
    @Secured({UserRole.AsString.ADMIN})
    public String deleteClient(Principal principal, Model model,
                            @PathVariable Long id){
        gameClientService.deleteClient(id);
        return "redirect:/clients";
    }
}