package de.nowchess.backcore.resource

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

@QuarkusTest
class ImportExportTest:

  private val startFen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"

  // ─── Import FEN ────────────────────────────────────────────────

  @Test
  def importFenReturns201WithCorrectPosition(): Unit =
    RestAssured
      .`given`()
      .contentType("application/json")
      .body(s"""{"fen":"$startFen"}""")
      .when()
      .post("/api/board/game/import/fen")
      .`then`()
      .statusCode(201)
      .body("gameId", matchesPattern("[A-Za-z0-9]{8}"))
      .body("state.fen", equalTo(startFen))
      .body("state.turn", equalTo("white"))

  @Test
  def importFenWithCustomPositionWorks(): Unit =
    val fen = "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1"
    RestAssured
      .`given`()
      .contentType("application/json")
      .body(s"""{"fen":"$fen"}""")
      .when()
      .post("/api/board/game/import/fen")
      .`then`()
      .statusCode(201)
      .body("state.fen", equalTo(fen))
      .body("state.turn", equalTo("black"))

  @Test
  def importFenWithInvalidFenReturns400(): Unit =
    RestAssured
      .`given`()
      .contentType("application/json")
      .body("""{"fen":"not-a-fen"}""")
      .when()
      .post("/api/board/game/import/fen")
      .`then`()
      .statusCode(400)

  @Test
  def importFenWithNullBodyReturns400(): Unit =
    RestAssured
      .`given`()
      .contentType("application/json")
      .body("null")
      .when()
      .post("/api/board/game/import/fen")
      .`then`()
      .statusCode(400)

  // ─── Import PGN ────────────────────────────────────────────────

  @Test
  def importPgnReturns201(): Unit =
    RestAssured
      .`given`()
      .contentType("application/json")
      .body("""{"pgn":"1. e4 e5 2. Nf3 Nc6 *"}""")
      .when()
      .post("/api/board/game/import/pgn")
      .`then`()
      .statusCode(201)
      .body("gameId", matchesPattern("[A-Za-z0-9]{8}"))
      .body("state.turn", equalTo("white"))

  @Test
  def importPgnWithInvalidPgnReturns400(): Unit =
    RestAssured
      .`given`()
      .contentType("application/json")
      .body("""{"pgn":"1. z9 *"}""")
      .when()
      .post("/api/board/game/import/pgn")
      .`then`()
      .statusCode(400)

  @Test
  def importPgnWithNullBodyReturns400(): Unit =
    RestAssured
      .`given`()
      .contentType("application/json")
      .body("null")
      .when()
      .post("/api/board/game/import/pgn")
      .`then`()
      .statusCode(400)

  // ─── Export FEN ────────────────────────────────────────────────

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

    RestAssured
      .`given`()
      .when()
      .get(s"/api/board/game/$gameId/export/fen")
      .`then`()
      .statusCode(200)
      .body(equalTo(startFen))

  @Test
  def exportFenOnUnknownGameReturns404(): Unit =
    RestAssured
      .`given`()
      .when()
      .get("/api/board/game/XXXXXXXX/export/fen")
      .`then`()
      .statusCode(404)

  // ─── Export PGN ────────────────────────────────────────────────

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

    RestAssured
      .`given`()
      .when()
      .post(s"/api/board/game/$gameId/move/e2e4")
      .`then`()
      .statusCode(200)

    RestAssured
      .`given`()
      .when()
      .get(s"/api/board/game/$gameId/export/pgn")
      .`then`()
      .statusCode(200)
      .body(containsString("e4"))

  // ─── Stream ────────────────────────────────────────────────────

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

    val body = RestAssured
      .`given`()
      .when()
      .get(s"/api/board/game/$gameId/stream")
      .`then`()
      .statusCode(200)
      .contentType("application/x-ndjson")
      .extract()
      .body()
      .asString()

    assert(body.trim.startsWith("""{"type":"gameFull""""), s"Expected gameFull event, got: $body")

  @Test
  def streamOnUnknownGameReturns404(): Unit =
    RestAssured
      .`given`()
      .when()
      .get("/api/board/game/XXXXXXXX/stream")
      .`then`()
      .statusCode(404)
