"""Routes: admin games"""
from datetime import datetime
from flask import flash, redirect, render_template, request, url_for

from nexora.config import IMAGE_ROOT
from nexora.core import app
from nexora.database.connection import clear_perf_caches, execute, query
from nexora.services.uploads import delete_upload, process_image_upload, sanitize_folder_name
from nexora.services.pricing import form_member_bounds
from nexora.services.qualifiers import save_qualifier_rows
from nexora.security.permissions import (
    admin_required,
    forbidden_response,
    has_permission,
    permission_required,
)


@app.route("/admin/games", methods=["GET", "POST"])
@admin_required
@permission_required("games_view")
def admin_games():
    if request.method == "POST":
        if not has_permission("games_create"):
            return forbidden_response()
        individual_price = request.form.get("individual_price", "").strip()
        group_price = request.form.get("group_price", "").strip()
        per_size_prices = [request.form.get(f"price_for_{size}", "").strip() for size in (2, 3, 4)]
        is_free_new = bool(request.form.get("is_free"))
        if not is_free_new and not individual_price and not group_price and not any(per_size_prices):
            flash("Add at least one price or mark the game as Free Entry.", "danger")
            return redirect(url_for("admin_games"))
        min_members, max_members = form_member_bounds()
        image, image_error = process_image_upload(
            request.files.get("image"), category="games", game_title=request.form["title"]
        )
        if image_error:
            flash(image_error, "danger")
            return redirect(url_for("admin_games"))
        # Canonical per-game folders exist as soon as a game is created
        game_folder = sanitize_folder_name(request.form["title"])
        if game_folder:
            try:
                (IMAGE_ROOT / "Games" / game_folder).mkdir(parents=True, exist_ok=True)
                (IMAGE_ROOT / "Registrations" / game_folder).mkdir(parents=True, exist_ok=True)
            except OSError:
                pass
        new_game_id = execute(
            """
INSERT INTO games
            (title, platform, individual_price, group_price, image, reg_from, reg_to,
             discount_label, individual_old_price, group_old_price,
             min_members, max_members,
             price_for_2, price_for_3, price_for_4,
             old_price_2, old_price_3, old_price_4,
             discount_from, discount_to, discount_pct, discount_type, active, created_at,
              qualifiers_enabled, qualifier_fee_type, qualifier_package_size,
             qualifier_package_fee, qualifier_additional_fee, team_label, registration_label, is_free, venue, venue_address, event_date, event_time, event_end_time)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
            """,
            (
                request.form["title"].strip(),
                request.form["platform"].strip(),
                individual_price,
                group_price,
                image or "",
                request.form.get("reg_from", "").strip(),
                request.form.get("reg_to", "").strip(),
                request.form.get("discount_label", "").strip(),
                "",
                "",
                str(min_members),
                str(max_members),
                request.form.get("price_for_2", "").strip(),
                request.form.get("price_for_3", "").strip(),
                request.form.get("price_for_4", "").strip(),
                "",
                "",
                "",
                request.form.get("discount_from", "").strip(),
                request.form.get("discount_to", "").strip(),
                request.form.get("discount_pct", "").strip(),
                request.form.get("discount_type", "percentage").strip(),
                1 if request.form.get("active") else 0,
                datetime.now().isoformat(timespec="seconds"),
                "1" if request.form.get("qualifiers_enabled") else "0",
                request.form.get("qualifier_fee_type", "separate").strip() or "separate",
                str(max(1, int(request.form.get("qualifier_package_size", 1) or 1))),
                request.form.get("qualifier_package_fee", "").strip(),
                request.form.get("qualifier_additional_fee", "").strip(),
                request.form.get("team_label", "").strip(),
                request.form.get("registration_label", "").strip(),
                "1" if request.form.get("is_free") else "0",
                request.form.get("venue", "").strip(),
                request.form.get("venue_address", "").strip(),
                request.form.get("event_date", "").strip(),
                request.form.get("event_time", "").strip(),
                request.form.get("event_end_time", "").strip(),
            ),
        )

        # Save qualifier rows
        if request.form.get("qualifiers_enabled"):
            qualifier_count = save_qualifier_rows(new_game_id)
            if qualifier_count == 0:
                flash("Warning: Qualifiers enabled but no qualifier rounds added. Please add at least one qualifier.", "warning")

        clear_perf_caches()
        flash("Game card created.", "success")
        return redirect(url_for("admin_games"))
    games = query("SELECT * FROM games WHERE deleted_at = '' ORDER BY id DESC")
    # Attach qualifiers to each game for the template
    games_list = []
    for game in games:
        g = dict(game)
        game_qualifiers = query(
            "SELECT * FROM qualifiers WHERE game_id = ? ORDER BY qualifier_number, sort_order, id",
            (game["id"],),
        )
        g["qualifier_list"] = [dict(q) for q in game_qualifiers]
        games_list.append(g)
    return render_template("admin_games.html", games=games_list)


@app.route("/admin/games/<int:game_id>/toggle", methods=["POST"])
@admin_required
@permission_required("games_update")
def toggle_game(game_id):
    execute("UPDATE games SET active = 1 - active WHERE id = ?", (game_id,))
    clear_perf_caches()
    flash("Game visibility updated.", "success")
    return redirect(url_for("admin_games"))


