from __future__ import annotations

from catan.data import Resource
from catan.game import GameConfig, Phase
from catan.sdk import ActionType, CatanEnv

from tests.utils import find_initial_spot


def _auto_setup(env: CatanEnv) -> None:
    game = env.game
    while game.phase != Phase.MAIN:
        corner, road = find_initial_spot(game)
        game.place_initial_settlement(corner, road)


def test_bank_trade_action_and_port_ratio() -> None:
    env = CatanEnv(GameConfig(player_names=["Alice", "Bob", "Cara"], seed=5))
    _auto_setup(env)
    game = env.game
    game.phase = Phase.MAIN
    game.has_rolled = True
    alice = game.players[0]
    board = game.board
    # Remove any accidental port bonuses from initial placements.
    for corner_id in list(alice.settlements):
        board.corners[corner_id].port = None

    # Base bank trade (4:1)
    alice.resources[Resource.BRICK] = 4
    actions = env.legal_actions()
    bank_actions = [
        action for action in actions if action.type == ActionType.TRADE_BANK
    ]
    base_ratios = [
        action.payload["ratio"]
        for action in bank_actions
        if action.payload["give"] == "brick"
    ]
    assert base_ratios and min(base_ratios) == 4

    # Attach Alice to a brick port for 2:1 ratio.
    port_corner = next(
        corner_id
        for corner_id, corner in board.corners.items()
        if corner.port and corner.port.resource == Resource.BRICK
    )
    board.corners[port_corner].owner = alice.name
    board.corners[port_corner].building = "settlement"
    alice.settlements.add(port_corner)
    alice.resources[Resource.BRICK] = 2

    actions = env.legal_actions()
    bank_actions = [
        action for action in actions if action.type == ActionType.TRADE_BANK
    ]
    assert any(action.payload["give"] == "brick" and action.payload["ratio"] == 2 for action in bank_actions)


def test_player_trade_actions_available() -> None:
    env = CatanEnv(GameConfig(player_names=["Alice", "Bob", "Cara"], seed=11))
    _auto_setup(env)
    game = env.game
    game.phase = Phase.MAIN
    game.has_rolled = True
    alice = game.player_by_name("Alice")
    bob = game.player_by_name("Bob")
    alice.resources[Resource.WOOL] = 1
    bob.resources[Resource.ORE] = 1

    actions = env.legal_actions()
    trade_actions = [
        action for action in actions if action.type == ActionType.TRADE_PLAYER
    ]
    assert trade_actions, "Expected player trade actions"
    assert any(
        action.payload["target"] == "Bob"
        and action.payload["offer"] == {"wool": 1}
        and action.payload["request"] == {"ore": 1}
        for action in trade_actions
    )
