from __future__ import annotations

import numpy as np

from blokus_gym.core.board import Board


class TestBoard:
    def test_board_creation(self):
        board = Board(20)
        assert board.size == 20
        assert board.grid.shape == (20, 20)
        assert np.all(board.grid == 0)

    def test_in_bounds(self):
        board = Board(20)
        assert board.in_bounds(0, 0)
        assert board.in_bounds(19, 19)
        assert not board.in_bounds(-1, 0)
        assert not board.in_bounds(20, 0)
        assert not board.in_bounds(0, 20)

    def test_place_and_get(self):
        board = Board(20)
        cells = [(0, 0), (1, 0), (2, 0)]
        board.place(1, cells)
        assert board.get_cell(0, 0) == 1
        assert board.get_cell(1, 0) == 1
        assert board.get_cell(2, 0) == 1
        assert board.get_cell(3, 0) == 0

    def test_has_overlap(self):
        board = Board(20)
        board.place(1, [(0, 0), (1, 0)])
        assert board.has_overlap([(0, 0), (1, 0)])  # overlap
        assert not board.has_overlap([(2, 0), (3, 0)])  # no overlap

    def test_has_overlap_out_of_bounds(self):
        board = Board(20)
        assert board.has_overlap([(20, 0)])  # out of bounds

    def test_clear(self):
        board = Board(20)
        board.place(1, [(0, 0)])
        board.clear()
        assert np.all(board.grid == 0)

    def test_get_player_squares(self):
        board = Board(20)
        board.place(1, [(0, 0), (1, 0)])
        squares = board.get_player_squares(1)
        assert len(squares) == 2
        assert (0, 0) in squares
        assert (1, 0) in squares

    def test_get_player_corners(self):
        board = Board(20)
        board.place(1, [(0, 0)])
        corners = board.get_player_corners(1)
        assert (1, 1) in corners  # diagonal
        assert (0, 0) not in corners  # occupied

    def test_is_full(self):
        board = Board(2)
        assert not board.is_full()
        board.place(1, [(0, 0), (0, 1), (1, 0), (1, 1)])
        assert board.is_full()

    def test_copy(self):
        board = Board(20)
        board.place(1, [(0, 0)])
        board_copy = board.copy()
        assert board_copy.get_cell(0, 0) == 1
        board_copy.place(2, [(1, 0)])
        assert board.get_cell(1, 0) == 0  # original unchanged

    def test_is_empty(self):
        board = Board(20)
        assert board.is_empty(0, 0)
        board.place(1, [(0, 0)])
        assert not board.is_empty(0, 0)

    def test_coverage(self):
        board = Board(2)
        assert board.coverage() == 0.0
        board.place(1, [(0, 0)])
        assert board.coverage() == 0.25

    def test_get_occupied(self):
        board = Board(20)
        board.place(1, [(0, 0), (1, 0)])
        board.place(2, [(5, 5)])
        occupied = board.get_occupied()
        assert (0, 0) in occupied
        assert (1, 0) in occupied
        assert (5, 5) in occupied
        assert (2, 0) not in occupied
