import random

win_states = [
    (0, 1, 2), (3, 4, 5), (6, 7, 8),  # horizontal
    (0, 3, 6), (1, 4, 7), (2, 5, 8),  # vertical
    (0, 4, 8), (2, 4, 6)  # diagonal
]


def Terminal(state: list):
    for win_state in win_states:
        if all(state[i] == "O" for i in win_state) or all(state[i] == "X" for i in win_state):
            return True
    if state.count(" ") == 0:
        return True
    else:
        return False


def Value(state):
    for win_state in win_states:
        if all(state[i] == "O" for i in win_state):
            return -1
        elif all(state[i] == "X" for i in win_state):
            return 1
    if state.count(" ") == 0:
        return 0


def Player(state: list):
    if state.count("X") == state.count("O"):
        return "X"
    else:
        return "O"


def Actions(state):
    indexes = []
    for i in range(9):
        if state[i] == " ":
            indexes.append(i)
    return indexes


def Result(state, index, player):
    state[index] = player
    return state


def Minimax(state):
    if Terminal(state):
        return Value(state)
    if Player(state) == "X":
        value = -9999
        for a in Actions(state):
            value = max(value, Minimax(Result(state.copy(), a, "X")))
        return value

    elif Player(state) == "O":
        value = 9999
        for a in Actions(state):
            value = min(value, Minimax(Result(state.copy(), a, "O")))
        return value


def aiO(state):
    best_score = float('inf')
    best_move = None
    for move in Actions(state):
        state[move] = 'O'
        score = Minimax(state)
        state[move] = ' '
        if score < best_score:
            best_score = score
            best_move = move
    return best_move


def aiX(state):
    best_score = float('-inf')
    best_move = None
    for move in Actions(state):
        state[move] = 'X'
        score = Minimax(state)
        state[move] = ' '
        if score > best_score:
            best_score = score
            best_move = move
    return best_move


def aiRandom(state):
    return random.choice(Actions(state))
