import React from "react";

import { sampleContentPack } from "@/data/sampleContentPack";
import { createStartingAdventurer } from "@/rules/character";
import {
  deleteSavedRun,
  getBrowserStorage,
  listSavedRuns,
  loadSavedRun,
  saveRun,
  type SavedRunSummary,
} from "@/rules/persistence";
import {
  createRunState,
  enterCurrentRoom,
  getAvailableMoves,
  isCurrentRoomCombatReady,
  resolveRunEnemyTurn,
  resolveRunPlayerTurn,
  resumeDungeon,
  returnToTown,
  startCombatInCurrentRoom,
  travelCurrentExit,
} from "@/rules/runState";
import { getNextLevelXpThreshold, MAX_ADVENTURER_LEVEL } from "@/rules/progression";
import {
  getConsumableCounts,
  restWithRation,
  usePotion,
  useScroll,
} from "@/rules/recovery";
import {
  grantDebugTreasure,
  queueTreasureForSale,
  sellPendingTreasure,
  stashCarriedTreasure,
  withdrawStashedTreasure,
} from "@/rules/townInventory";
import { useTownService } from "@/rules/townServices";
import type { RunState } from "@/types/state";

function createDemoRun() {
  const adventurer = createStartingAdventurer(sampleContentPack, {
    name: "Aster",
    weaponId: "weapon.short-sword",
    armourId: "armour.leather-vest",
    scrollId: "scroll.lesser-heal",
  });

  return createRunState({
    content: sampleContentPack,
    campaignId: "campaign.demo",
    adventurer,
  });
}

function getRoomTitle(run: RunState, roomId?: string) {
  if (!roomId) {
    return "Unknown Room";
  }

  const room = run.dungeon.levels[run.currentLevel]?.rooms[roomId];

  if (!room) {
    return "Unknown Room";
  }

  return (
    sampleContentPack.roomTemplates.find((template) => template.id === room.templateId)?.title ??
    room.notes[0] ??
    room.templateId ??
    room.id
  );
}

function getTownServiceDescription(serviceId: string) {
  switch (serviceId) {
    case "service.healer":
      return "Restore HP to full for 2 gold.";
    case "service.market":
      return "Buy 1 ration for 1 gold.";
    case "service.tavern":
      return "Recover 2 HP for 1 gold.";
    default:
      return "Visit this service.";
  }
}

function getItemName(definitionId: string) {
  return sampleContentPack.items.find((item) => item.id === definitionId)?.name ?? definitionId;
}

function getItemValue(definitionId: string) {
  return sampleContentPack.items.find((item) => item.id === definitionId)?.valueGp ?? 0;
}

function getManoeuvreName(manoeuvreId: string) {
  return sampleContentPack.manoeuvres.find((entry) => entry.id === manoeuvreId)?.name ?? manoeuvreId;
}

function getCombatTargetNumber(enemyArmourValue = 0) {
  return 7 + enemyArmourValue;
}

