from __future__ import annotations

import uuid

from flask import Flask, jsonify, redirect, render_template, request, url_for

from blokus_gym.core.game import BlokusGame
from blokus_gym.core.pieces import STANDARD_PIECES, PieceSet
from blokus_ui.session import GameSession
from blokus_ui.store import RunStore

app = Flask(__name__)

SESSIONS: dict[str, GameSession] = {}
store = RunStore()


@app.route("/")
def index():
    runs = store.list_runs()
    return render_template("index.html", runs=runs)


@app.route("/game/new", methods=["POST"])
def new_game():
    board_size = int(request.form.get("board_size", 20))
    num_players = int(request.form.get("num_players", 4))
    human_player = int(request.form.get("human_player", 0))
    bot_type = request.form.get("bot_type", "greedy")
    bot_seed = int(request.form.get("bot_seed", 42))

    session = GameSession(
        board_size=board_size,
        num_players=num_players,
        human_player=human_player,
        bot_type=bot_type,
        bot_seed=bot_seed,
    )
    session_id = str(uuid.uuid4())
    SESSIONS[session_id] = session

    return redirect(url_for("game_page", session_id=session_id))


@app.route("/game/<session_id>")
def game_page(session_id):
    session = SESSIONS.get(session_id)
    if session is None:
        return "Game session not found", 404
    return render_template(
        "game.html",
        session_id=session_id,
        board_size=session.board_size,
    )


@app.route("/api/game/<session_id>/state")
def game_state(session_id):
    session = SESSIONS.get(session_id)
    if session is None:
        return jsonify({"error": "Session not found"}), 404
    return jsonify(session.get_state())


@app.route("/api/game/<session_id>/placements")
def game_placements(session_id):
    session = SESSIONS.get(session_id)
    if session is None:
        return jsonify({"error": "Session not found"}), 404
    piece_id = int(request.args.get("piece_id", 0))
    placements = session.get_valid_placements(piece_id)
    return jsonify({"placements": placements})


@app.route("/api/game/<session_id>/move", methods=["POST"])
def game_move(session_id):
    session = SESSIONS.get(session_id)
    if session is None:
        return jsonify({"error": "Session not found"}), 404
    action = int(request.json.get("action", -1))
    result = session.apply_human_action(action)
    return jsonify(result)


@app.route("/api/game/<session_id>/save", methods=["POST"])
def save_game(session_id):
    session = SESSIONS.get(session_id)
    if session is None:
        return jsonify({"error": "Session not found"}), 404
    run_id = store.save(session)
    return jsonify({"success": True, "run_id": run_id})


@app.route("/runs")
def runs_page():
    runs = store.list_runs()
    return render_template("index.html", runs=runs)


@app.route("/replay/<run_id>")
def replay_page(run_id):
    run_data = store.load(run_id)
    if run_data is None:
        return "Run not found", 404

    config = run_data["data"]["config"]
    move_history = run_data["data"]["move_history"]
    statistics = run_data["data"].get("statistics", {})

    game = BlokusGame(
        board_size=config["board_size"],
        pieces=PieceSet(STANDARD_PIECES),
        num_players=config["num_players"],
    )
    game.reset()

    states = [{
        "board": game.board.grid.tolist(),
        "current_player": game.current_player,
        "scores": game.get_scores(),
    }]

    for move in move_history:
        game.play_move(move["player_idx"], move["action"])
        game.next_player()
        states.append({
            "board": game.board.grid.tolist(),
            "current_player": game.current_player,
            "scores": game.get_scores(),
        })

    replay_data = {
        "states": states,
        "moves": move_history,
        "config": config,
        "statistics": statistics,
    }

    return render_template(
        "replay.html",
        run_id=run_id,
        board_size=config["board_size"],
        total_moves=len(move_history),
        replay_data=replay_data,
    )


@app.route("/runs/<run_id>/delete", methods=["POST"])
def delete_run(run_id):
    store.delete(run_id)
    return redirect(url_for("index"))


if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000, debug=True)
