import os
import re
from flask import Flask, render_template_string, request, redirect, url_for, session, jsonify, flash

app = Flask(__name__)
app.secret_key = "tactical-battleship-spy-game-encryption-auth-key-v5"

ADMIN_PASSWORD = "spyadmin"  # Override access password

# 24 labeled islands + 1 unlabeled island mapped from your visual grid
ISLANDS = [
    "Alsgard", "Dunfjord", "Farnhamn", "Frostfjord", "Galdsund",
    "Grimstad", "Grytholm", "Isenhamn", "Kielvik", "Krogsund",
    "Norderwall", "Nordvik", "Osterby", "Runasund", "Saltvik",
    "Skargard", "Skarvik", "Stormhamn", "Svartvik", "Sydhavn",
    "Tarnby", "Vardhamn", "Vargby", "Vestvik (Unlabeled)", "Vindholm"
]

MAP_CONNECTIONS = [
    ("Nordvik", ["Stormhamn", "Tarnby", "Vardhamn"]),
    ("Stormhamn", ["Nordvik", "Tarnby", "Vestvik (Unlabeled)"]),
    ("Vestvik (Unlabeled)", ["Stormhamn", "Vargby"]),
    ("Vargby", ["Vestvik (Unlabeled)", "Alsgard", "Tarnby"]),
    ("Alsgard", ["Vargby", "Galdsund", "Grytholm"]),
    ("Tarnby", ["Nordvik", "Stormhamn", "Vargby", "Grytholm", "Frostfjord"]),
    ("Grytholm", ["Alsgard", "Tarnby", "Galdsund", "Sydhavn"]),
    ("Galdsund", ["Alsgard", "Grytholm", "Sydhavn", "Norderwall"]),
    ("Frostfjord", ["Tarnby", "Sydhavn", "Grimstad"]),
    ("Sydhavn", ["Grytholm", "Galdsund", "Frostfjord", "Skarvik"]),
    ("Grimstad", ["Frostfjord", "Skarvik", "Dunfjord", "Vindholm"]),
    ("Skarvik", ["Sydhavn", "Grimstad", "Svartvik", "Isenhamn"]),
    ("Dunfjord", ["Grimstad", "Vindholm"]),
    ("Vindholm", ["Grimstad", "Dunfjord", "Vardhamn", "Osterby"]),
    ("Vardhamn", ["Nordvik", "Vindholm", "Osterby", "Farnhamn"]),
    ("Norderwall", ["Galdsund", "Svartvik", "Runasund"]),
    ("Svartvik", ["Skarvik", "Norderwall", "Runasund"]),
    ("Runasund", ["Norderwall", "Svartvik", "Krogsund"]),
    ("Isenhamn", ["Skarvik", "Kielvik", "Saltvik"]),
    ("Kielvik", ["Isenhamn", "Saltvik", "Krogsund"]),
    ("Krogsund", ["Kielvik", "Runasund", "Saltvik", "Skargard"]),
    ("Saltvik", ["Isenhamn", "Kielvik", "Krogsund", "Osterby"]),
    ("Osterby", ["Vindholm", "Vardhamn", "Saltvik", "Farnhamn"]),
    ("Farnhamn", ["Vardhamn", "Osterby", "Skargard"]),
    ("Skargard", ["Krogsund", "Farnhamn"])
]

def get_initial_state():
    return {
        "turn": 1,
        "phase": "SIGNAL",  # "SIGNAL" (Phase 1), "MOVE" (Phase 2), "SHOOT" (Phase 3), "REVEAL" (Phase 4)
        "teams": {
            "team_1": {
                "id": "team_1",
                "display_name": "Team Alpha",
                "points": 3,
                "current_msg": "",
                "current_moves_spent": 0,
                "current_shot_team": "",
                "current_shot_island": "",
                "phase_signal_submitted": False,
                "phase_move_submitted": False,
                "phase_shoot_submitted": False
            },
            "team_2": {
                "id": "team_2",
                "display_name": "Team Bravo",
                "points": 3,
                "current_msg": "",
                "current_moves_spent": 0,
                "current_shot_team": "",
                "current_shot_island": "",
                "phase_signal_submitted": False,
                "phase_move_submitted": False,
                "phase_shoot_submitted": False
            },
            "team_3": {
                "id": "team_3",
                "display_name": "Team Charlie",
                "points": 3,
                "current_msg": "",
                "current_moves_spent": 0,
                "current_shot_team": "",
                "current_shot_island": "",
                "phase_signal_submitted": False,
                "phase_move_submitted": False,
                "phase_shoot_submitted": False
            },
            "team_4": {
                "id": "team_4",
                "display_name": "Team Delta",
                "points": 3,
                "current_msg": "",
                "current_moves_spent": 0,
                "current_shot_team": "",
                "current_shot_island": "",
                "phase_signal_submitted": False,
                "phase_move_submitted": False,
                "phase_shoot_submitted": False
            }
        },
        "history": []
    }

game_state = get_initial_state()

def validate_spy_msg(msg):
    return bool(re.match(r"^[a-z]{6}$", msg))

@app.before_request
def check_admin_access():
    if request.path.startswith("/admin") and not request.path.endswith("/login") and not request.path.endswith("/action") and not "add_team" in request.path and not "remove_team" in request.path:
        if not session.get("is_admin"):
            flash("Admin session missing. Please re-authenticate override.", "danger")
            return redirect(url_for("home"))

