package de.nowchess.backcore.resource

import io.quarkus.test.junit.QuarkusTest
import io.restassured.RestAssured
import org.hamcrest.Matchers.{equalTo, notNullValue}
import org.junit.jupiter.api.Test

@QuarkusTest
class ResignDrawTest:

  private def createGame(): String =
    RestAssured
      .`given`()
      .contentType("application/json")
      .body("{}")
      .when()
      .post("/api/board/game")
      .`then`()
      .statusCode(201)
      .extract()
      .path[String]("gameId")

  // ─── Resign ────────────────────────────────────────────────────

  @Test
  def resignReturns200(): Unit =
    val gameId = createGame()
    RestAssured
      .`given`()
      .when()
      .post(s"/api/board/game/$gameId/resign")
      .`then`()
      .statusCode(200)
      .body("ok", equalTo(true))

  @Test
  def afterResignGameShowsResignStatusAndWinner(): Unit =
    val gameId = createGame()
    RestAssured
      .`given`()
      .when()
      .post(s"/api/board/game/$gameId/resign")
      .`then`()
      .statusCode(200)

    RestAssured
      .`given`()
      .when()
      .get(s"/api/board/game/$gameId")
      .`then`()
      .statusCode(200)
      .body("state.status", equalTo("resign"))
      .body("state.winner", notNullValue())

  @Test
  def resignOnUnknownGameReturns404(): Unit =
    RestAssured
      .`given`()
      .when()
      .post("/api/board/game/XXXXXXXX/resign")
      .`then`()
      .statusCode(404)

  // ─── Draw ──────────────────────────────────────────────────────

  @Test
  def offerDrawSetsDrawOfferedStatus(): Unit =
    val gameId = createGame()
    RestAssured
      .`given`()
      .when()
      .post(s"/api/board/game/$gameId/draw/offer")
      .`then`()
      .statusCode(200)
      .body("ok", equalTo(true))

    RestAssured
      .`given`()
      .when()
      .get(s"/api/board/game/$gameId")
      .`then`()
      .statusCode(200)
      .body("state.status", equalTo("drawOffered"))

  @Test
  def acceptDrawAfterOfferSetsDrawStatus(): Unit =
    val gameId = createGame()
    // White offers
    RestAssured
      .`given`()
      .when()
      .post(s"/api/board/game/$gameId/draw/offer")
      .`then`()
      .statusCode(200)

    // Black moves so it's black's turn... actually the API doesn't enforce turn-based draw accept.
    // White offered, so black (opponent) accepts — but since there's no auth, we just call accept.
    // The GameStore checks drawOfferedBy != turn to allow accept.
    // White offered on white's turn, so black needs to accept — but current turn is still white.
    // We need to make a move first to switch turns.
    RestAssured
      .`given`()
      .when()
      .post(s"/api/board/game/$gameId/move/e2e4")
      .`then`()
      .statusCode(200)

    // Now it's black's turn and white offered the draw — black accepts
    RestAssured
      .`given`()
      .when()
      .post(s"/api/board/game/$gameId/draw/accept")
      .`then`()
      .statusCode(200)
      .body("ok", equalTo(true))

    RestAssured
      .`given`()
      .when()
      .get(s"/api/board/game/$gameId")
      .`then`()
      .statusCode(200)
      .body("state.status", equalTo("draw"))

  @Test
  def declineDrawClearsOffer(): Unit =
    val gameId = createGame()
    RestAssured
      .`given`()
      .when()
      .post(s"/api/board/game/$gameId/draw/offer")
      .`then`()
      .statusCode(200)

    RestAssured
      .`given`()
      .when()
      .post(s"/api/board/game/$gameId/draw/decline")
      .`then`()
      .statusCode(200)
      .body("ok", equalTo(true))

    RestAssured
      .`given`()
      .when()
      .get(s"/api/board/game/$gameId")
      .`then`()
      .statusCode(200)
      .body("state.status", equalTo("started"))

  @Test
  def acceptWithoutOfferReturns400(): Unit =
    val gameId = createGame()
    RestAssured
      .`given`()
      .when()
      .post(s"/api/board/game/$gameId/draw/accept")
      .`then`()
      .statusCode(400)

  @Test
  def drawOnUnknownGameReturns404(): Unit =
    RestAssured
      .`given`()
      .when()
      .post("/api/board/game/XXXXXXXX/draw/offer")
      .`then`()
      .statusCode(404)
