package cz.muni.fi.pa165.soccermanager.controllers;


import static cz.muni.fi.pa165.soccermanager.ApplicationConstants.API_URL;
import static cz.muni.fi.pa165.soccermanager.ApplicationConstants.PLAYER_URL;

import cz.muni.fi.pa165.soccermanager.dto.PlayerDto;
import cz.muni.fi.pa165.soccermanager.dto.request.CreatePlayerRequest;
import cz.muni.fi.pa165.soccermanager.dto.request.UpdatePlayerDto;
import cz.muni.fi.pa165.soccermanager.service.PlayerService;
import cz.muni.fi.pa165.soccermanager.service.TeamService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import java.net.URI;
import java.util.List;
import java.util.Optional;

import io.swagger.v3.oas.annotations.tags.Tag;
import javax.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@Tag(name = "Player")
@RestController
@RequestMapping(API_URL)
@RequiredArgsConstructor
@CrossOrigin(origins = "*")
@SecurityRequirement(name = "bearerAuth")
public class PlayerController {

    private final PlayerService playerService;
    private final TeamService teamService;

    @Operation(summary = "Get player",
        description = "The purpose of this method is to provide player. Available only to Admin and User roles.")
    @GetMapping("/players/{playerId}")
    public ResponseEntity<PlayerDto> getPlayerById(@PathVariable Long playerId) {
        return ResponseEntity.of(playerService.findPlayerById(playerId));
    }

    @Operation(summary = "Update player",
        description = "The purpose of this method is to update player. Available only to Admin and User-owner of team, which the player belongs to.")
    @PutMapping("/players/{playerId}")
    public ResponseEntity<Void> updatePlayer(@Valid @RequestBody UpdatePlayerDto newPlayerDTO, @PathVariable Long playerId) {
        playerService.update(playerId,newPlayerDTO);
        return ResponseEntity.accepted().build();
    }

    @Operation(summary = "Get all players",
        description = "The purpose of this method is to provide players. Available to Admin and User roles.")
    @GetMapping("/players")
    public Page<PlayerDto> getPlayers(@RequestParam(value = "page",required = false) Optional<Integer> page,
        @RequestParam(value = "size",required = false) Optional<Integer> size, @RequestParam(required = false) Optional<String> sortBy){
        return
            playerService.getAllPlayers(page.orElse(0), size.orElse(20), sortBy.orElse("id"));
    }

    @Operation(summary = "Create player",
        description = "The purpose of this method is to create match. Available only to Admin role.")
    @PostMapping("/players")
    public ResponseEntity<PlayerDto> savePlayer(@Valid @RequestBody CreatePlayerRequest request) {
        final var id = playerService.savePlayer(request);
        final var next = new PlayerDto();
        next.setId(id);
        return ResponseEntity.created(URI.create(PLAYER_URL + next.getId())).body(next);
    }

    @Operation(summary = "Get all free agents",
        description = "The purpose of this method is to provide free agents. Available to Admin and User roles.")
    @GetMapping("/players/freeAgents")
    public ResponseEntity<List<PlayerDto>> getFreeAgents() {
        return ResponseEntity.ok(playerService.findFreeAgents());
    }

    @Operation(summary = "Get all players for given team",
        description = "The purpose of this method is to provide all players for given team. Available to Admin and User roles.")
    @GetMapping("/teams/{teamId}/players")
    public ResponseEntity<List<PlayerDto>> findPlayersByTeam(@PathVariable Long teamId) {
        return ResponseEntity.ok(playerService.findPlayersByTeam(teamId));
    }

    @Operation(summary = "Add player to given team",
        description = "The purpose of this method is to add player to given team. Available to Admin and User-owner of given team.")
    @PutMapping("/teams/{teamId}/add/{playerId}")
    public ResponseEntity<Void> addPlayer(@PathVariable Long teamId, @PathVariable Long playerId) {
        teamService.addFreeAgent(playerId, teamId);
        return ResponseEntity.accepted().build();
    }

    @Operation(summary = "Remove player from given team",
        description = "The purpose of this method is to remove player from given team. Available to Admin and User-owner of given team.")
    @PutMapping("/teams/{teamId}/remove/{playerId}")
    public ResponseEntity<Void> removePlayer(@PathVariable Long teamId, @PathVariable Long playerId) {
        teamService.removePlayer(teamId, playerId);
        return ResponseEntity.accepted().build();
    }

}