# --- BASE THEME (HTML & CSS optimized for high-contrast dark mode) ---
COMMON_LAYOUT_START = """
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Naval Decryption Network</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
    <style>
        :root {
            --term-green: #39ff14;
            --term-bg: #070a0f;
            --term-card: #0f172a;
            --term-border: #334155;
            --term-glow: rgba(57, 255, 20, 0.15);
        }
        body {
            background-color: var(--term-bg);
            color: #f1f5f9 !important; /* Forces high-contrast light grey for general text */
            font-family: 'Courier New', Courier, monospace;
        }
        .navbar-tactical {
            background-color: #020617;
            border-bottom: 2px solid var(--term-green);
            box-shadow: 0 0 12px var(--term-glow);
        }
        .card-tactical {
            background-color: var(--term-card);
            border: 1px solid var(--term-border);
            box-shadow: 0 5px 15px rgba(0,0,0,0.6);
        }
        .card-tactical-header {
            background-color: #1e293b;
            border-bottom: 2px solid var(--term-green);
            color: var(--term-green) !important;
            font-weight: bold;
            text-shadow: 0 0 4px var(--term-glow);
        }
        .terminal-console {
            background-color: #020617;
            border: 1px solid var(--term-green);
            color: var(--term-green) !important;
            padding: 15px;
            border-radius: 6px;
            box-shadow: inset 0 0 10px rgba(57, 255, 20, 0.15);
            max-height: 400px;
            overflow-y: auto;
        }
        .btn-tactical {
            background-color: transparent;
            border: 1px solid var(--term-green);
            color: var(--term-green) !important;
            font-weight: bold;
            transition: all 0.2s ease-in-out;
        }
        .btn-tactical:hover {
            background-color: var(--term-green);
            color: var(--term-bg) !important;
            box-shadow: 0 0 15px var(--term-green);
        }
        .btn-tactical-danger {
            background-color: transparent;
            border: 1px solid #f87171;
            color: #f87171 !important;
            font-weight: bold;
            transition: all 0.2s ease-in-out;
        }
        .btn-tactical-danger:hover {
            background-color: #f87171;
            color: #ffffff !important;
            box-shadow: 0 0 15px #f87171;
        }
        .text-green {
            color: var(--term-green) !important;
        }
        .badge-ready {
            background-color: rgba(57, 255, 20, 0.2);
            border: 1px solid var(--term-green);
            color: var(--term-green) !important;
        }
        .badge-pending {
            background-color: rgba(245, 158, 11, 0.2);
            border: 1px solid #f59e0b;
            color: #f59e0b !important;
        }
        /* Custom overrides to fix readability of dark text in dark mode */
        .text-muted, .form-text, p.text-muted {
            color: #cbd5e1 !important; /* Lighter slate grey for distinct readability on dark backgrounds */
        }
        .form-control, .form-select {
            background-color: #1e293b !important;
            color: #f1f5f9 !important;
            border: 1px solid #475569 !important;
        }
        .form-control::placeholder {
            color: #94a3b8 !important;
        }
        /* Ensure select dropdown options remain highly visible across systems */
        select option {
            background-color: #0f172a !important;
            color: #f1f5f9 !important;
        }
        .table {
            color: #f1f5f9 !important;
        }
        .alert-success {
            background-color: rgba(16, 185, 129, 0.2) !important;
            color: #34d399 !important;
            border: 1px solid #10b981 !important;
        }
        .alert-danger {
            background-color: rgba(239, 68, 68, 0.2) !important;
            color: #f87171 !important;
            border: 1px solid #f87171 !important;
        }
        label, th {
            color: #f1f5f9 !important;
        }
    </style>
</head>
<body>
    <nav class="navbar navbar-dark navbar-tactical mb-4">
        <div class="container-fluid">
            <span class="navbar-brand text-green mb-0 h1">NAVAL DECRYPTION SYSTEM V4.0</span>
            <div class="d-flex align-items-center">
                {% if session.get('team') %}
                    {% if session['team'] in game_state.teams %}
                    <span class="text-white me-3">Squadron: <strong class="text-green">{{ game_state.teams[session['team']].display_name }}</strong></span>
                    {% endif %}
                    <a href="/logout" class="btn btn-sm btn-outline-secondary text-white border-secondary">Disconnect</a>
                {% elif session.get('is_admin') %}
                    <span class="text-danger me-3"><strong>[COMMANDER MODE]</strong></span>
                    <a href="/logout" class="btn btn-sm btn-outline-danger">Exit Override</a>
                {% endif %}
            </div>
        </div>
    </nav>
    <div class="container-fluid px-md-5">
        {% with messages = get_flashed_messages(with_categories=true) %}
            {% if messages %}
                {% for category, message in messages %}
                    <div class="alert alert-{{ 'danger' if category == 'error' else 'success' }} mb-4" role="alert">
                        <strong>LOG:</strong> {{ message }}
                    </div>
                {% endfor %}
            {% endif %}
        {% endwith %}
"""

COMMON_LAYOUT_END = """
    </div>
    <footer class="text-center mt-5 mb-4 text-muted" style="font-size: 0.8rem;">
        Encryption Training Framework • Classified Material • Operational Clearance Required
    </footer>
</body>
</html>
"""

# --- ROUTE HANDLERS ---

