<script>
    import { onMount, onDestroy } from 'svelte';
    import { push } from 'svelte-spa-router';
    import { apiRequest } from '../lib/api';
    import { extraMenuLinks } from '../lib/menu';
    import { getSuggestion } from '../lib/suggestions';
    import { displayName } from '../lib/cards';
    import { setPageTitle } from '../lib/title';
    import { saveSession, removeSession } from '../lib/sessions';

    import LobbyPhase from '../components/LobbyPhase.svelte';
    import CharacterCreationPhase from '../components/CharacterCreationPhase.svelte';
    import SceneSetupPhase from '../components/SceneSetupPhase.svelte';
    import ScenePhase from '../components/ScenePhase.svelte';
    import UpkeepPhase from '../components/UpkeepPhase.svelte';
    import RecruitPhase from '../components/RecruitPhase.svelte';
    import GameOverPhase from '../components/GameOverPhase.svelte';
    import EventLog from '../components/EventLog.svelte';
    import NameModal from '../components/NameModal.svelte';
    import GatModal from '../components/GatModal.svelte';
    import RankBonusModal from '../components/RankBonusModal.svelte';

    export let params = {};
    let gameId = params.id;
    let playerId = params.pid;

    let state = null;
    let error = '';
    let intervalId;
    let ws = null;
    let reconnectTimer = null;
    let reconnectDelay = 1000;
    let destroyed = false;

    async function fetchState() {
        try {
            const data = await apiRequest(`/game/${gameId}/player/${playerId}/state`);
            state = data;
            error = '';
        } catch (err) {
            error = err.message;
        }
    }

    // The server pushes a ping over this socket whenever the game changes;
    // each ping triggers a refetch of the state blob.
    function connectSocket() {
        const proto = location.protocol === 'https:' ? 'wss' : 'ws';
        ws = new WebSocket(`${proto}://${location.host}/api/game/${gameId}/ws`);
        ws.onopen = () => {
            reconnectDelay = 1000;
            fetchState(); // catch up on anything missed while disconnected
        };
        ws.onmessage = () => fetchState();
        ws.onclose = () => {
            if (destroyed) return;
            reconnectTimer = setTimeout(connectSocket, reconnectDelay);
            reconnectDelay = Math.min(reconnectDelay * 2, 10000);
        };
    }

    onMount(() => {
        fetchState();
        connectSocket();
        // Slow fallback poll in case a push is ever missed
        intervalId = setInterval(fetchState, 30000);
    });

    // Creator-only corner menu entries: Dev Mode toggle (all phases), the
    // Skip Character Creation shortcut (Dev Mode only), and the Admin link.
    async function toggleDevMode() {
        try {
            await apiRequest(`/game/${gameId}/player/${playerId}/dev-mode`, 'POST', {
                enabled: !state.game.dev_mode
            });
        } catch (err) {
            error = err.message;
        }
    }

    async function skipCharacterCreation() {
        // Suggested values for everyone's free-text fields; the backend only
        // applies them to fields players haven't filled in themselves.
        const fills = {};
        for (const p of state.players) {
            fills[p.id] = {
                avatar_look: getSuggestion('look'),
                avatar_smell: getSuggestion('smell'),
                first_words: getSuggestion('first_words'),
                good_at_math: getSuggestion('good_at_math'),
                like: getSuggestion('like'),
                hate: getSuggestion('hate'),
            };
        }
        try {
            await apiRequest(`/game/${gameId}/player/${playerId}/skip-character-creation`, 'POST', {
                fills: JSON.stringify(fills)
            });
        } catch (err) {
            error = err.message;
        }
    }

    // Admin escape hatch: hand out every technique randomly and auto-assign J/Q/K
    async function autoAssignTechniques() {
        try {
            await apiRequest(`/game/${gameId}/player/${playerId}/auto-assign-techniques`, 'POST');
        } catch (err) {
            error = err.message;
        }
    }

    // Voluntarily remove yourself from the game (cards go to the discard)
    async function leaveGame() {
        if (!confirm("Leave this game? Your cards go to the discard and you'll need a new invite to rejoin. This can't be undone.")) return;
        try {
            await apiRequest(`/game/${gameId}/player/${playerId}/leave`, 'POST');
            removeSession(gameId, playerId);
            push('/');
        } catch (err) {
            error = err.message;
        }
    }

    // Distinguish tabs/history by the Pi-Rat (and crew) this dashboard is for
    $: setPageTitle(state ? displayName(state.player) : null, state?.game?.crew_name);

    // Keep this browser's saved session up to date so the home page can rejoin
    // with current crew/rat names (the rat name changes when a Name is earned)
    $: if (state?.game && state?.player) {
        saveSession({
            gameId,
            playerId,
            crewName: state.game.crew_name,
            playerName: state.player.player_name,
            ratName: state.player.name,
        });
    }

    // Admins get the admin key in their state blob; stash it so the Admin page works for them too
    $: if (state?.player?.is_admin && state?.game?.admin_key) {
        localStorage.setItem(`admin_key_${gameId}`, state.game.admin_key);
    }

    $: {
        const items = [];
        if (state?.player?.is_admin) {
            items.push({
                label: `🧪 Dev Mode: ${state.game.dev_mode ? 'On' : 'Off'}`,
                action: toggleDevMode,
                title: 'Toggle Dev Mode testing shortcuts for the whole table',
            });
            if (state.game.dev_mode && ['character_creation', 'swap_techniques', 'assign_techniques'].includes(state.game.phase)) {
                items.push({
                    label: '⏭️ Skip Character Creation',
                    action: skipCharacterCreation,
                    title: 'Auto-fill anything unfinished for all players and jump to scene setup',
                });
            }
            if (state.game.phase === 'swap_techniques' || state.game.phase === 'assign_techniques') {
                items.push({
                    label: '🎲 Auto-Assign Techniques',
                    action: autoAssignTechniques,
                    title: 'Randomly distribute all techniques to eligible players and assign them to J/Q/K',
                });
            }
            items.push({ label: '🛠️ Admin', href: `#/game/${gameId}/admin`, title: 'Open the Admin Panel' });
        }
        if (state?.player) {
            items.push({
                label: '🚪 Leave Game',
                action: leaveGame,
                title: 'Remove yourself from this game (your cards go to the discard)',
            });
        }
        extraMenuLinks.set(items);
    }

    onDestroy(() => {
        destroyed = true;
        if (intervalId) clearInterval(intervalId);
        if (reconnectTimer) clearTimeout(reconnectTimer);
        if (ws) ws.close();
        extraMenuLinks.set([]);
    });
