import test from "ava"

import Factory from "@/factory"

import Position from "~/app/models/position"
import Revision from "~/app/models/revision"

import { MOVE } from "~/share/constants/revision_types"

test("tableName", t => {
  t.is(Revision.forge().tableName, "revisions")
})

test("hasTimestamps", t => {
  t.true(Revision.forge().hasTimestamps)
})

test.serial("create: with invalid type does not raise", async t => {
  t.notThrows(() => {
    Revision.create({ type: "foobar" })
  })
})

test.serial("create: with a valid type returns result", async t => {
  const game = await Factory.game()
  const move = { from: "a1", to: "a8" }
  const type = MOVE

  const result = await Revision.create({ game, type, ...move })

  t.false(result) // invalid move
})

test("move: when valid", async t => {
  const game = await Factory.game()
  const move = { from: "e2", to: "e4" }

  const revision = await Revision.move({ game, ...move })
  const position = await revision.position().fetch()

  t.truthy(revision)

  t.is(1, position.get("move_number"))
  t.is(
    "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1",
    position.get("m_fen")
  )
})

test("move: causes game to emit capture", async t => {
  t.plan(2)

  const game_ = await Factory.game()

  const position = await Position.forge({
    move_number: 2,
    m_fen: "rnbqkb1r/pppp1ppp/5n2/4p3/4P3/5N2/PPPP1PPP/RNBQKB1R w KQkq - 2 3",
  }).save()

  await Revision.forge({
    game_id: game_.get("id"),
    source_game_id: game_.get("id"),
    position_id: position.get("id"),
    type: MOVE
  }).save()

  await game_.refresh()

  game_.on("capture", ({ game, piece }) => {
    t.is(game_, game)
    t.is("p", piece)
  })

  await Revision.move({ game: game_, from: "f3", to: "e5" })
})

test("move: when invalid", async t => {
  const game = await Factory.game()
  const move = { game, from: "e2", to: "e2", promotion: null }

  t.false(await Revision.move({ game, ...move }))
})

test("move: when game is over", async t => {
  const game = await Factory.game()

  const position = await Position.forge({
    move_number: 2,
    m_fen: "4k3/4P3/4K3/8/8/8/8/8 b - - 0 78",
  }).save()

  await Revision.forge({
    game_id: game.get("id"),
    source_game_id: game.get("id"),
    position_id: position.get("id"),
    type: MOVE
  }).save()

  await game.refresh()

  t.false(await Revision.move({ game }))
})

test("reserve", async t => {
  const source = await Factory.game()
  const target = await Factory.game()

  const piece = "p"

  const revision = await Revision.reserve({ source, targetUUID: target.get("uuid"), piece })
  await revision.refresh({ withRelated: ["position"] })

  const position = revision.related("position")

  t.is(1, position.get("move_number"))
  t.is(1, position.get("black_reserve")[piece])
})

@@ -872,32 +872,46 @@
  %22e4%22 %7D%0A%0A  const
+ %7B moveResult,
  revision = awai
@@ -895,32 +895,34 @@
 Result, revision
+ %7D
  = await Revisio
@@ -997,24 +997,47 @@
 ().fetch()%0A%0A
+  t.truthy(moveResult)%0A
   t.truthy(r
@@ -1190,16 +1190,16 @@
 n%22)%0A
+
   )%0A%7D)%0A%0A
 test
@@ -1198,609 +1198,8 @@
 %7D)%0A%0A
-test(%22move: causes game to emit capture%22, async t =%3E %7B%0A  t.plan(2)%0A%0A  const game_ = await Factory.game()%0A%0A  const position = await Position.forge(%7B%0A    move_number: 2,%0A    m_fen: %22rnbqkb1r/pppp1ppp/5n2/4p3/4P3/5N2/PPPP1PPP/RNBQKB1R w KQkq - 2 3%22,%0A  %7D).save()%0A%0A  await Revision.forge(%7B%0A    game_id: game_.get(%22id%22),%0A    source_game_id: game_.get(%22id%22),%0A    position_id: position.get(%22id%22),%0A    type: MOVE%0A  %7D).save()%0A%0A  await game_.refresh()%0A%0A  game_.on(%22capture%22, (%7B game, piece %7D) =%3E %7B%0A    t.is(game_, game)%0A    t.is(%22p%22, piece)%0A  %7D)%0A%0A  await Revision.move(%7B game: game_, from: %22f3%22, to: %22e5%22 %7D)%0A%7D)%0A%0A
 test

update server tests