@app.route("/")
def home():
    if session.get("is_admin"):
        return redirect(url_for("admin_dashboard"))
    if session.get("team"):
        # Edge case: If team was deleted by admin
        if session["team"] not in game_state["teams"]:
            session.clear()
            flash("Your team was decommissioned by the Commander.", "danger")
            return redirect(url_for("home"))
        return render_client_dashboard()
    
    login_html = """
    <div class="row justify-content-center mt-5">
        <div class="col-md-8 text-center">
            <pre class="text-green text-center d-none d-md-block" style="font-size: 0.75rem; line-height: 1.1;">
    ██████╗  ██████╗  ██████╗  ██████╗     ███████╗██████╗ ██╗   ██╗
    ██╔══██╗██╔═══██╗██╔═══██╗██╔════╝     ██╔════╝██╔══██╗╚██╗ ██╔╝
    ██████╔╝██║   ██║██║   ██║██║  ███╗    ███████╗██████╔╝ ╚████╔╝ 
    ██╔═══╝ ██║   ██║██║   ██║██║   ██║    ╚════██║██╔═══╝   ╚██╔╝  
    ██║     ╚██████╔╝╚██████╔╝╚██████╔╝    ███████║██║        ██║   
    ╚═╝      ╚═════╝  ╚═════╝  ╚═════╝     ╚══════╝╚═╝        ╚═╝   
            </pre>
            <h1 class="text-green mb-4">OPERATION: SPY-SIGNAL</h1>
            <p class="text-muted">Welcome to the Tactical Encryption Command Network. Please select your team station or input Commander coordinates.</p>
        </div>
    </div>
    <div class="row justify-content-center mt-3">
        <div class="col-md-5 mb-4">
            <div class="card card-tactical h-100">
                <div class="card-header card-tactical-header">TEAM STATION ACCESS</div>
                <div class="card-body d-flex flex-column justify-content-between">
                    <form action="/select_team" method="POST">
                        <div class="mb-4">
                            <label class="form-label text-green">Select Team Designation</label>
                            <select name="team_id" class="form-select bg-dark text-white border-secondary" required>
                                <option value="" disabled selected>Choose team...</option>
                                {% for tid, tdata in game_state.teams.items() %}
                                <option value="{{ tid }}">{{ tdata.display_name }} ({{ tdata.points }} MP)</option>
                                {% endfor %}
                            </select>
                        </div>
                        <button type="submit" class="btn btn-tactical w-100">Establish Link</button>
                    </form>
                </div>
            </div>
        </div>
        <div class="col-md-5 mb-4">
            <div class="card card-tactical h-100">
                <div class="card-header card-tactical-header text-danger" style="border-bottom-color: #f87171;">COMMANDER OVERRIDE</div>
                <div class="card-body">
                    <form action="/admin/login" method="POST">
                        <div class="mb-4">
                            <label class="form-label text-danger">Override Access Password</label>
                            <input type="password" name="password" class="form-control bg-dark text-white border-secondary" placeholder="Enter Admin Password..." required>
                        </div>
                        <button type="submit" class="btn btn-tactical-danger w-100">Authenticate Override</button>
                    </form>
                </div>
            </div>
        </div>
    </div>
    """
    return render_template_string(COMMON_LAYOUT_START + login_html + COMMON_LAYOUT_END, game_state=game_state)

@app.route("/select_team", methods=["POST"])
def select_team():
    team_id = request.form.get("team_id")
    if team_id in game_state["teams"]:
        session["team"] = team_id
        flash(f"Secure link initialized for {game_state['teams'][team_id]['display_name']}.", "success")
    return redirect(url_for("home"))

@app.route("/logout")
def logout():
    session.clear()
    flash("Disconnected session cleanly.", "success")
    return redirect(url_for("home"))

# --- CLIENT LOGIC ---