</script>

{#if error}
    <div class="alert alert-danger" style="margin: 20px;">
        Error connecting to game: {error}
    </div>
{/if}

{#if state}
    <div class="dashboard-container {state.player.is_ghost ? 'ghost-world' : ''}">
        {#if state.game.phase === 'lobby'}
            <LobbyPhase {state} />
        {:else if state.game.phase === 'character_creation' || state.game.phase === 'swap_techniques' || state.game.phase === 'assign_techniques'}
            <CharacterCreationPhase {state} />
        {:else if state.game.phase === 'scene_setup'}
            <SceneSetupPhase {state} />
        {:else if state.game.phase === 'scene'}
            <ScenePhase {state} />
        {:else if state.game.phase === 'between_scenes' || state.game.phase === 'deep_upkeep'}
            <UpkeepPhase {state} />
        {:else if state.game.phase === 'recruit_creation'}
            <RecruitPhase {state} />
        {:else if state.game.phase === 'ended'}
            <GameOverPhase {state} />
        {:else}
            <div class="card p-4">Unknown phase: {state.game.phase}</div>
        {/if}
    </div>

    <!-- The scene phase renders its own inline Event Log as the third column. -->
    {#if state.game.phase !== 'scene'}
        <EventLog {state} />
    {/if}
    <NameModal {state} />
    <GatModal {state} />
    <RankBonusModal {state} />
{:else if !error}
    <div class="loading-container">
        <p>Loading game state...</p>
    </div>
{/if}

<style>
    .loading-container {
        display: flex;
        justify-content: center;
        align-items: center;
        height: 100vh;
        color: white;
        font-size: 1.5rem;
    }
</style>
