package de.szut.casino.blackjack;

import de.szut.casino.exceptionHandling.exceptions.InsufficientFundsException;
import de.szut.casino.exceptionHandling.exceptions.UserNotFoundException;
import de.szut.casino.shared.dto.BetDto;
import de.szut.casino.shared.service.BalanceService;
import de.szut.casino.user.UserEntity;
import de.szut.casino.user.UserService;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.Objects;
import java.util.Optional;

@Slf4j
@RestController
public class BlackJackGameController {

    private final BalanceService balanceService;
    private final UserService userService;
    private final BlackJackService blackJackService;

    public BlackJackGameController(BalanceService balanceService, UserService userService, BlackJackService blackJackService) {
        this.balanceService = balanceService;
        this.blackJackService = blackJackService;
        this.userService = userService;
    }

    @GetMapping("/blackjack/{id}")
    public ResponseEntity<Object> getGame(@PathVariable Long id) {
        Optional<UserEntity> optionalUser = userService.getCurrentUser();

        if (optionalUser.isEmpty()) {
            throw new UserNotFoundException();
        }

        UserEntity user = optionalUser.get();
        BlackJackGameEntity game = blackJackService.getBlackJackGame(id);
        if (game == null || !Objects.equals(game.getUserId(), user.getId())) {
            return ResponseEntity.notFound().build();
        }

        return ResponseEntity.ok(game);
    }

    @PostMapping("/blackjack/{id}/hit")
    public ResponseEntity<Object> hit(@PathVariable Long id) {
        Optional<UserEntity> optionalUser = userService.getCurrentUser();

        if (optionalUser.isEmpty()) {
            throw new UserNotFoundException();
        }

        UserEntity user = optionalUser.get();
        BlackJackGameEntity game = blackJackService.getBlackJackGame(id);
        if (game == null || !Objects.equals(game.getUserId(), user.getId())) {
            return ResponseEntity.notFound().build();
        }

        return ResponseEntity.ok(blackJackService.hit(game));
    }

    @PostMapping("/blackjack/{id}/stand")
    public ResponseEntity<Object> stand(@PathVariable Long id) {
        Optional<UserEntity> optionalUser = userService.getCurrentUser();

        if (optionalUser.isEmpty()) {
            throw new UserNotFoundException();
        }

        UserEntity user = optionalUser.get();
        BlackJackGameEntity game = blackJackService.getBlackJackGame(id);
        if (game == null || !Objects.equals(game.getUserId(), user.getId())) {
            return ResponseEntity.notFound().build();
        }

        return ResponseEntity.ok(blackJackService.stand(game));
    }

    @PostMapping("/blackjack/{id}/doubleDown")
    public ResponseEntity<Object> doubleDown(@PathVariable Long id) {
        Optional<UserEntity> optionalUser = userService.getCurrentUser();

        if (optionalUser.isEmpty()) {
            throw new UserNotFoundException();
        }

        UserEntity user = optionalUser.get();
        BlackJackGameEntity game = blackJackService.getBlackJackGame(id);
        if (game == null || !Objects.equals(game.getUserId(), user.getId())) {
            return ResponseEntity.notFound().build();
        }

        return ResponseEntity.ok(blackJackService.doubleDown(game));
    }

    @PostMapping("/blackjack/{id}/split")
    public ResponseEntity<Object> split(@PathVariable Long id) {
        Optional<UserEntity> optionalUser = userService.getCurrentUser();

        if (optionalUser.isEmpty()) {
            throw new UserNotFoundException();
        }

        UserEntity user = optionalUser.get();
        BlackJackGameEntity game = blackJackService.getBlackJackGame(id);
        if (game == null || !Objects.equals(game.getUserId(), user.getId())) {
            return ResponseEntity.notFound().build();
        }

        return ResponseEntity.ok(blackJackService.split(game));
    }

    @PostMapping("/blackjack/start")
    public ResponseEntity<Object> createBlackJackGame(@RequestBody @Valid BetDto betDto) {
        Optional<UserEntity> optionalUser = userService.getCurrentUser();

        if (optionalUser.isEmpty()) {
            throw new UserNotFoundException();
        }

        UserEntity user = optionalUser.get();

        if (!this.balanceService.hasFunds(user, betDto)) {
            throw new InsufficientFundsException();
        }

        return ResponseEntity.ok(blackJackService.createBlackJackGame(user, betDto.getBetAmount()));
    }
}