def render_client_dashboard():
    current_team_id = session["team"]
    team = game_state["teams"][current_team_id]
    
    client_html = """
    <div class="row">
        <!-- Main Panel: Planning & Controls -->
        <div class="col-lg-8 mb-4">
            <div class="card card-tactical mb-4">
                <div class="card-header card-tactical-header d-flex justify-content-between align-items-center">
                    <span>SQUADRON CONSOLE [{{ team.display_name }}]</span>
                    <span class="badge bg-dark text-green border border-success">TURN {{ game_state.turn }}</span>
                </div>
                <div class="card-body">
                    <!-- Global Phase Indicator -->
                    <div class="p-3 mb-4 rounded shadow-sm" style="background-color: #020617; border: 1px solid var(--term-border);">
                        <h5 class="text-green mb-1">CURRENT BROADCAST PHASE:</h5>
                        {% if game_state.phase == 'SIGNAL' %}
                            <span class="text-white fs-4">[PHASE 1] Spy Signal Transmission</span>
                            <p class="text-muted mt-2 mb-0">The spy on your team must broadcast a 6-character encrypted signal designating which of your ships is betrayed. Other members do not submit anything yet.</p>
                        {% elif game_state.phase == 'MOVE' %}
                            <span class="text-cyan fs-4" style="color: #00f0ff !important;">[PHASE 2] Decryption and Ship Movement</span>
                            <p class="text-muted mt-2 mb-0">Examine the spy message logs in your terminal on the right. Decrypt your team's code and spend movement points (MP) to relocate the ship away from danger.</p>
                        {% elif game_state.phase == 'SHOOT' %}
                            <span class="text-warning fs-4">[PHASE 3] Shell Target Acquisition</span>
                            <p class="text-muted mt-2 mb-0">The fleet is in firing position. Select exactly one opposing squadron and designate your shell impact coordinates.</p>
                        {% elif game_state.phase == 'REVEAL' %}
                            <span class="text-green fs-4">[PHASE 4] Tactical Reveal</span>
                            <p class="text-muted mt-2 mb-0">Commander has authorized system decryptions. Assess the results and update your physical boards.</p>
                        {% endif %}
                    </div>

                    <!-- Highlighted Bombardment Detection Box (Only in Phase 4: Reveal) -->
                    {% if game_state.phase == 'REVEAL' %}
                        <div class="p-3 mb-4 rounded border border-danger" style="background-color: rgba(239, 68, 68, 0.12);">
                            <span class="text-danger font-weight-bold" style="color: #f87171 !important;">>>> INCOMING BOMBARDMENT ALERTS DETECTED ON YOUR SQUADRON:</span><br>
                            {% set ns = namespace(has_incoming=False) %}
                            {% for tid, tdata in game_state.teams.items() %}
                                {% if tdata.current_shot_team == team.id %}
                                    {% set ns.has_incoming = True %}
                                    <span class="text-white">>>> [ALERT] <strong class="text-danger" style="color: #f87171 !important;">{{ tdata.display_name }}</strong> TARGETED YOUR NODE: <strong class="text-warning">{{ tdata.current_shot_island }}</strong></span><br>
                                {% endif %}
                            {% endfor %}
                            {% if not ns.has_incoming %}
                                <span class="text-green">>>> [SECURE] SQUADRON FLANK SECURE. NO INCOMING ORDNANCE TARGETED YOUR NODES FOR THIS TURN.</span><br>
                            {% endif %}
                        </div>
                    {% endif %}

                    <!-- Highlighted Intel Decryption Box while choosing Target (Only in Phase 3: Shoot) -->
                    {% if game_state.phase == 'SHOOT' and not team.phase_shoot_submitted %}
                        <div class="p-3 mb-4 rounded border border-warning" style="background-color: rgba(245, 158, 11, 0.08);">
                            <span class="text-warning font-weight-bold">>>> INTERCEPTED SPY SIGNALS (ALL ACTIVE SQUADRONS):</span><br>
                            {% for tid, tdata in game_state.teams.items() %}
                                <span class="text-white">>>> [{{ tdata.display_name }}] Intercepted Signal: <strong class="text-green" style="text-shadow: 0 0 5px rgba(57,255,20,0.5);">{{ tdata.current_msg or 'No signal transmitted' }}</strong></span><br>
                            {% endfor %}
                            <div class="form-text mt-2 text-white">Determine which coordinates have been leaked to trace the positions of adversary vessels before firing.</div>
                        </div>
                    {% endif %}

                    <!-- Client Interaction Form based on current phase -->
                    {% if game_state.phase == 'SIGNAL' %}
                        {% if team.phase_signal_submitted %}
                            <div class="text-center p-4 terminal-console">
                                <h4 class="text-green">[TRANSMISSION QUEUED AND SECURED]</h4>
                                <p class="mb-0 text-muted mt-2">The spy's signal has been securely queued. Awaiting other squadrons. The commander will unlock Phase 2 (Movement) shortly.</p>
                                <div class="mt-3 fs-6">
                                    Your spy's signal code: <strong class="text-white">"{{ team.current_msg }}"</strong>
                                </div>
                            </div>
                        {% else %}
                            <h4 class="text-green mb-3">Broadcast Spy Signal</h4>
                            <form action="/submit_signal" method="POST">
                                <div class="mb-3">
                                    <label class="form-label text-green">SPY SIGNAL CODE (6 lowercase characters)</label>
                                    <input type="text" name="spy_msg" maxlength="6" minlength="6" pattern="[a-z]{6}" class="form-control" placeholder="e.g., xzyvqt" required autocomplete="off" style="text-transform: lowercase;">
                                    <div class="form-text">Must be exactly 6 English characters (a-z). This corresponds to the secret ship node betrayed by your spy.</div>
                                </div>
                                <button type="submit" class="btn btn-tactical w-100 mt-2">Securely Broadcast Signal</button>
                            </form>
                        {% endif %}

                    {% elif game_state.phase == 'MOVE' %}
                        {% if team.phase_move_submitted %}
                            <div class="text-center p-4 terminal-console">
                                <h4 class="text-green">[MOVEMENT MANEUVERS COMMITTED]</h4>
                                <p class="mb-0 text-muted mt-2">Maneuver instructions successfully sent. Waiting for opposing squadrons. The Commander will trigger Target Acquisition next.</p>
                                <div class="mt-3 fs-6">
                                    Point budget spent: <strong class="text-white">{{ team.current_moves_spent }} MP</strong>
                                </div>
                            </div>
                        {% else %}
                            <h4 class="text-green mb-3">Execute Strategic Moves</h4>
                            <form action="/submit_move" method="POST">
                                <div class="mb-3">
                                    <label class="form-label text-green">CHOOSE SHIP MOVEMENT (Budget: {{ team.points }} MP)</label>
                                    <input type="number" name="moves_spent" min="0" max="{{ team.points }}" value="0" class="form-control" required>
                                    <div class="form-text">Each point spent allows you to move one ship for one step along connected lines on your physical board. You can select 0 to save points. Unspent points carry over.</div>
                                </div>
                                <button type="submit" class="btn btn-tactical w-100 mt-2">Commit Movement maneuvers</button>
                            </form>
                        {% endif %}

                    {% elif game_state.phase == 'SHOOT' %}
                        {% if team.phase_shoot_submitted %}
                            <div class="text-center p-4 terminal-console">
                                <h4 class="text-warning">[WEAPON CONTROLS COMMITTED]</h4>
                                <p class="mb-0 text-muted mt-2">Locked targets: <strong class="text-white">{{ game_state.teams[team.current_shot_team].display_name if team.current_shot_team else "None" }}</strong> at <strong class="text-white">{{ team.current_shot_island }}</strong>.</p>
                                <p class="text-muted mt-2">Awaiting other squadrons. The commander will reveal all shell impact sites shortly.</p>
                            </div>
                        {% else %}
                            <h4 class="text-green mb-3">Weapons Control Authorization</h4>
                            <form action="/submit_shoot" method="POST">
                                <div class="mb-3">
                                    <label class="form-label text-green">1. TARGET ADVERSARY SQUADRON</label>
                                    <select name="target_team" class="form-select" required>
                                        <option value="" disabled selected>Select an enemy fleet...</option>
                                        {% for tid, tdata in game_state.teams.items() %}
                                            {% if tid != team.id %}
                                            <option value="{{ tid }}">{{ tdata.display_name }}</option>
                                            {% endif %}
                                        {% endfor %}
                                    </select>
                                    <div class="form-text">Select exactly one enemy team to target this turn.</div>
                                </div>
                                <div class="mb-3">
                                    <label class="form-label text-green">2. SHELL TARGET COORDINATES (Island Name)</label>
                                    <select name="island" class="form-select" required>
                                        <option value="" disabled selected>Select island to attack...</option>
                                        {% for island in islands %}
                                        <option value="{{ island }}">{{ island }}</option>
                                        {% endfor %}
                                    </select>
                                    <div class="form-text">Designate which node you want to hit based on your physical grid.</div>
                                </div>
                                <button type="submit" class="btn btn-tactical w-100 mt-2">Fire Ordnance</button>
                            </form>
                        {% endif %}

                    {% elif game_state.phase == 'REVEAL' %}
                        <div class="text-center p-4 terminal-console">
                            <h4 class="text-green">[TRANSMISSIONS DECLASSIFIED]</h4>
                            <p class="text-muted mt-2">The commander has bypassed the cryptographic locks. Review previous intelligence archives in the right pane to decipher your next strategy.</p>
                        </div>
                    {% endif %}
                </div>
            </div>
        </div>

        <!-- Sidebar Panel: Logs & Map compass -->
        <div class="col-lg-4">
            <!-- Strategic Points Dashboard -->
            <div class="card card-tactical mb-4">
                <div class="card-header card-tactical-header">SQUADRON RESOURCES</div>
                <div class="card-body text-center">
                    <h2 class="text-green mb-0" style="text-shadow: 0 0 5px var(--term-glow);">{{ team.points }} MP</h2>
                    <div class="text-muted" style="font-size: 0.85rem;">Available Movement Points</div>
                </div>
            </div>

            <!-- Decryption Log Console (Command Line Output) -->
            <div class="card card-tactical mb-4">
                <div class="card-header card-tactical-header">TRANSMISSION HISTORY LOG</div>
                <div class="card-body">
                    <div class="terminal-console" style="font-size: 0.85rem;">
                        <!-- Current Turn Logs -->
                        <div class="mb-3 border-bottom border-secondary pb-2">
                            <span class="text-white"><strong>>>> CURRENT STATUS: TURN {{ game_state.turn }}</strong></span><br>
                            {% if game_state.phase == 'SIGNAL' %}
                                <span class="text-muted">>>> Waiting for squadron spy input...</span><br>
                            {% elif game_state.phase == 'MOVE' %}
                                <span class="text-cyan" style="color: #00f0ff !important;">>>> SYSTEM RADAR INTERCEPT</span><br>
                                <span class="text-white">>>> Intercepted Spy Signal: <strong>{{ team.current_msg or 'No signal' }}</strong></span><br>
                            {% elif game_state.phase == 'SHOOT' %}
                                <span class="text-muted">>>> Intercepts compiled. Direct targeting system active.</span><br>
                            {% elif game_state.phase == 'REVEAL' %}
                                <span class="text-green">>>> ROUND TRANSMISSIONS DECLASSIFIED:</span><br>
                                {% for tid, tdata in game_state.teams.items() %}
                                    <span class="text-green">>>> [{{ tdata.display_name }}] Spy Signal: {{ tdata.current_msg or 'None' }}</span><br>
                                    <span class="text-green">>>> [{{ tdata.display_name }}] Relocated: {{ tdata.current_moves_spent }} MP</span><br>
                                    <span class="text-green">>>> [{{ tdata.display_name }}] Fired: {{ game_state.teams[tdata.current_shot_team].display_name if tdata.current_shot_team in game_state.teams else 'None' }} @ {{ tdata.current_shot_island or 'None' }}</span><br>
                                {% endfor %}
                            {% endif %}
                        </div>

                        <!-- Historical Turn Logs -->
                        {% if game_state.history %}
                            {% for record in game_state.history|reverse %}
                                <div class="mb-3 border-bottom border-secondary pb-2" style="color: #cbd5e1;">
                                    <div class="text-white"><strong>>>> ARCHIVE TURN: {{ record.turn }}</strong></div>
                                    {% for tid, sub in record.submissions.items() %}
                                        <div class="ps-2 mt-1">
                                            <span class="text-green"><strong>[{{ sub.display_name }}]</strong></span><br>
                                            • Spy Signal: "{{ sub.msg }}"<br>
                                            • Relocated: {{ sub.moves_spent }} MP<br>
                                            • Fired: {{ sub.shot_team }} @ {{ sub.shot_island }}
                                        </div>
                                    {% endfor %}
                                </div>
                            {% endfor %}
                        {% else %}
                            <div class="text-muted">>>> Listening for secure transmissions... Historical records will populate here after the Commander terminates Turn 1 and broadcasts findings.</div>
                        {% endif %}
                    </div>
                </div>
            </div>

            <!-- Map Connections Reference -->
            <div class="card card-tactical mb-4">
                <div class="card-header card-tactical-header">STRATEGIC SEA ROUTES DIRECTORY</div>
                <div class="card-body p-0">
                    <div class="accordion accordion-flush" id="mapAccordion">
                        <div class="accordion-item bg-dark border-secondary">
                            <h2 class="accordion-header">
                                <button class="accordion-button collapsed bg-dark text-green border-secondary" type="button" data-bs-toggle="collapse" data-bs-target="#collapseCompass" aria-expanded="false" aria-controls="collapseCompass">
                                    Show connected sea routes
                                </button>
                            </h2>
                            <div id="collapseCompass" class="accordion-collapse collapse" data-bs-parent="#mapAccordion">
                                <div class="accordion-body bg-dark text-white p-3" style="font-size: 0.8rem; max-height: 250px; overflow-y: auto; color: #f1f5f9 !important;">
                                    {% for island, connections in map_connections %}
                                    <div class="mb-2">
                                        <strong class="text-green">{{ island }}</strong> &rarr; <span class="text-muted">{{ connections|join(", ") }}</span>
                                    </div>
                                    {% endfor %}
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <!-- Active Synchronous State Checker -->
    <script>
        const initialTurn = {{ game_state.turn }};
        const initialPhase = "{{ game_state.phase }}";
        setInterval(() => {
            fetch('/api/status')
                .then(response => response.json())
                .then(data => {
                    if (data.turn !== initialTurn || data.phase !== initialPhase) {
                        window.location.reload();
                    }
                })
                .catch(err => console.log("State sync warning: connection lost. Retrying...", err));
        }, 2500);
    </script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
    """
    return render_template_string(COMMON_LAYOUT_START + client_html + COMMON_LAYOUT_END, game_state=game_state, team=team, islands=ISLANDS, map_connections=MAP_CONNECTIONS)