@app.route("/admin/games/<int:game_id>/update", methods=["POST"])
@admin_required
@permission_required("games_update")
def update_game(game_id):
    existing = query("SELECT * FROM games WHERE id = ?", (game_id,), one=True)
    if not existing:
        flash("Game not found.", "danger")
        return redirect(url_for("admin_games"))
    individual_price = request.form.get("individual_price", "").strip()
    group_price = request.form.get("group_price", "").strip()
    per_size_prices = [request.form.get(f"price_for_{size}", "").strip() for size in (2, 3, 4)]
    is_free_new = bool(request.form.get("is_free"))
    if not is_free_new and not individual_price and not group_price and not any(per_size_prices):
        flash("Add at least one price or mark the game as Free Entry.", "danger")
        return redirect(url_for("admin_games"))
    min_members, max_members = form_member_bounds()

    new_title = request.form["title"].strip()
    image, image_error = process_image_upload(
        request.files.get("image"), category="games", game_title=new_title
    )
    if image_error:
        flash(image_error, "danger")
        return redirect(url_for("admin_games"))
    if image and existing["image"]:
        delete_upload(existing["image"])
    # Keep per-game folders present when a game is renamed/retitled
    game_folder = sanitize_folder_name(new_title)
    if game_folder:
        try:
            (IMAGE_ROOT / "Games" / game_folder).mkdir(parents=True, exist_ok=True)
            (IMAGE_ROOT / "Registrations" / game_folder).mkdir(parents=True, exist_ok=True)
        except OSError:
            pass

    execute(
        """
        UPDATE games SET title = ?, platform = ?, individual_price = ?, group_price = ?,
        image = ?, reg_from = ?, reg_to = ?, discount_label = ?, individual_old_price = ?,
        group_old_price = ?, min_members = ?, max_members = ?,
        price_for_2 = ?, price_for_3 = ?, price_for_4 = ?,
        old_price_2 = ?, old_price_3 = ?, old_price_4 = ?,
        discount_from = ?, discount_to = ?, discount_pct = ?, discount_type = ?,
        active = ?, qualifiers_enabled = ?, qualifier_fee_type = ?, qualifier_package_size = ?,
        qualifier_package_fee = ?, qualifier_additional_fee = ?, team_label = ?, registration_label = ?, is_free = ?,
        venue = ?, venue_address = ?, event_date = ?, event_time = ?, event_end_time = ?
        WHERE id = ?
        """,
        (
            new_title, request.form["platform"].strip(), individual_price, group_price,
            image or existing["image"], request.form.get("reg_from", "").strip(), request.form.get("reg_to", "").strip(),
            request.form.get("discount_label", "").strip(), "", "",
            str(min_members), str(max_members),
            request.form.get("price_for_2", "").strip(), request.form.get("price_for_3", "").strip(), request.form.get("price_for_4", "").strip(),
            "", "", "", request.form.get("discount_from", "").strip(), request.form.get("discount_to", "").strip(), request.form.get("discount_pct", "").strip(), request.form.get("discount_type", "percentage").strip(),
            1 if request.form.get("active") else 0, "1" if request.form.get("qualifiers_enabled") else "0",
            request.form.get("qualifier_fee_type", "separate").strip() or "separate",
            str(max(1, int(request.form.get("qualifier_package_size", 1) or 1))),
            request.form.get("qualifier_package_fee", "").strip(), request.form.get("qualifier_additional_fee", "").strip(),
            request.form.get("team_label", "").strip(), request.form.get("registration_label", "").strip(),
            "1" if request.form.get("is_free") else "0",
            request.form.get("venue", "").strip(), request.form.get("venue_address", "").strip(), request.form.get("event_date", "").strip(), request.form.get("event_time", "").strip(), request.form.get("event_end_time", "").strip(),
            game_id,
        )
    )

    if request.form.get("qualifiers_enabled"):
        qualifier_count = save_qualifier_rows(game_id)
        if qualifier_count == 0:
            flash("Warning: Qualifiers enabled but no qualifier rounds added.", "warning")

    # When qualifiers are disabled, keep the qualifier rows in the DB so their
    # IDs stay stable. They are simply ignored because qualifiers_enabled = 0
    # (tickets/QRs check that flag). Re-enabling reuses the same IDs.
    clear_perf_caches()
    flash("Game card updated.", "success")
    return redirect(url_for("admin_games"))


@app.route("/admin/games/<int:game_id>/delete", methods=["POST"])
@admin_required
@permission_required("games_delete")
def delete_game(game_id):
    row = query("SELECT * FROM games WHERE id = ?", (game_id,), one=True)
    if not row:
        flash("Game not found.", "danger")
        return redirect(url_for("admin_games"))

    reg_count = query("SELECT COUNT(*) AS c FROM registrations WHERE game_id = ?", (game_id,), one=True)["c"]
    execute(
        "UPDATE games SET deleted_at = ?, active = 0 WHERE id = ?",
        (datetime.now().isoformat(timespec="seconds"), game_id),
    )
    clear_perf_caches()
    flash(
        f'"{row["title"]}" was removed from the site. '
        + (f"Its {reg_count} registration(s) and ticket history are preserved." if reg_count else "No registration records were deleted."),
        "success",
    )
    return redirect(url_for("admin_games"))
