BareGit
import { h, render, useState, useEffect, html } from 'https://unpkg.com/htm/preact/standalone.module.js';
import { 
    INITIAL_STATE, THEMES, 
    createDeck, shuffleDeck, saveHistory, saveState, loadState 
} from './game.js';
import { Card, WeaponSlot, GameOver } from './components.js';

const App = () => {
    const [state, setState] = useState(() => {
        const loaded = loadState();
        if (loaded) return loaded;
        
        // Fallback: check legacy theme key or default
        const saved_theme = localStorage.getItem('scoundrel_theme');
        return {
            ...INITIAL_STATE,
            theme: (saved_theme && THEMES[saved_theme]) ? saved_theme : 'Text'
        };
    });

    // Save state on every change
    useEffect(() => {
        saveState(state);
    }, [state]);

    // Only start a new game on mount if we didn't load a valid active game
    useEffect(() => { 
        const isGameActive = state.deck.length > 0 || state.room.some(c => c !== null) || state.game_over;
        if (!isGameActive) {
            startGame(); 
        }
    }, []);

    const startGame = () => {
        const full_deck = shuffleDeck(createDeck());
        const room = full_deck.splice(0, 4);
        // Preserve current theme when resetting
        setState(prev => ({ 
            ...INITIAL_STATE, 
            theme: prev.theme, 
            deck: full_deck, 
            room, 
            msg: "A new dungeon awaits." 
        }));
    };

    const undoLastMove = () => {
        if (state.history.length === 0) return;
        
        const previousState = state.history[state.history.length - 1];
        const remainingHistory = state.history.slice(0, -1);
        
        // Fix JSON.stringify(Infinity) -> null issue
        if (previousState.last_enemy_value === null) {
            previousState.last_enemy_value = Infinity;
        }

        setState({
            ...previousState,
            history: remainingHistory,
            msg: "Undid last move."
        });
    };

    const resolveCard = (card, use_weapon = true) => {
        let new_state = { 
            ...state,
            history: saveHistory(state)
        };
        let card_resolved = false;

        if (card.type === 'MONSTER') {
            let damage_taken = 0;
            if (use_weapon && new_state.weapon && card.value < new_state.last_enemy_value) {
                damage_taken = Math.max(0, card.value - new_state.weapon.value);
                new_state.last_enemy_value = card.value;
                new_state.msg = `Slayed ${card.rank}${card.suit} with weapon. Took ${damage_taken} damage.`;
                new_state.defeated_monsters = [...new_state.defeated_monsters, card];
            } else {
                damage_taken = card.value;
                new_state.msg = `Fought ${card.rank}${card.suit} bare-handed. Took ${damage_taken} damage.`;
                new_state.discard_pile = [...new_state.discard_pile, card];
            }
            new_state.hp -= damage_taken;
            card_resolved = true;
        } else if (card.type === 'WEAPON') {
            if (new_state.weapon) {
                new_state.discard_pile = [
                    ...new_state.discard_pile, 
                    new_state.weapon,
                    ...new_state.defeated_monsters
                ];
            }
            new_state.defeated_monsters = [];
            new_state.weapon = card;
            new_state.last_enemy_value = Infinity;
            new_state.msg = `Equipped ${card.rank}${card.suit}.`;
            card_resolved = true;
        } else if (card.type === 'POTION') {
            if (!new_state.potion_used_this_turn) {
                const old_hp = new_state.hp;
                new_state.hp = Math.min(new_state.max_hp, new_state.hp + card.value);
                new_state.potion_used_this_turn = true;
                new_state.msg = `Healed ${new_state.hp - old_hp} HP.`;
            } else {
                new_state.msg = "Potion wasted!";
            }
            new_state.discard_pile = [...new_state.discard_pile, card];
            card_resolved = true;
        }

        if (card_resolved) {
            new_state.room = new_state.room.map(c => c && c.id === card.id ? null : c);
            new_state.cards_played_this_turn += 1;
            if (new_state.hp <= 0) { new_state.game_over = true; new_state.won = false; }
            else if (new_state.room.filter(c => c !== null).length === 1 && new_state.deck.length > 0) {
                const remaining_card = new_state.room.find(c => c !== null);
                const next_cards = new_state.deck.splice(0, 3);
                new_state.room = [remaining_card, ...next_cards];
                new_state.cards_played_this_turn = 0;
                new_state.potion_used_this_turn = false;
                new_state.fled_last_turn = false;
            } else if (new_state.room.every(c => c === null) && new_state.deck.length === 0) {
                new_state.game_over = true; new_state.won = true;
            }
            setState(new_state);
        }
    };

    const handleCardClick = (card) => {
        if (state.game_over) return;
        if (card.type === 'MONSTER') {
            // Monsters are handled via overlay buttons
            return;
        } else {
            resolveCard(card);
        }
    };

    const fleeRoom = () => {
        const active_cards = state.room.filter(c => c !== null);
        const new_deck = [...state.deck, ...active_cards];
        const new_room = new_deck.splice(0, 4);
        setState({ 
            ...state, 
            deck: new_deck, 
            room: new_room, 
            fled_last_turn: true, 
            cards_played_this_turn: 0, 
            potion_used_this_turn: false, 
            msg: "Fled the room.",
            history: saveHistory(state)
        });
    };

    const can_flee_check = !state.fled_last_turn && state.cards_played_this_turn === 0 && state.deck.length > 0;

    return html`
        <header>
            <h1>SCOUNDREL</h1>
            <div class="stats-bar">
                <span class="hp-bar">HP: ${state.hp} / ${state.max_hp}</span>
                <span class="deck-count">Deck: ${state.deck.length}</span>
                <select class="theme-selector" value=${state.theme} onChange=${(e) => setState({...state, theme: e.target.value})}>
                    ${Object.entries(THEMES).map(([key, theme]) => html`<option value=${key}>${theme.label}</option>`)}
                </select>
            </div>
        </header>

        <div class="game-board">
            <div class="weapon-area">
                <div style="display: flex; gap: 20px; align-items: center;">
                    <${WeaponSlot} weapon=${state.weapon} last_enemy_value=${state.last_enemy_value} themeKey=${state.theme} />
                </div>
                <div class="defeated-container">
                    <strong>Defeated:</strong>
                    <div class="defeated-pile">
                        ${state.defeated_monsters.map(m => html`<div class="mini-card ${m.color}" title="${m.rank}${m.suit}">${m.rank}${m.suit}</div>`)}
                    </div>
                </div>
            </div>

            <div style="text-align: center; height: 1.2em; font-style: italic;">${state.msg}</div>

            <div class="room-container">
                <div class="room-cards">
                    ${state.room.map((card, idx) => html`<${Card} 
                        key=${card ? card.id : 'empty-'+idx} 
                        card=${card} 
                        onClick=${handleCardClick} 
                        onAttack=${resolveCard}
                        can_use_weapon=${card && state.weapon && card.value < state.last_enemy_value}
                        themeKey=${state.theme}
                    />`)}
                </div>
            </div>

            <div class="actions">
                <button onClick=${undoLastMove} disabled=${state.history.length === 0}>Undo</button>
                <button onClick=${() => { if (confirm("Start a new game? Current progress will be lost.")) startGame(); }}>New Game</button>
                <button onClick=${fleeRoom} disabled=${!can_flee_check}>Run Away</button>
            </div>
        </div>

        <div class="history-area">
            <div class="discard-container">
                <strong>Discard Pile (Newest First):</strong>
                <div class="discard-pile">
                    ${state.discard_pile.slice().reverse().map(c => html`<div class="mini-card ${c.color}" title="${c.rank}${c.suit}">${c.rank}${c.suit}</div>`)}
                </div>
            </div>
            <div class="rules-container">
                <p><strong>Rules:</strong> Standard 52-card deck (no red face cards/aces). Play 3 of 4 cards to advance. Hearts heal (1/turn). Diamonds are weapons. Weapons durability: next monster must be weaker than last. <a href="https://rpdillon.net/scoundrel.html" target="_blank">Full Rules</a></p>
            </div>
        </div>

        ${state.game_over && html`<${GameOver} won=${state.won} hp=${state.hp} reset_game=${startGame} />`}
    `;
};

render(html`<${App} />`, document.getElementById('app'));