@app.route("/submit_signal", methods=["POST"])
def submit_signal():
    team_id = session.get("team")
    if not team_id or game_state["phase"] != "SIGNAL":
        return redirect(url_for("home"))
    
    spy_msg = request.form.get("spy_msg", "").strip().lower()
    if not validate_spy_msg(spy_msg):
        flash("Operational error: Cryptographic signals must be exactly 6 lowercase English letters (a-z).", "error")
        return redirect(url_for("home"))

    team = game_state["teams"][team_id]
    team["current_msg"] = spy_msg
    team["phase_signal_submitted"] = True

    flash("Spy coordinate signal locked and broadcasted.", "success")
    return redirect(url_for("home"))

@app.route("/submit_move", methods=["POST"])
def submit_move():
    team_id = session.get("team")
    if not team_id or game_state["phase"] != "MOVE":
        return redirect(url_for("home"))
    
    try:
        moves_spent = int(request.form.get("moves_spent", 0))
    except ValueError:
        moves_spent = -1

    team = game_state["teams"][team_id]

    if moves_spent < 0 or moves_spent > team["points"]:
        flash("Operational error: Budget restriction. Spent points cannot exceed available MP budget.", "error")
        return redirect(url_for("home"))

    # Deduct and lock
    team["current_moves_spent"] = moves_spent
    team["points"] -= moves_spent
    team["phase_move_submitted"] = True

    flash("Maneuver plans calculated and locked.", "success")
    return redirect(url_for("home"))