function App() {
  const [run, setRun] = React.useState<RunState>(() => createDemoRun());
  const [savedRuns, setSavedRuns] = React.useState<SavedRunSummary[]>([]);
  const currentLevel = run.dungeon.levels[run.currentLevel];
  const currentRoom = run.currentRoomId ? currentLevel?.rooms[run.currentRoomId] : undefined;
  const availableMoves = getAvailableMoves(run);
  const combatReadyEncounter = isCurrentRoomCombatReady(run);
  const inTown = run.phase === "town";
  const knownServices = sampleContentPack.townServices.filter((service) =>
    run.townState.knownServices.includes(service.id),
  );
  const carriedTreasure = run.adventurerSnapshot.inventory.carried.filter((entry) =>
    sampleContentPack.items.find((item) => item.id === entry.definitionId)?.itemType === "treasure",
  );
  const stashedTreasure = run.townState.stash;
  const pendingSales = run.townState.pendingSales;
  const pendingSaleValue = pendingSales.reduce(
    (total, entry) => total + getItemValue(entry.definitionId) * entry.quantity,
    0,
  );
  const consumableCounts = getConsumableCounts(run);
  const latestCombatLogs = run.activeCombat?.combatLog.slice(-3).reverse() ?? [];
  const nextLevelXpThreshold =
    run.adventurerSnapshot.level >= MAX_ADVENTURER_LEVEL
      ? undefined
      : getNextLevelXpThreshold(run.adventurerSnapshot.level);
  const xpToNextLevel =
    nextLevelXpThreshold === undefined
      ? 0
      : Math.max(0, nextLevelXpThreshold - run.adventurerSnapshot.xp);

  React.useEffect(() => {
    const storage = getBrowserStorage();

    if (!storage) {
      return;
    }

    setSavedRuns(listSavedRuns(storage));
  }, []);

  const handleReset = () => {
    setRun(createDemoRun());
  };

  const refreshSavedRuns = React.useCallback(() => {
    const storage = getBrowserStorage();

    if (!storage) {
      return;
    }

    setSavedRuns(listSavedRuns(storage));
  }, []);

  const handleEnterRoom = () => {
    setRun((previous) => enterCurrentRoom({ content: sampleContentPack, run: previous }).run);
  };

  const handleStartCombat = () => {
    setRun((previous) =>
      startCombatInCurrentRoom({ content: sampleContentPack, run: previous }).run,
    );
  };

  const handleTravel = (direction: "north" | "east" | "south" | "west") => {
    setRun((previous) =>
      travelCurrentExit({
        content: sampleContentPack,
        run: previous,
        exitDirection: direction,
      }).run,
    );
  };

  const handlePlayerTurn = (manoeuvreId: string, targetEnemyId: string) => {
    setRun((previous) =>
      resolveRunPlayerTurn({
        content: sampleContentPack,
        run: previous,
        manoeuvreId,
        targetEnemyId,
      }).run,
    );
  };

  const handleEnemyTurn = () => {
    setRun((previous) =>
      resolveRunEnemyTurn({ content: sampleContentPack, run: previous }).run,
    );
  };

  const handleReturnToTown = () => {
    setRun((previous) => returnToTown(previous).run);
  };

  const handleResumeDungeon = () => {
    setRun((previous) => resumeDungeon(previous).run);
  };

  const handleUseTownService = (serviceId: string) => {
    setRun((previous) =>
      useTownService({
        content: sampleContentPack,
        run: previous,
        serviceId,
      }).run,
    );
  };

  const handleGrantTreasure = (definitionId: string) => {
    setRun((previous) =>
      grantDebugTreasure({
        content: sampleContentPack,
        run: previous,
        definitionId,
      }).run,
    );
  };

  const handleStashTreasure = (definitionId: string) => {
    setRun((previous) =>
      stashCarriedTreasure({
        content: sampleContentPack,
        run: previous,
        definitionId,
      }).run,
    );
  };

  const handleWithdrawTreasure = (definitionId: string) => {
    setRun((previous) =>
      withdrawStashedTreasure({
        content: sampleContentPack,
        run: previous,
        definitionId,
      }).run,
    );
  };

  const handleQueueTreasure = (definitionId: string, source: "carried" | "stash") => {
    setRun((previous) =>
      queueTreasureForSale({
        content: sampleContentPack,
        run: previous,
        definitionId,
        source,
      }).run,
    );
  };

  const handleSellPending = () => {
    setRun((previous) =>
      sellPendingTreasure({
        content: sampleContentPack,
        run: previous,
      }).run,
    );
  };

  const handleUsePotion = () => {
    setRun((previous) =>
      usePotion({
        content: sampleContentPack,
        run: previous,
        definitionId: "potion.healing",
      }).run,
    );
  };

  const handleUseScroll = () => {
    setRun((previous) =>
      useScroll({
        content: sampleContentPack,
        run: previous,
        definitionId: "scroll.lesser-heal",
        roller: () => 4,
      }).run,
    );
  };

  const handleRationRest = () => {
    setRun((previous) =>
      restWithRation({
        content: sampleContentPack,
        run: previous,
        definitionId: "item.ration",
      }).run,
    );
  };

  const handleSaveRun = () => {
    const storage = getBrowserStorage();

    if (!storage) {
      return;
    }

    saveRun(storage, run);
    refreshSavedRuns();
  };

  const handleLoadRun = (saveId: string) => {
    const storage = getBrowserStorage();

    if (!storage) {
      return;
    }

    setRun(loadSavedRun(storage, saveId));
    refreshSavedRuns();
  };

  const handleDeleteSave = (saveId: string) => {
    const storage = getBrowserStorage();

    if (!storage) {
      return;
    }

    setSavedRuns(deleteSavedRun(storage, saveId));
  };

  return (
    <main className="app-shell">
      <section className="hero">
        <div>
          <p className="eyebrow">2D6 Dungeon Web</p>
          <h1>Dungeon Loop Shell</h1>
          <p className="lede">
            Traverse generated rooms, auto-resolve room entry, and engage combat
            when a room reveals a real encounter.
          </p>
        </div>

        <div className="hero-actions">
          <button className="button button-primary" onClick={handleReset}>
            Reset Demo Run
          </button>
          <button className="button" onClick={handleSaveRun}>
            Save Run
          </button>
          <button
            className="button"
            onClick={inTown ? handleResumeDungeon : handleReturnToTown}
            disabled={Boolean(run.activeCombat)}
          >
            {inTown ? "Resume Dungeon" : "Return To Town"}
          </button>
          <div className="status-chip">
            <span>Run Phase</span>
            <strong>{run.phase}</strong>
          </div>
        </div>
      </section>

      {combatReadyEncounter && !run.activeCombat && !inTown ? (
        <section className="alert-banner">
          <div>
            <span className="alert-kicker">Encounter Ready</span>
            <strong>{currentRoom?.encounter?.resultLabel}</strong>
            <p>
              This room contains a combat-ready encounter. Engage now to enter
              tactical resolution.
            </p>
          </div>
          <button className="button button-primary" onClick={handleStartCombat}>
            Engage Encounter
          </button>
        </section>
      ) : null}

      {run.lastCombatOutcome ? (
        <section
          className={`alert-banner ${run.lastCombatOutcome.result === "victory" ? "alert-banner-victory" : "alert-banner-defeat"}`}
        >
          <div>
            <span className="alert-kicker">
              {run.lastCombatOutcome.result === "victory" ? "Last Victory" : "Last Defeat"}
            </span>
            <strong>{run.lastCombatOutcome.summary}</strong>
            <p>
              {run.lastCombatOutcome.enemyNames.length > 0
                ? `Opposition: ${run.lastCombatOutcome.enemyNames.join(", ")}.`
                : "No enemy details recorded."}
            </p>
          </div>
        </section>
      ) : null}

      {run.lastLevelUp ? (
        <section className="alert-banner alert-banner-level">
          <div>
            <span className="alert-kicker">Latest Level Up</span>
            <strong>{run.lastLevelUp.summary}</strong>
            <p>
              {run.lastLevelUp.unlockedManoeuvreIds.length > 0
                ? `Unlocked: ${run.lastLevelUp.unlockedManoeuvreIds.map(getManoeuvreName).join(", ")}.`
                : "No additional manoeuvres unlocked on that level."}
            </p>
          </div>
        </section>
      ) : null}

      <section className="dashboard-grid">
        <article className="panel panel-highlight">
          <div className="panel-header">
            <h2>Adventurer</h2>
            <span>Level {run.adventurerSnapshot.level}</span>
          </div>
          <div className="stat-strip">
            <div>
              <span>HP</span>
              <strong>
                {run.adventurerSnapshot.hp.current}/{run.adventurerSnapshot.hp.max}
              </strong>
            </div>
            <div>
              <span>Shift</span>
              <strong>{run.adventurerSnapshot.stats.shift}</strong>
            </div>
            <div>
              <span>Discipline</span>
              <strong>{run.adventurerSnapshot.stats.discipline}</strong>
            </div>
            <div>
              <span>Precision</span>
              <strong>{run.adventurerSnapshot.stats.precision}</strong>
            </div>
            <div>
              <span>XP</span>
              <strong>{run.adventurerSnapshot.xp}</strong>
            </div>
            <div>
              <span>Next Level</span>
              <strong>
                {nextLevelXpThreshold === undefined
                  ? "Max"
                  : `${xpToNextLevel} to go`}
              </strong>
            </div>
          </div>
          <p className="supporting-text">
            {run.adventurerSnapshot.name} is equipped with a{" "}
            {sampleContentPack.weapons.find(
              (weapon) => weapon.id === run.adventurerSnapshot.weaponId,
            )?.name ?? "weapon"}
            .
          </p>
          <p className="supporting-text">
            Run rewards: {run.xpGained} XP earned, {run.defeatedCreatureIds.length} foes defeated.
          </p>
          <p className="supporting-text">
            {nextLevelXpThreshold === undefined
              ? `${run.adventurerSnapshot.name} has reached the current maximum supported level.`
              : `Next level at ${nextLevelXpThreshold} XP. Current manoeuvres: ${run.adventurerSnapshot.manoeuvreIds.map(getManoeuvreName).join(", ")}.`}
          </p>
          <p className="supporting-text">
            {inTown
              ? `The party is currently in town${run.lastTownAt ? ` as of ${new Date(run.lastTownAt).toLocaleString()}` : ""}.`
              : "The party is still delving below ground."}
          </p>
          <div className="recovery-panel">
            <div className="panel-header">
              <h2>Recovery Kit</h2>
              <span>{inTown ? "Town-ready" : "Field-ready"}</span>
            </div>
            <div className="recovery-grid">
              <article className="recovery-card">
                <span className="encounter-label">Potion</span>
                <strong>Healing Potion</strong>
                <p className="supporting-text">
                  Restore 3 HP. Carried: {consumableCounts.healingPotion}
                </p>
                <button
                  className="button"
                  onClick={handleUsePotion}
                  disabled={consumableCounts.healingPotion === 0}
                >
                  Use Potion
                </button>
              </article>
              <article className="recovery-card">
                <span className="encounter-label">Scroll</span>
                <strong>Lesser Heal</strong>
                <p className="supporting-text">
                  Restore 2 HP on a successful cast. Carried: {consumableCounts.lesserHealScroll}
                </p>
                <button
                  className="button"
                  onClick={handleUseScroll}
                  disabled={consumableCounts.lesserHealScroll === 0}
                >
                  Cast Scroll
                </button>
              </article>
              <article className="recovery-card">
                <span className="encounter-label">Ration</span>
                <strong>Town Rest</strong>
                <p className="supporting-text">
                  Spend 1 ration in town to recover 2 HP. Carried: {consumableCounts.ration}
                </p>
                <button
                  className="button"
                  onClick={handleRationRest}
                  disabled={!inTown || consumableCounts.ration === 0}
                >
                  Eat And Rest
                </button>
              </article>
            </div>
          </div>
        </article>

        <article className="panel panel-saves">
          <div className="panel-header">
            <h2>Save Archive</h2>
            <span>{savedRuns.length} saves</span>
          </div>
          {savedRuns.length === 0 ? (
            <p className="supporting-text">No saved runs yet. Save the current run to persist progress.</p>
          ) : (
            <div className="save-list">
              {savedRuns.map((save) => (
                <article key={save.id} className="save-card">
                  <div>
                    <span className="encounter-label">{save.phase}</span>
                    <strong>{save.label}</strong>
                    <p className="supporting-text">
                      Saved {new Date(save.savedAt).toLocaleString()} · Level {save.currentLevel}
                    </p>
                  </div>
                  <div className="save-actions">
                    <button className="button" onClick={() => handleLoadRun(save.id)}>
                      Load
                    </button>
                    <button className="button" onClick={() => handleDeleteSave(save.id)}>
                      Delete
                    </button>
                  </div>
                </article>
              ))}
            </div>
          )}
        </article>

        {inTown ? (
          <article className="panel panel-town-hub">
            <div className="panel-header">
              <h2>Town Hub</h2>
              <span>Between Delves</span>
            </div>
            <h3 className="room-title">Safe Harbor</h3>
            <p className="supporting-text">
              You are out of the dungeon. Review the current expedition, catch your breath, and
              then resume the delve from the same level when you are ready.
            </p>
            <div className="town-summary-grid">
              <div className="encounter-box">
                <span className="encounter-label">Current Gold</span>
                <strong>{run.adventurerSnapshot.inventory.currency.gold}</strong>
              </div>
              <div className="encounter-box">
                <span className="encounter-label">Rooms Found</span>
                <strong>{currentLevel?.discoveredRoomOrder.length ?? 0}</strong>
              </div>
              <div className="encounter-box">
                <span className="encounter-label">Foes Defeated</span>
                <strong>{run.defeatedCreatureIds.length}</strong>
              </div>
            </div>
            <div className="button-row">
              <button className="button button-primary" onClick={handleResumeDungeon}>
                Resume Delve
              </button>
            </div>
            <div className="town-services">
              {knownServices.map((service) => (
                <article key={service.id} className="town-service-card">
                  <div>
                    <span className="encounter-label">{service.serviceType}</span>
                    <strong>{service.name}</strong>
                    <p className="supporting-text">{getTownServiceDescription(service.id)}</p>
                  </div>
                  <button
                    className="button"
                    onClick={() => handleUseTownService(service.id)}
                  >
                    Use Service
                  </button>
                </article>
              ))}
            </div>
            <div className="town-ledger">
              <div className="panel-header">
                <h2>Treasure Ledger</h2>
                <span>{pendingSaleValue} gp pending</span>
              </div>
              <div className="button-row">
                <button
                  className="button"
                  onClick={() => handleGrantTreasure("item.silver-chalice")}
                >
                  Debug: Add Chalice
                </button>
                <button
                  className="button"
                  onClick={() => handleGrantTreasure("item.garnet-ring")}
                >
                  Debug: Add Ring
                </button>
                <button
                  className="button button-primary"
                  onClick={handleSellPending}
                  disabled={pendingSales.length === 0}
                >
                  Sell Queued Treasure
                </button>
              </div>
              <div className="town-ledger-grid">
                <article className="town-ledger-card">
                  <h3>Pack Treasure</h3>
                  {carriedTreasure.length === 0 ? (
                    <p className="supporting-text">No treasure currently in the pack.</p>
                  ) : (
                    carriedTreasure.map((entry) => (
                      <div key={`carried-${entry.definitionId}`} className="treasure-row">
                        <div>
                          <strong>{getItemName(entry.definitionId)}</strong>
                          <p className="supporting-text">
                            Qty {entry.quantity} · {getItemValue(entry.definitionId)} gp each
                          </p>
                        </div>
                        <div className="treasure-actions">
                          <button
                            className="button"
                            onClick={() => handleStashTreasure(entry.definitionId)}
                          >
                            Stash
                          </button>
                          <button
                            className="button"
                            onClick={() => handleQueueTreasure(entry.definitionId, "carried")}
                          >
                            Queue Sale
                          </button>
                        </div>
                      </div>
                    ))
                  )}
                </article>
                <article className="town-ledger-card">
                  <h3>Town Stash</h3>
                  {stashedTreasure.length === 0 ? (
                    <p className="supporting-text">No treasure stored in town.</p>
                  ) : (
                    stashedTreasure.map((entry) => (
                      <div key={`stash-${entry.definitionId}`} className="treasure-row">
                        <div>
                          <strong>{getItemName(entry.definitionId)}</strong>
                          <p className="supporting-text">
                            Qty {entry.quantity} · {getItemValue(entry.definitionId)} gp each
                          </p>
                        </div>
                        <div className="treasure-actions">
                          <button
                            className="button"
                            onClick={() => handleWithdrawTreasure(entry.definitionId)}
                          >
                            Withdraw
                          </button>
                          <button
                            className="button"
                            onClick={() => handleQueueTreasure(entry.definitionId, "stash")}
                          >
                            Queue Sale
                          </button>
                        </div>
                      </div>
                    ))
                  )}
                </article>
                <article className="town-ledger-card">
                  <h3>Queued Sales</h3>
                  {pendingSales.length === 0 ? (
                    <p className="supporting-text">Nothing is queued for sale yet.</p>
                  ) : (
                    pendingSales.map((entry) => (
                      <div key={`sale-${entry.definitionId}`} className="treasure-row">
                        <div>
                          <strong>{getItemName(entry.definitionId)}</strong>
                          <p className="supporting-text">
                            Qty {entry.quantity} · {getItemValue(entry.definitionId) * entry.quantity} gp total
                          </p>
                        </div>
                      </div>
                    ))
                  )}
                </article>
              </div>
            </div>
          </article>
        ) : (
          <>
            <article className="panel">
          <div className="panel-header">
            <h2>Current Room</h2>
            <span>Level {run.currentLevel}</span>
          </div>
          <h3 className="room-title">
            {getRoomTitle(run, run.currentRoomId)}
          </h3>
          <p className="supporting-text">
            {currentRoom?.notes[1] ?? "No encounter notes available yet."}
          </p>
          <div className="room-meta">
            <span>Entered: {currentRoom?.discovery.entered ? "Yes" : "No"}</span>
            <span>Cleared: {currentRoom?.discovery.cleared ? "Yes" : "No"}</span>
            <span>Exits: {currentRoom?.exits.length ?? 0}</span>
          </div>
          <div className="button-row">
            <button className="button" onClick={handleEnterRoom}>
              Enter Room
            </button>
            <button
              className="button button-primary"
              onClick={handleStartCombat}
              disabled={!combatReadyEncounter || Boolean(run.activeCombat)}
            >
              Start Combat
            </button>
          </div>
          <div className="encounter-box">
            <span className="encounter-label">Encounter</span>
            <strong>{currentRoom?.encounter?.resultLabel ?? "None"}</strong>
          </div>
        </article>

        <article className="panel">
          <div className="panel-header">
            <h2>Navigation</h2>
            <span>{availableMoves.length} exits</span>
          </div>
          <div className="move-list">
            {availableMoves.map((move) => (
              <button
                key={move.direction}
                className="move-card"
                onClick={() => handleTravel(move.direction)}
                disabled={Boolean(run.activeCombat)}
              >
                <span>{move.direction}</span>
                <strong>{move.leadsToRoomId ? "Travel" : "Generate"}</strong>
                <em>
                  {move.leadsToRoomId
                    ? getRoomTitle(run, move.leadsToRoomId)
                    : `${move.exitType} exit`}
                </em>
              </button>
            ))}
          </div>
          <div className="mini-map">
            {currentLevel?.discoveredRoomOrder.map((roomId) => {
              const room = currentLevel.rooms[roomId];
              const active = roomId === run.currentRoomId;

              return (
                <article
                  key={roomId}
                  className={`map-node${active ? " map-node-active" : ""}`}
                >
                  <span>
                    {room.position.x},{room.position.y}
                  </span>
                  <strong>{getRoomTitle(run, roomId)}</strong>
                </article>
              );
            })}
          </div>
        </article>

        <article className="panel">
          <div className="panel-header">
            <h2>Combat</h2>
            <span>{run.activeCombat ? `Round ${run.activeCombat.round}` : "Inactive"}</span>
          </div>
          {run.activeCombat ? (
            <>
              <div className="combat-status">
                <span>Acting Side</span>
                <strong>{run.activeCombat.actingSide}</strong>
              </div>
              <div className="combat-summary-grid">
                <div className="encounter-box">
                  <span className="encounter-label">Player HP</span>
                  <strong>
                    {run.activeCombat.player.hpCurrent}/{run.activeCombat.player.hpMax}
                  </strong>
                </div>
                <div className="encounter-box">
                  <span className="encounter-label">Enemies Standing</span>
                  <strong>
                    {run.activeCombat.enemies.filter((enemy) => enemy.hpCurrent > 0).length}
                  </strong>
                </div>
                <div className="encounter-box">
                  <span className="encounter-label">Last Roll</span>
                  <strong>{run.activeCombat.lastRoll?.total ?? "-"}</strong>
                </div>
              </div>
              <div className="enemy-list">
                {run.activeCombat.enemies.map((enemy) => (
                  <div key={enemy.id} className="enemy-card">
                    <div>
                      <strong>{enemy.name}</strong>
                      <span>
                        HP {enemy.hpCurrent}/{enemy.hpMax}
                      </span>
                      <span>Target {getCombatTargetNumber(enemy.armourValue ?? 0)}</span>
                    </div>
                    <div className="enemy-actions">
                      <button
                        className="button"
                        onClick={() =>
                          handlePlayerTurn("manoeuvre.exact-strike", enemy.id)
                        }
                        disabled={
                          run.activeCombat?.actingSide !== "player" ||
                          enemy.hpCurrent <= 0
                        }
                      >
                        Exact Strike
                      </button>
                      <button
                        className="button"
                        onClick={() => handlePlayerTurn("manoeuvre.guard-break", enemy.id)}
                        disabled={
                          run.activeCombat?.actingSide !== "player" ||
                          enemy.hpCurrent <= 0
                        }
                      >
                        Guard Break
                      </button>
                    </div>
                  </div>
                ))}
              </div>
              <div className="button-row">
                <button
                  className="button button-primary"
                  onClick={handleEnemyTurn}
                  disabled={run.activeCombat.actingSide !== "enemy"}
                >
                  Resolve Enemy Turn
                </button>
              </div>
              <div className="combat-feed">
                {latestCombatLogs.map((entry) => (
                  <article key={entry.id} className="log-entry">
                    <span>{entry.type}</span>
                    <p>{entry.text}</p>
                  </article>
                ))}
              </div>
            </>
          ) : (
            <p className="supporting-text">
              {run.lastCombatOutcome
                ? "No active combat. Review the last battle above, then continue the delve or recover in town."
                : "No active combat. Travel until a room reveals a hostile encounter, then engage it from the banner or room panel."}
            </p>
          )}
        </article>
          </>
        )}

        <article className="panel panel-log">
          <div className="panel-header">
            <h2>Run Log</h2>
            <span>{run.log.length} entries</span>
          </div>
          <div className="log-list">
            {run.log.length === 0 ? (
              <p className="supporting-text">No events recorded yet.</p>
            ) : (
              run.log
                .slice()
                .reverse()
                .map((entry) => (
                  <article key={entry.id} className="log-entry">
                    <span>{entry.type}</span>
                    <p>{entry.text}</p>
                  </article>
                ))
            )}
          </div>
        </article>
      </section>
    </main>
  );
}

export default App;