@app.route("/submit_shoot", methods=["POST"])
def submit_shoot():
    team_id = session.get("team")
    if not team_id or game_state["phase"] != "SHOOT":
        return redirect(url_for("home"))

    target_team = request.form.get("target_team")
    island = request.form.get("island")

    if target_team == team_id or target_team not in game_state["teams"]:
        flash("Operational error: Invalid targets.", "error")
        return redirect(url_for("home"))

    if island not in ISLANDS:
        flash("Operational error: Target grid out of physical limits.", "error")
        return redirect(url_for("home"))

    team = game_state["teams"][team_id]
    team["current_shot_team"] = target_team
    team["current_shot_island"] = island
    team["phase_shoot_submitted"] = True

    flash("Ordnance locks committed and primed.", "success")
    return redirect(url_for("home"))

# --- ADMIN PANEL OVERRIDE & API CONTROLLERS ---

@app.route("/admin/add_team", methods=["POST"])
def add_team():
    if not session.get("is_admin"):
        return redirect(url_for("home"))
    
    display_name = request.form.get("display_name", "").strip()
    if not display_name:
        display_name = f"Team {len(game_state['teams']) + 1}"
    
    # Calculate a unique sequential numeric key
    num = 1
    while f"team_{num}" in game_state["teams"]:
        num += 1
    tid = f"team_{num}"

    game_state["teams"][tid] = {
        "id": tid,
        "display_name": display_name,
        "points": 3,
        "current_msg": "",
        "current_moves_spent": 0,
        "current_shot_team": "",
        "current_shot_island": "",
        "phase_signal_submitted": False,
        "phase_move_submitted": False,
        "phase_shoot_submitted": False
    }
    flash(f"Activated secure link for callsign: {display_name} ({tid})", "success")
    return redirect(url_for("admin_dashboard"))

@app.route("/admin/remove_team/<tid>")
def remove_team(tid):
    if not session.get("is_admin"):
        return redirect(url_for("home"))
    
    if len(game_state["teams"]) <= 2:
        flash("Tactical limitation: A minimum of 2 active teams is required to maintain game viability.", "error")
        return redirect(url_for("admin_dashboard"))

    if tid in game_state["teams"]:
        name = game_state["teams"][tid]["display_name"]
        del game_state["teams"][tid]

        # Reset any target selections pointing to the removed team
        for other_tid, other_team in game_state["teams"].items():
            if other_team["current_shot_team"] == tid:
                other_team["current_shot_team"] = ""
                other_team["current_shot_island"] = ""
                other_team["phase_shoot_submitted"] = False
        
        flash(f"Decommissioned team station: {name}", "success")
    return redirect(url_for("admin_dashboard"))

@app.route("/admin/login", methods=["POST"])
def admin_login():
    pwd = request.form.get("password")
    if pwd == ADMIN_PASSWORD:
        session["is_admin"] = True
        flash("Commander credentials accepted. Override validated.", "success")
        return redirect(url_for("admin_dashboard"))
    else:
        flash("Override rejected. Incorrect cryptographic password.", "error")
        return redirect(url_for("home"))

@app.route("/admin")
def admin_dashboard():
    admin_html = """
    <div class="row">
        <div class="col-12">
            <!-- Global Admin Panel Strategy Status -->
            <div class="card card-tactical mb-4">
                <div class="card-header card-tactical-header">COMMAND OVERRIDE CENTER (ADMIN)</div>
                <div class="card-body">
                    <h5 class="text-green mb-3">Turn Controls: Turn {{ game_state.turn }} | State: {{ game_state.phase }}</h5>
                    <div class="row g-2">
                        <div class="col-md-2">
                            <a href="/admin/action?action=set_phase_signal" class="btn btn-tactical w-100 {% if game_state.phase == 'SIGNAL' %}bg-success text-black{% endif %}" style="font-size: 0.82rem;">
                                Phase 1: Spy Signal
                            </a>
                        </div>
                        <div class="col-md-2">
                            <a href="/admin/action?action=set_phase_move" class="btn btn-tactical w-100 {% if game_state.phase == 'MOVE' %}bg-info text-black{% endif %}" style="font-size: 0.82rem;">
                                Phase 2: Move Ships
                            </a>
                        </div>
                        <div class="col-md-2">
                            <a href="/admin/action?action=set_phase_shoot" class="btn btn-tactical w-100 {% if game_state.phase == 'SHOOT' %}bg-warning text-black{% endif %}" style="font-size: 0.82rem;">
                                Phase 3: Shell Targets
                            </a>
                        </div>
                        <div class="col-md-2">
                            <a href="/admin/action?action=set_phase_reveal" class="btn btn-tactical w-100 {% if game_state.phase == 'REVEAL' %}bg-secondary text-black{% endif %}" style="font-size: 0.82rem;">
                                Phase 4: Reveal Round
                            </a>
                        </div>
                        <div class="col-md-4">
                            <a href="/admin/action?action=next_turn" class="btn btn-tactical-danger w-100" style="font-size: 0.82rem;" onclick="return confirm('Advance to next turn? This resets signals, awards +1 MP, and archives history.')">
                                &gt;&gt; Advance Next Turn (+1 MP)
                            </a>
                        </div>
                    </div>
                </div>
            </div>

            <!-- Dynamic Team Registration Control -->
            <div class="card card-tactical mb-4">
                <div class="card-header card-tactical-header">SQUADRON REGISTRY (Add / Configure Teams)</div>
                <div class="card-body">
                    <form action="/admin/add_team" method="POST" class="row g-2 align-items-center">
                        <div class="col-md-9">
                            <input type="text" name="display_name" class="form-control" placeholder="Enter name of new team (e.g., Team Echo)..." required>
                        </div>
                        <div class="col-md-3">
                            <button type="submit" class="btn btn-tactical w-100">+ Add New Team</button>
                        </div>
                    </form>
                </div>
            </div>

            <!-- Squadrons Status Grid -->
            <div class="card card-tactical mb-4">
                <div class="card-header card-tactical-header">SQUADRON INTEL & TELEMETRY DETAILED</div>
                <div class="card-body">
                    <div class="table-responsive">
                        <table class="table table-dark table-bordered border-secondary align-middle text-center">
                            <thead>
                                <tr class="text-green">
                                    <th>Fleet Callsign</th>
                                    <th>MP Pool</th>
                                    <th>Phase 1: Spy Signal</th>
                                    <th>Phase 2: Moves Spent</th>
                                    <th>Phase 3: Target Locks</th>
                                    <th>Operational Overrides</th>
                                </tr>
                            </thead>
                            <tbody>
                                {% for tid, tdata in game_state.teams.items() %}
                                <tr>
                                    <td class="text-start">
                                        <strong class="text-green">{{ tdata.display_name }}</strong> <span class="text-muted">({{ tid }})</span>
                                        <form action="/admin/action" method="POST" class="d-flex gap-1 mt-1">
                                            <input type="hidden" name="action" value="rename_team_admin">
                                            <input type="hidden" name="team_id" value="{{ tid }}">
                                            <input type="text" name="new_name" value="{{ tdata.display_name }}" class="form-control form-control-sm bg-dark text-white border-secondary py-0 px-1" style="font-size: 0.8rem;">
                                            <button type="submit" class="btn btn-sm btn-tactical py-0 px-1" style="font-size: 0.8rem;">Save</button>
                                        </form>
                                    </td>
                                    <td>
                                        <span class="fs-5 text-white">{{ tdata.points }} MP</span>
                                        <div class="btn-group btn-group-sm d-flex mt-1">
                                            <a href="/admin/action?action=adjust_points&team_id={{ tid }}&amount=1" class="btn btn-outline-secondary text-white border-secondary">+1</a>
                                            <a href="/admin/action?action=adjust_points&team_id={{ tid }}&amount=-1" class="btn btn-outline-secondary text-white border-secondary">-1</a>
                                        </div>
                                    </td>
                                    <td>
                                        {% if tdata.phase_signal_submitted %}
                                            <span class="badge badge-ready mb-1">SIGNAL READY</span><br>
                                            Code: <span class="text-white">"{{ tdata.current_msg }}"</span><br>
                                            <a href="/admin/action?action=unlock_signal&team_id={{ tid }}" class="btn btn-sm btn-tactical-danger py-0 px-1 mt-1" style="font-size: 0.75rem;">Unlock Phase 1</a>
                                        {% else %}
                                            <span class="badge badge-pending">WAITING</span>
                                        {% endif %}
                                    </td>
                                    <td>
                                        {% if tdata.phase_move_submitted %}
                                            <span class="badge badge-ready mb-1">MOVED</span><br>
                                            Spent: <span class="text-info">{{ tdata.current_moves_spent }} MP</span><br>
                                            <a href="/admin/action?action=unlock_move&team_id={{ tid }}" class="btn btn-sm btn-tactical-danger py-0 px-1 mt-1" style="font-size: 0.75rem;">Unlock Phase 2</a>
                                        {% else %}
                                            <span class="badge badge-pending">WAITING</span>
                                        {% endif %}
                                    </td>
                                    <td>
                                        {% if tdata.phase_shoot_submitted %}
                                            <span class="badge badge-ready mb-1">LOCKED</span><br>
                                            Target: <span class="text-danger" style="color: #f87171 !important;">{{ game_state.teams[tdata.current_shot_team].display_name if tdata.current_shot_team in game_state.teams else "None" }}</span><br>
                                            Island: <span class="text-warning">{{ tdata.current_shot_island }}</span><br>
                                            <a href="/admin/action?action=unlock_shoot&team_id={{ tid }}" class="btn btn-sm btn-tactical-danger py-0 px-1 mt-1" style="font-size: 0.75rem;">Unlock Phase 3</a>
                                        {% else %}
                                            <span class="badge badge-pending">WAITING</span>
                                        {% endif %}
                                    </td>
                                    <td>
                                        <div class="d-grid gap-1">
                                            <a href="/admin/action?action=force_submit_all&team_id={{ tid }}" class="btn btn-sm btn-tactical py-1 mb-1" style="font-size: 0.78rem;">Force Submit Defaults</a>
                                            <a href="/admin/remove_team/{{ tid }}" class="btn btn-sm btn-tactical-danger py-1" style="font-size: 0.78rem;" onclick="return confirm('Completely remove team {{ tdata.display_name }} from the map registration?')">Decommission Station</a>
                                        </div>
                                    </td>
                                </tr>
                                {% endfor %}
                            </tbody>
                        </table>
                    </div>
                </div>
            </div>

            <!-- Danger Zone Controls -->
            <div class="card card-tactical mb-4" style="border-color: #f87171;">
                <div class="card-header card-tactical-header text-danger" style="border-bottom-color: #f87171;">SYSTEM MASTER REBOOT PROTOCOL</div>
                <div class="card-body d-flex justify-content-between align-items-center">
                    <span class="text-muted" style="font-size: 0.85rem; color: #cbd5e1 !important;">This wipes game state variables, resets turn counters to 1, restores the default 4 teams, and assigns all squad budgets back to 3 MP.</span>
                    <a href="/admin/action?action=reset_game" class="btn btn-tactical-danger" onclick="return confirm('WARNING: Force full reset? All current game progress will be permanently erased!')">Reboot & Wipe</a>
                </div>
            </div>
        </div>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
    """
    return render_template_string(COMMON_LAYOUT_START + admin_html + COMMON_LAYOUT_END, game_state=game_state)

@app.route("/admin/action", methods=["GET", "POST"])
def admin_action():
    is_post = (request.method == "POST")
    action = request.form.get("action") if is_post else request.args.get("action")
    
    if not session.get("is_admin") and action != "rename_team_admin":
        flash("Authentication required to make adjustments.", "error")
        return redirect(url_for("home"))

    if action == "rename_team_admin":
        tid = request.form.get("team_id")
        new_name = request.form.get("new_name", "").strip()
        if tid in game_state["teams"] and new_name:
            game_state["teams"][tid]["display_name"] = new_name
            flash(f"Team {tid} Call Sign renamed to {new_name}.", "success")
        return redirect(url_for("admin_dashboard"))

    elif action == "set_phase_signal":
        game_state["phase"] = "SIGNAL"
        flash("State updated to: Phase 1: Spy Signal.", "success")
    elif action == "set_phase_move":
        game_state["phase"] = "MOVE"
        flash("State updated to: Phase 2: Decryption & Ship Movement.", "success")
    elif action == "set_phase_shoot":
        game_state["phase"] = "SHOOT"
        flash("State updated to: Phase 3: Target Acquisition.", "success")
    elif action == "set_phase_reveal":
        game_state["phase"] = "REVEAL"
        flash("State updated to: Phase 4: Tactical Reveal.", "success")
    elif action == "next_turn":
        # Archive current turn state into the logs
        turn_log = {
            "turn": game_state["turn"],
            "submissions": {}
        }
        for tid, tdata in game_state["teams"].items():
            shot_team_name = "None"
            if tdata["current_shot_team"] in game_state["teams"]:
                shot_team_name = game_state["teams"][tdata["current_shot_team"]]["display_name"]

            turn_log["submissions"][tid] = {
                "display_name": tdata["display_name"],
                "msg": tdata["current_msg"] or "None Submitted",
                "moves_spent": tdata["current_moves_spent"],
                "shot_team": shot_team_name,
                "shot_island": tdata["current_shot_island"] or "None"
            }
        game_state["history"].append(turn_log)

        # Increment Turn and reset locks for new round
        game_state["turn"] += 1
        game_state["phase"] = "SIGNAL"
        for tid in game_state["teams"]:
            game_state["teams"][tid]["points"] += 1  # Add +1 Movement point for the new turn
            game_state["teams"][tid]["current_msg"] = ""
            game_state["teams"][tid]["current_moves_spent"] = 0
            game_state["teams"][tid]["current_shot_team"] = ""
            game_state["teams"][tid]["current_shot_island"] = ""
            game_state["teams"][tid]["phase_signal_submitted"] = False
            game_state["teams"][tid]["phase_move_submitted"] = False
            game_state["teams"][tid]["phase_shoot_submitted"] = False
        
        flash(f"System advanced to Turn {game_state['turn']}. Resource points granted.", "success")

    elif action == "unlock_signal":
        tid = request.args.get("team_id")
        if tid in game_state["teams"]:
            team = game_state["teams"][tid]
            team["current_msg"] = ""
            team["phase_signal_submitted"] = False
            flash(f"Spy signal unlock for {team['display_name']}.", "success")

    elif action == "unlock_move":
        tid = request.args.get("team_id")
        if tid in game_state["teams"]:
            team = game_state["teams"][tid]
            if team["phase_move_submitted"]:
                # Refund movement points and unlock
                team["points"] += team["current_moves_spent"]
                team["current_moves_spent"] = 0
                team["phase_move_submitted"] = False
                flash(f"Movement coordinates unlocked for {team['display_name']}. Points refunded.", "success")

    elif action == "unlock_shoot":
        tid = request.args.get("team_id")
        if tid in game_state["teams"]:
            team = game_state["teams"][tid]
            team["current_shot_team"] = ""
            team["current_shot_island"] = ""
            team["phase_shoot_submitted"] = False
            flash(f"Weapons targets reset for {team['display_name']}.", "success")

    elif action == "adjust_points":
        tid = request.args.get("team_id")
        try:
            amt = int(request.args.get("amount", 0))
        except ValueError:
            amt = 0
        if tid in game_state["teams"]:
            game_state["teams"][tid]["points"] = max(0, game_state["teams"][tid]["points"] + amt)
            flash(f"Altered point reserves for {game_state['teams'][tid]['display_name']}.", "success")

    elif action == "force_submit_all":
        tid = request.args.get("team_id")
        if tid in game_state["teams"]:
            team = game_state["teams"][tid]
            if not team["phase_signal_submitted"]:
                team["current_msg"] = "xxxxxx"
                team["phase_signal_submitted"] = True
            if not team["phase_move_submitted"]:
                team["current_moves_spent"] = 0
                team["phase_move_submitted"] = True
            if not team["phase_shoot_submitted"]:
                other_teams = [t for t in game_state["teams"] if t != tid]
                team["current_shot_team"] = other_teams[0] if other_teams else ""
                team["current_shot_island"] = "Nordvik"
                team["phase_shoot_submitted"] = True
            flash(f"Force-applied defaults for {team['display_name']}.", "success")

    elif action == "reset_game":
        game_state.clear()
        game_state.update(get_initial_state())
        flash("System rebooted. Initial game parameters loaded.", "success")

    return redirect(url_for("admin_dashboard"))

# API to let screens poll for status without manual refreshes
@app.route("/api/status")
def api_status():
    return jsonify({
        "turn": game_state["turn"],
        "phase": game_state["phase"]
    })

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

