import type { CSSProperties } from "react";
import { useEffect, useState } from "react";
import { openWorldshaperStudioWindow } from "./worldshaperStudio/windowing";
import {
  CHANGELOG_SECTIONS,
  CHANGELOG_SPLASH_FOOTNOTE,
  CHANGELOG_SPLASH_KICKER,
  CHANGELOG_SPLASH_TITLE,
  CHANGELOG_SPLASH_VERSION,
} from "./worldshaperStudio/changelogData";
import type { ChangelogItem } from "./worldshaperStudio/changelogData";
import launcherBackground from "../background.png";

type WorldDefaultPayload = {
  worldId?: string;
  world?: {
    id?: string;
  };
};

type LaunchState = "ready" | "opening" | "opened" | "blocked" | "error";
type BoardTab = "news" | "requests";

type LauncherRequest = {
  id: string;
  sourceSubmissionId?: string;
  title: string;
  status: "pending" | "active";
  category: string;
  tags: string[];
  sourceText: string;
  summary: string;
  implementationNotes: string;
  analysis?: {
    state?: "unprocessed" | "processing" | "processed" | "needs_review" | "error";
    confidence?: number | null;
    model?: string;
    createdAt?: string;
    updatedAt?: string;
    error?: string;
    submissionId?: string;
    sourceTextSnapshot?: string;
    itemCount?: number;
    items?: Array<{
      title?: string;
      primaryCategory?: string;
      tags?: string[];
      statusRecommendation?: string;
      parsedInterpretation?: string;
      implementationApproach?: string;
      affectedSystems?: string[];
      affectedFiles?: string[];
      problemType?: string;
      rawExcerpt?: string;
      confidence?: number | null;
      notes?: string;
    }>;
  };
  createdAt: string;
  updatedAt: string;
};

type LauncherRequestsPayload = {
  requests?: LauncherRequest[];
};

type RecentSaveEvent = {
  at?: string;
  type?: string;
  requestId?: string;
  textPreview?: string;
  status?: string;
  category?: string;
  itemCount?: number;
  model?: string;
  reason?: string;
  provider?: string;
  pid?: number;
  code?: number | null;
  signal?: string;
  error?: string;
};

type RecentSaveEventsPayload = {
  saves?: RecentSaveEvent[];
};

type ProcessPendingPayload = {
  ok?: boolean;
  launched?: boolean;
  reason?: string;
  autorunEnabled?: boolean;
  configured?: boolean;
  queuedPendingCount?: number;
  pid?: number;
};

type AdminAuthPayload = {
  ok?: boolean;
  accessGranted?: boolean;
  adminConfigured?: boolean;
  error?: string;
};

const DEFAULT_EDITOR_WORLD_ID_FALLBACK = "overworld";

async function resolveDefaultWorldId(): Promise<string> {
  const response = await fetch("/api/world-default");
  if (!response.ok) {
    throw new Error(`Failed to load default world (${response.status}).`);
  }
  const payload = await response.json() as WorldDefaultPayload;
  const resolvedWorldId = String(payload.worldId || payload.world?.id || "").trim();
  return resolvedWorldId || DEFAULT_EDITOR_WORLD_ID_FALLBACK;
}

async function fetchJsonOrThrow<T>(input: RequestInfo | URL, init?: RequestInit): Promise<T> {
  const response = await fetch(input, init);
  if (!response.ok) {
    let detail = `Request failed (${response.status}).`;
    try {
      const payload = await response.json() as { error?: string };
      detail = String(payload?.error || detail);
    } catch {
      // Ignore JSON parse failures and fall back to status text.
    }
    throw new Error(detail);
  }
  return response.json() as Promise<T>;
}

function buildAdminHeaders(password: string, headers?: HeadersInit): HeadersInit {
  const normalizedPassword = String(password || "").trim();
  if (!normalizedPassword) {
    return {
      ...(headers || {}),
    };
  }
  return {
    ...(headers || {}),
    "x-worldshaper-admin-password": normalizedPassword,
  };
}

function isAdminAccessError(error: unknown): boolean {
  const text = String(error || "").toLowerCase();
  return text.includes("admin access denied")
    || text.includes("admin access is not configured");
}

function formatRequestTimestamp(value: string): string {
  const parsed = Date.parse(String(value || ""));
  if (!Number.isFinite(parsed)) {
    return "Saved recently";
  }
  return new Intl.DateTimeFormat(undefined, {
    month: "short",
    day: "numeric",
    hour: "numeric",
    minute: "2-digit",
  }).format(parsed);
}

function formatRequestStatusLabel(status: "pending" | "active"): string {
  return status === "active" ? "Active" : "Pending";
}

function normalizeAnalysisState(value: string | undefined): string {
  return String(value || "").trim().toLowerCase();
}

function formatAnalysisStateLabel(value: string | undefined): string {
  const normalized = normalizeAnalysisState(value);
  if (normalized === "processing") {
    return "Processing";
  }
  if (normalized === "processed") {
    return "Processed";
  }
  if (normalized === "needs_review") {
    return "Needs Review";
  }
  if (normalized === "error") {
    return "Error";
  }
  return "Unprocessed";
}

function getRequestDisplayStateLabel(requestEntry: LauncherRequest): string {
  if (requestEntry.status === "active") {
    return "Active";
  }
  const analysisState = normalizeAnalysisState(requestEntry.analysis?.state);
  if (!analysisState || analysisState === "unprocessed") {
    return "Queued";
  }
  if (analysisState === "needs_review") {
    return "Needs Review";
  }
  if (analysisState === "error") {
    return "Analysis Error";
  }
  if (analysisState === "processed") {
    return "Reviewed";
  }
  return formatAnalysisStateLabel(analysisState);
}

function getRequestDisplayStateClassName(requestEntry: LauncherRequest): string {
  if (requestEntry.status === "active") {
    return "active";
  }
  const analysisState = normalizeAnalysisState(requestEntry.analysis?.state);
  if (!analysisState || analysisState === "unprocessed") {
    return "queued";
  }
  if (analysisState === "needs_review") {
    return "needs-review";
  }
  if (analysisState === "error") {
    return "error";
  }
  if (analysisState === "processed") {
    return "processed";
  }
  if (analysisState === "processing") {
    return "processing";
  }
  return "pending";
}

function isQueuedPendingRequest(requestEntry: LauncherRequest): boolean {
  const analysisState = normalizeAnalysisState(requestEntry.analysis?.state);
  return requestEntry.status === "pending" && (!analysisState || analysisState === "unprocessed" || analysisState === "processing");
}

function isNeedsReviewRequest(requestEntry: LauncherRequest): boolean {
  const analysisState = normalizeAnalysisState(requestEntry.analysis?.state);
  return requestEntry.status === "pending" && (analysisState === "needs_review" || analysisState === "error");
}

function formatEventLabel(event: RecentSaveEvent): string {
  switch (String(event.type || "").trim()) {
    case "launcher-request-add":
      return "Request submitted";
    case "launcher-request-delete":
      return "Request deleted";
    case "launcher-request-update":
      return "Request updated";
    case "launcher-request-review":
      return "Analysis saved for review";
    case "launcher-request-promote":
      return "Pending request promoted";
    case "launcher-request-analysis-error":
      return "Analysis failed";
    case "launcher-request-analysis-launch":
      return "Queue worker launched";
    case "launcher-request-analysis-finish":
      return "Queue worker finished";
    case "launcher-request-analysis-launch-error":
      return "Queue worker launch error";
    default:
      return String(event.type || "Event");
  }
}

function formatEventDetail(event: RecentSaveEvent): string {
  const parts = [
    event.requestId ? `Request ${event.requestId}` : "",
    event.category ? `Category ${event.category}` : "",
    event.status ? `Status ${event.status}` : "",
    event.itemCount ? `${event.itemCount} item${event.itemCount === 1 ? "" : "s"}` : "",
    event.provider ? `Provider ${event.provider}` : "",
    event.model ? `Model ${event.model}` : "",
    event.reason ? `Reason ${event.reason}` : "",
    event.pid ? `PID ${event.pid}` : "",
    Number.isFinite(Number(event.code)) ? `Exit ${event.code}` : "",
    event.signal ? `Signal ${event.signal}` : "",
    event.error ? String(event.error) : "",
    event.textPreview ? `Preview: ${event.textPreview}` : "",
  ].filter(Boolean);
  return parts.join(" • ");
}

function openStudioPopup(worldId: string): boolean {
  const popup = openWorldshaperStudioWindow(worldId, window, { worldId });
  return Boolean(popup);
}

function openRepo(): void {
  window.location.assign("https://repo.andraxion.net/");
}

function WorldshaperLauncher() {
  const [launchState, setLaunchState] = useState<LaunchState>("ready");
  const [status, setStatus] = useState("Launch Worldshaper Studio in its floating window.");
  const [error, setError] = useState("");
  const [worldId, setWorldId] = useState(DEFAULT_EDITOR_WORLD_ID_FALLBACK);
  const [activeBoardTab, setActiveBoardTab] = useState<BoardTab>("news");
  const [requests, setRequests] = useState<LauncherRequest[]>([]);
  const [requestsLoading, setRequestsLoading] = useState(true);
  const [requestsError, setRequestsError] = useState("");
  const [requestDraftOpen, setRequestDraftOpen] = useState(false);
  const [requestDraft, setRequestDraft] = useState("");
  const [requestSubmitting, setRequestSubmitting] = useState(false);
  const [requestMutatingId, setRequestMutatingId] = useState("");
  const [requestFilter, setRequestFilter] = useState("all");
  const [expandedRequestIds, setExpandedRequestIds] = useState<string[]>([]);
  const [adminPanelOpen, setAdminPanelOpen] = useState(false);
  const [adminAccessGranted, setAdminAccessGranted] = useState(false);
  const [adminPassword, setAdminPassword] = useState("");
  const [adminPasswordDraft, setAdminPasswordDraft] = useState("");
  const [adminAuthSubmitting, setAdminAuthSubmitting] = useState(false);
  const [adminPasswordError, setAdminPasswordError] = useState("");
  const [recentSaveEvents, setRecentSaveEvents] = useState<RecentSaveEvent[]>([]);
  const [logsLoading, setLogsLoading] = useState(false);
  const [logsError, setLogsError] = useState("");
  const [queueTriggering, setQueueTriggering] = useState(false);
  const [adminNotice, setAdminNotice] = useState("");

  useEffect(() => {
    let cancelled = false;
    void resolveDefaultWorldId()
      .then((resolvedWorldId) => {
        if (cancelled) {
          return;
        }
        setWorldId(resolvedWorldId);
      })
      .catch(() => {
        if (cancelled) {
          return;
        }
        setWorldId(DEFAULT_EDITOR_WORLD_ID_FALLBACK);
      });

    return () => {
      cancelled = true;
    };
  }, []);

  async function loadRequests(options?: { silent?: boolean }): Promise<void> {
    const silent = options?.silent === true;
    if (!silent) {
      setRequestsLoading(true);
    }
    try {
      const payload = await fetchJsonOrThrow<LauncherRequestsPayload>("/api/launcher-requests");
      setRequests(Array.isArray(payload.requests) ? payload.requests : []);
      setRequestsError("");
    } catch (nextError: unknown) {
      setRequestsError(String(nextError || "Failed to load requests."));
    } finally {
      if (!silent) {
        setRequestsLoading(false);
      }
    }
  }

  async function loadRecentSaveEvents(): Promise<void> {
    setLogsLoading(true);
    try {
      const payload = await fetchJsonOrThrow<RecentSaveEventsPayload>("/api/debug/recent-saves", {
        headers: buildAdminHeaders(adminPassword),
      });
      setRecentSaveEvents(Array.isArray(payload.saves) ? payload.saves : []);
      setLogsError("");
    } catch (nextError: unknown) {
      if (isAdminAccessError(nextError)) {
        setAdminAccessGranted(false);
      }
      setLogsError(String(nextError || "Failed to load admin logs."));
    } finally {
      setLogsLoading(false);
    }
  }

  async function verifyAdminPassword(password: string): Promise<void> {
    const payload = await fetchJsonOrThrow<AdminAuthPayload>("/api/admin/auth-check", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ password }),
    });
    if (!payload.accessGranted) {
      throw new Error(String(payload.error || "Admin access denied."));
    }
  }

  async function refreshAdminData(options?: { includeLogs?: boolean; silentRequests?: boolean }): Promise<void> {
    await loadRequests({ silent: options?.silentRequests === true });
    if (options?.includeLogs && adminAccessGranted && adminPassword) {
      await loadRecentSaveEvents();
    }
  }

  useEffect(() => {
    void loadRequests();
  }, []);

  useEffect(() => {
    if (!adminPanelOpen || !adminAccessGranted || !adminPassword) {
      return;
    }
    void loadRecentSaveEvents();
  }, [adminPanelOpen, adminAccessGranted, adminPassword]);

  useEffect(() => {
    if (activeBoardTab !== "requests") {
      return;
    }
    let cancelled = false;
    const refreshBoard = async (): Promise<void> => {
      try {
        const payload = await fetchJsonOrThrow<LauncherRequestsPayload>("/api/launcher-requests");
        if (!cancelled) {
          setRequests(Array.isArray(payload.requests) ? payload.requests : []);
        }
      } catch {
        // Keep the current list visible during background refresh failures.
      }
      if (!adminPanelOpen || !adminAccessGranted || !adminPassword) {
        return;
      }
      try {
        const payload = await fetchJsonOrThrow<RecentSaveEventsPayload>("/api/debug/recent-saves", {
          headers: buildAdminHeaders(adminPassword),
        });
        if (!cancelled) {
          setRecentSaveEvents(Array.isArray(payload.saves) ? payload.saves : []);
        }
      } catch {
        // Avoid surfacing noisy polling failures in the admin panel.
      }
    };
    const intervalId = window.setInterval(() => {
      void refreshBoard();
    }, 15000);
    return () => {
      cancelled = true;
      window.clearInterval(intervalId);
    };
  }, [activeBoardTab, adminPanelOpen, adminAccessGranted, adminPassword]);

  async function handleLaunch(): Promise<void> {
    setError("");
    const nextWorldId = worldId || DEFAULT_EDITOR_WORLD_ID_FALLBACK;
    setLaunchState("opening");
    setStatus(`Opening Worldshaper Studio for ${nextWorldId}...`);
    try {
      const resolvedWorldId = nextWorldId || await resolveDefaultWorldId().catch(() => DEFAULT_EDITOR_WORLD_ID_FALLBACK);
      setWorldId(resolvedWorldId);
      setStatus(`Opening Worldshaper Studio for ${resolvedWorldId}...`);
      if (openStudioPopup(resolvedWorldId)) {
        setLaunchState("opened");
        setStatus("Worldshaper Studio opened in a separate window.");
        return;
      }
      setLaunchState("blocked");
      setStatus("Your browser blocked the studio window. Use the launch button again after allowing popups.");
    } catch (nextError: unknown) {
      const nextErrorText = String(nextError || "Failed to prepare Worldshaper Studio.");
      setLaunchState("error");
      setError(nextErrorText);
      setStatus("Worldshaper Studio unavailable.");
    }
  }

  async function handleAddRequest(): Promise<void> {
    const text = requestDraft.trim();
    if (!text) {
      setRequestsError("Write a request before saving it.");
      return;
    }
    setRequestSubmitting(true);
    try {
      const payload = await fetchJsonOrThrow<LauncherRequestsPayload>("/api/launcher-requests", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({ text }),
      });
      setRequests(Array.isArray(payload.requests) ? payload.requests : []);
      setRequestDraft("");
      setRequestDraftOpen(false);
      setRequestsError("");
      setAdminNotice("Request saved. The VPS queue worker will pick it up if analysis autorun is enabled.");
      if (adminPanelOpen && adminAccessGranted) {
        void loadRecentSaveEvents();
      }
      window.setTimeout(() => {
        void refreshAdminData({ includeLogs: adminPanelOpen && adminAccessGranted, silentRequests: true });
      }, 3500);
    } catch (nextError: unknown) {
      setRequestsError(String(nextError || "Failed to save request."));
    } finally {
      setRequestSubmitting(false);
    }
  }

  async function handleAdminPanelToggle(): Promise<void> {
    setRequestDraftOpen(false);
    setRequestsError("");
    setLogsError("");
    if (adminPanelOpen) {
      setAdminPanelOpen(false);
      setAdminNotice("");
      return;
    }
    setAdminPanelOpen(true);
    setAdminPasswordError("");
    if (adminAccessGranted && adminPassword) {
      await refreshAdminData({ includeLogs: true, silentRequests: true });
    }
  }

  async function handleAdminUnlock(): Promise<void> {
    const submittedPassword = adminPasswordDraft.trim();
    if (!submittedPassword) {
      setAdminPasswordError("Enter the admin password to continue.");
      return;
    }
    setAdminAuthSubmitting(true);
    setAdminPasswordError("");
    try {
      await verifyAdminPassword(submittedPassword);
      setAdminPassword(submittedPassword);
      setAdminAccessGranted(true);
      setAdminNotice("Admin access granted.");
      await refreshAdminData({ includeLogs: true, silentRequests: true });
    } catch (nextError: unknown) {
      setAdminAccessGranted(false);
      setAdminPassword("");
      setAdminPasswordError(String(nextError || "Failed to unlock the admin panel."));
    } finally {
      setAdminAuthSubmitting(false);
    }
  }

  function handleToggleExpandedRequest(requestId: string): void {
    setExpandedRequestIds((current) => (
      current.includes(requestId)
        ? current.filter((entry) => entry !== requestId)
        : [...current, requestId]
    ));
  }

  async function handleDeleteRequest(requestEntry: LauncherRequest): Promise<void> {
    const confirmed = window.confirm(`Delete this request?\n\n${requestEntry.title}`);
    if (!confirmed) {
      return;
    }
    setRequestMutatingId(requestEntry.id);
    try {
      const payload = await fetchJsonOrThrow<LauncherRequestsPayload>(`/api/launcher-requests/${encodeURIComponent(requestEntry.id)}`, {
        method: "DELETE",
        headers: buildAdminHeaders(adminPassword),
      });
      setRequests(Array.isArray(payload.requests) ? payload.requests : []);
      setRequestsError("");
      setExpandedRequestIds((current) => current.filter((entry) => entry !== requestEntry.id));
      setAdminNotice(`Deleted request "${requestEntry.title}".`);
      if (adminPanelOpen) {
        void loadRecentSaveEvents();
      }
    } catch (nextError: unknown) {
      if (isAdminAccessError(nextError)) {
        setAdminAccessGranted(false);
        setAdminPassword("");
        setAdminPasswordError("Admin access expired. Enter the password again.");
      }
      setRequestsError(String(nextError || "Failed to delete request."));
    } finally {
      setRequestMutatingId("");
    }
  }

  async function handleProcessPendingQueue(): Promise<void> {
    setQueueTriggering(true);
    try {
      const payload = await fetchJsonOrThrow<ProcessPendingPayload>("/api/launcher-requests/process-pending", {
        method: "POST",
        headers: buildAdminHeaders(adminPassword),
      });
      if (payload.launched) {
        setAdminNotice(`Queue worker launched for ${payload.queuedPendingCount ?? 0} pending request${payload.queuedPendingCount === 1 ? "" : "s"}.`);
      } else {
        const reason = String(payload.reason || "no-op");
        if (reason === "no-pending-requests") {
          setAdminNotice("No unprocessed pending requests are waiting in the queue.");
        } else if (reason === "request-analysis-already-running") {
          setAdminNotice("The request analysis worker is already running on the VPS.");
        } else if (reason === "request-analysis-not-configured") {
          setAdminNotice("Request analysis is not configured on the server.");
        } else {
          setAdminNotice(`Queue trigger returned: ${reason}.`);
        }
      }
      await refreshAdminData({ includeLogs: true, silentRequests: true });
      if (payload.launched) {
        window.setTimeout(() => {
          void refreshAdminData({ includeLogs: true, silentRequests: true });
        }, 4200);
      }
    } catch (nextError: unknown) {
      if (isAdminAccessError(nextError)) {
        setAdminAccessGranted(false);
        setAdminPassword("");
        setAdminPasswordError("Admin access expired. Enter the password again.");
      }
      setLogsError(String(nextError || "Failed to trigger the queue worker."));
    } finally {
      setQueueTriggering(false);
    }
  }

  const isBusy = launchState === "opening";
  const requestCount = requests.length;
  const pendingRequestCount = requests.filter((entry) => entry.status === "pending").length;
  const activeRequestCount = requests.filter((entry) => entry.status === "active").length;
  const queuedPendingRequestCount = requests.filter(isQueuedPendingRequest).length;
  const needsReviewRequestCount = requests.filter(isNeedsReviewRequest).length;
  const requestTags = Array.from(new Set(
    requests
      .flatMap((entry) => Array.isArray(entry.tags) ? entry.tags : [])
      .map((entry) => String(entry || "").trim())
      .filter(Boolean),
  )).sort((a, b) => a.localeCompare(b));
  const filteredRequests = requests.filter((entry) => {
    if (requestFilter === "status:pending") {
      return entry.status === "pending";
    }
    if (requestFilter === "status:queued") {
      return isQueuedPendingRequest(entry);
    }
    if (requestFilter === "status:review") {
      return isNeedsReviewRequest(entry);
    }
    if (requestFilter === "status:active") {
      return entry.status === "active";
    }
    if (requestFilter.startsWith("tag:")) {
      const tag = requestFilter.slice(4);
      return entry.status === "active" && entry.tags.includes(tag);
    }
    return true;
  });
  const boardHint = activeBoardTab === "news"
    ? "Latest announcements"
    : `${queuedPendingRequestCount} queued, ${needsReviewRequestCount} review, ${activeRequestCount} active`;

  return (
    <main
      className="launcher-shell"
      style={{ "--launcher-background-image": `url(${launcherBackground})` } as CSSProperties}
    >
      <div className="launcher-stack">
        <section className="launcher-hero-window" aria-labelledby="launcher-studio-title">
          <div className="launcher-changelog-titlebar">
            <div className="launcher-changelog-title">Worldshaper Studio</div>
            <div className="launcher-changelog-hint">Floating editor launch</div>
          </div>
          <div className="launcher-hero-body">
            <div className="launcher-hero-card">
              <div className="changelog-splash-hero launcher-hero-banner">
                <p className="launcher-eyebrow">New RPG</p>
                <h1 className="launcher-title" id="launcher-studio-title">Worldshaper Studio</h1>
                <p className="launcher-status">{status}</p>
              </div>
              <div className="launcher-hero-support">
                {launchState === "blocked" ? (
                  <p className="launcher-hint">
                    Allow the popup, then use the studio button again to launch the floating editor window.
                  </p>
                ) : null}
                {launchState === "opened" ? (
                  <p className="launcher-hint">
                    The studio is open in its own slim window. This page stays behind as your release board and relaunch point.
                  </p>
                ) : null}
                {launchState === "ready" ? (
                  <p className="launcher-hint">
                    The editor is designed to live in its own floating window, so the launcher keeps the first step clean.
                  </p>
                ) : null}
                {error ? <p className="launcher-error">{error}</p> : null}
                <div className="launcher-actions">
                  <button type="button" className="launcher-primary-btn" onClick={() => void handleLaunch()} disabled={isBusy}>
                    Open Floating Studio
                  </button>
                  <button type="button" className="launcher-secondary-btn" onClick={openRepo} disabled={isBusy}>
                    Open Repo
                  </button>
                </div>
              </div>
            </div>
          </div>
        </section>
        <section className="launcher-changelog-window" aria-labelledby="launcher-board-title">
          <div className="launcher-changelog-titlebar">
            <div className="launcher-changelog-title" id="launcher-board-title">Worldshaper Board</div>
            <div className="launcher-changelog-hint">{boardHint}</div>
          </div>
          <div className="launcher-changelog-body">
            <div className="launcher-board-content">
              <div className="launcher-board-tabs">
                <button
                  type="button"
                  className={`launcher-secondary-btn launcher-board-tab ${activeBoardTab === "news" ? "is-active" : ""}`}
                  onClick={() => setActiveBoardTab("news")}
                >
                  News
                </button>
                <button
                  type="button"
                  className={`launcher-secondary-btn launcher-board-tab ${activeBoardTab === "requests" ? "is-active" : ""}`}
                  onClick={() => setActiveBoardTab("requests")}
                >
                  Requests
                </button>
              </div>
              {activeBoardTab === "news" ? (
                <div className="changelog-splash-card">
                  <div className="changelog-splash-hero">
                    <div className="changelog-splash-kicker">{CHANGELOG_SPLASH_KICKER}</div>
                    <div className="changelog-splash-title" id="launcher-whats-new-title">{CHANGELOG_SPLASH_TITLE}</div>
                    <div className="changelog-splash-meta">Release {CHANGELOG_SPLASH_VERSION}</div>
                  </div>
                  <div className="changelog-splash-list">
                    {CHANGELOG_SECTIONS.map((section) => (
                      <section key={section.title} className="changelog-splash-section">
                        <h3 className="changelog-splash-section-title">{section.title}</h3>
                        <ul className="changelog-splash-bullets">
                          {section.items.map((item, index) => {
                            const key = `${section.title}-${index}`;
                            const normalizedItem: ChangelogItem = item;
                            if (typeof normalizedItem === "string") {
                              return <li key={key}>{normalizedItem}</li>;
                            }
                            return (
                              <li key={key}>
                                <div>{normalizedItem.text}</div>
                                {normalizedItem.note ? <div className="changelog-splash-bullet-note">{normalizedItem.note}</div> : null}
                              </li>
                            );
                          })}
                        </ul>
                      </section>
                    ))}
                  </div>
                  <div className="changelog-splash-footer">
                    <div className="changelog-splash-footnote">{CHANGELOG_SPLASH_FOOTNOTE}</div>
                  </div>
                </div>
              ) : (
                <div className="changelog-splash-card">
                  <div className="changelog-splash-hero">
                    <div className="changelog-splash-kicker">Shared Request Board</div>
                    <div className="changelog-splash-title" id="launcher-requests-title">Requests</div>
                    <div className="changelog-splash-meta">
                      {requestCount} saved request{requestCount === 1 ? "" : "s"}: {queuedPendingRequestCount} queued, {needsReviewRequestCount} in review, and {activeRequestCount} active.
                    </div>
                    <div className="launcher-request-hero-actions">
                      <div className="launcher-request-toolbar-buttons">
                        <button
                          type="button"
                          className="launcher-primary-btn"
                          onClick={() => {
                            setAdminPanelOpen(false);
                            setRequestDraftOpen((value) => !value);
                          }}
                          disabled={requestSubmitting}
                        >
                          {requestDraftOpen && !adminPanelOpen ? "Hide Request Form" : "Add New Request"}
                        </button>
                        <button
                          type="button"
                          className={`launcher-secondary-btn ${adminPanelOpen ? "is-active" : ""}`}
                          onClick={() => void handleAdminPanelToggle()}
                        >
                          {adminPanelOpen ? "Hide Admin Panel" : "Admin Panel"}
                        </button>
                      </div>
                      <label className="launcher-request-filter">
                        <span className="launcher-request-filter-label">Filter</span>
                        <select
                          className="launcher-request-filter-select"
                          value={requestFilter}
                          onChange={(event) => setRequestFilter(event.target.value)}
                        >
                          <option value="all">All Requests</option>
                          <option value="status:pending">Pending Requests</option>
                          <option value="status:queued">Queued For Analysis</option>
                          <option value="status:review">Needs Review</option>
                          <option value="status:active">Active Requests</option>
                          {requestTags.map((tag) => (
                            <option key={tag} value={`tag:${tag}`}>{tag}</option>
                          ))}
                        </select>
                      </label>
                    </div>
                  </div>
                  {adminPanelOpen ? (
                    <section className="launcher-request-admin-panel">
                      {!adminAccessGranted ? (
                        <div className="launcher-request-admin-unlock">
                          <div className="launcher-request-admin-kicker">Protected Tools</div>
                          <h3 className="launcher-request-admin-title">Admin Access Required</h3>
                          <p className="launcher-request-admin-copy">
                            Enter the admin password to manage deletions, run the queue worker, and read request logs.
                          </p>
                          <label className="launcher-request-admin-field">
                            <span className="launcher-request-filter-label">Password</span>
                            <input
                              type="password"
                              className="launcher-request-filter-select"
                              value={adminPasswordDraft}
                              onChange={(event) => setAdminPasswordDraft(event.target.value)}
                              onKeyDown={(event) => {
                                if (event.key === "Enter") {
                                  event.preventDefault();
                                  void handleAdminUnlock();
                                }
                              }}
                              placeholder="Enter admin password"
                            />
                          </label>
                          <div className="launcher-request-admin-actions">
                            <button
                              type="button"
                              className="launcher-primary-btn"
                              onClick={() => void handleAdminUnlock()}
                              disabled={adminAuthSubmitting}
                            >
                              {adminAuthSubmitting ? "Unlocking..." : "Unlock Admin Panel"}
                            </button>
                          </div>
                          {adminPasswordError ? <p className="launcher-request-error">{adminPasswordError}</p> : null}
                        </div>
                      ) : (
                        <>
                          <div className="launcher-request-admin-head">
                            <div>
                              <div className="launcher-request-admin-kicker">Moderation Tools</div>
                              <h3 className="launcher-request-admin-title">Admin Panel</h3>
                              <p className="launcher-request-admin-copy">
                                Run the VPS queue worker, review the latest request-analysis events, and manage deletions from one place.
                              </p>
                            </div>
                            <div className="launcher-request-admin-stats">
                              <span>{queuedPendingRequestCount} queued</span>
                              <span>{needsReviewRequestCount} review</span>
                              <span>{pendingRequestCount} pending</span>
                              <span>{activeRequestCount} active</span>
                            </div>
                          </div>
                          <div className="launcher-request-admin-actions">
                            <button
                              type="button"
                              className="launcher-primary-btn"
                              onClick={() => void handleProcessPendingQueue()}
                              disabled={queueTriggering}
                            >
                              {queueTriggering ? "Starting Queue..." : "Run Pending Queue"}
                            </button>
                            <button
                              type="button"
                              className="launcher-secondary-btn"
                              onClick={() => void refreshAdminData({ includeLogs: true, silentRequests: true })}
                              disabled={logsLoading}
                            >
                              {logsLoading ? "Refreshing..." : "Refresh Admin Data"}
                            </button>
                          </div>
                          {adminNotice ? <p className="launcher-request-admin-notice">{adminNotice}</p> : null}
                          {adminPasswordError ? <p className="launcher-request-error">{adminPasswordError}</p> : null}
                          {logsError ? <p className="launcher-request-error">{logsError}</p> : null}
                          <div className="launcher-request-admin-grid">
                            <section className="launcher-request-admin-card">
                              <div className="launcher-request-admin-card-head">
                                <h4 className="launcher-request-admin-card-title">Request Management</h4>
                                <div className="launcher-request-admin-card-hint">Delete actions live here now.</div>
                              </div>
                              <div className="launcher-request-admin-request-list">
                                {requests.map((requestEntry) => {
                                  const isMutating = requestMutatingId === requestEntry.id;
                                  const analysisState = formatAnalysisStateLabel(requestEntry.analysis?.state);
                                  return (
                                    <article key={`admin-${requestEntry.id}`} className="launcher-request-admin-request-row">
                                      <div className="launcher-request-admin-request-copy">
                                        <div className="launcher-request-admin-request-title">{requestEntry.title}</div>
                                        <div className="launcher-request-admin-request-meta">
                                          <span>{formatRequestStatusLabel(requestEntry.status)}</span>
                                          <span>{requestEntry.category}</span>
                                          <span>{analysisState}</span>
                                          <span>{formatRequestTimestamp(requestEntry.updatedAt)}</span>
                                        </div>
                                      </div>
                                      <button
                                        type="button"
                                        className="launcher-request-delete-btn"
                                        onClick={() => void handleDeleteRequest(requestEntry)}
                                        disabled={isMutating}
                                        aria-label={`Delete ${requestEntry.title}`}
                                      >
                                        X
                                      </button>
                                    </article>
                                  );
                                })}
                              </div>
                            </section>
                            <section className="launcher-request-admin-card">
                              <div className="launcher-request-admin-card-head">
                                <h4 className="launcher-request-admin-card-title">Recent Logs</h4>
                                <div className="launcher-request-admin-card-hint">Newest events first.</div>
                              </div>
                              <div className="launcher-request-admin-log-list">
                                {logsLoading && recentSaveEvents.length === 0 ? (
                                  <div className="launcher-request-empty">Loading admin logs...</div>
                                ) : null}
                                {!logsLoading && recentSaveEvents.length === 0 ? (
                                  <div className="launcher-request-empty">No admin logs have been recorded yet.</div>
                                ) : null}
                                {recentSaveEvents.map((eventEntry, index) => (
                                  <article key={`log-${eventEntry.at || index}-${eventEntry.type || "event"}`} className="launcher-request-admin-log-row">
                                    <div className="launcher-request-admin-log-head">
                                      <div className="launcher-request-admin-log-title">{formatEventLabel(eventEntry)}</div>
                                      <div className="launcher-request-admin-log-time">{formatRequestTimestamp(String(eventEntry.at || ""))}</div>
                                    </div>
                                    <div className="launcher-request-admin-log-detail">{formatEventDetail(eventEntry) || "No extra details recorded."}</div>
                                  </article>
                                ))}
                              </div>
                            </section>
                          </div>
                        </>
                      )}
                    </section>
                  ) : null}
                  {requestDraftOpen && !adminPanelOpen ? (
                    <section className="launcher-request-composer">
                      <label className="launcher-request-composer-label" htmlFor="launcher-request-draft">
                        What should be added or improved?
                      </label>
                      <textarea
                        id="launcher-request-draft"
                        className="launcher-request-textarea"
                        value={requestDraft}
                        onChange={(event) => setRequestDraft(event.target.value)}
                        placeholder="Type a request for the board..."
                        maxLength={1000}
                      />
                      <div className="launcher-request-composer-actions">
                        <button
                          type="button"
                          className="launcher-primary-btn"
                          onClick={() => void handleAddRequest()}
                          disabled={requestSubmitting}
                        >
                          {requestSubmitting ? "Saving Request..." : "Save Request"}
                        </button>
                        <button
                          type="button"
                          className="launcher-secondary-btn"
                          onClick={() => {
                            setRequestDraft("");
                            setRequestDraftOpen(false);
                          }}
                          disabled={requestSubmitting}
                        >
                          Cancel
                        </button>
                      </div>
                    </section>
                  ) : null}
                  {!adminPanelOpen ? (
                    <div className="launcher-request-list">
                    {requestsLoading ? (
                      <section className="launcher-request-entry">
                        <div className="launcher-request-empty">Loading saved requests...</div>
                      </section>
                    ) : null}
                    {!requestsLoading && filteredRequests.length === 0 ? (
                      <section className="launcher-request-entry">
                        <div className="launcher-request-empty">
                          {requests.length === 0
                            ? "No requests yet. Add the first one to start the board."
                            : "No requests match the current filter."}
                        </div>
                      </section>
                    ) : null}
                    {!requestsLoading ? filteredRequests.map((requestEntry) => {
                      const isExpanded = expandedRequestIds.includes(requestEntry.id);
                      const isActiveRequest = requestEntry.status === "active";
                      const requestDisplayState = getRequestDisplayStateLabel(requestEntry);
                      const requestDisplayStateClassName = getRequestDisplayStateClassName(requestEntry);
                      const analysisStateLabel = requestEntry.status === "pending"
                        ? formatAnalysisStateLabel(requestEntry.analysis?.state)
                        : "";
                      return (
                        <section
                          key={requestEntry.id}
                          className={`launcher-request-entry is-${requestEntry.status} ${isExpanded ? "is-expanded" : ""} ${isActiveRequest ? "is-clickable" : ""}`}
                          onClick={isActiveRequest ? () => handleToggleExpandedRequest(requestEntry.id) : undefined}
                        >
                          <div className="launcher-request-entry-head">
                            <div className="launcher-request-entry-head-main">
                              <div className={`launcher-request-status-pill is-${requestDisplayStateClassName}`}>
                                {requestDisplayState}
                              </div>
                              <div className="launcher-request-entry-title-block">
                                <h3 className="launcher-request-entry-title">{requestEntry.title}</h3>
                                <div className="launcher-request-entry-category">{requestEntry.category}</div>
                              </div>
                            </div>
                          </div>
                          {requestEntry.tags.length > 0 ? (
                            <div className="launcher-request-tags">
                              {requestEntry.tags.map((tag) => (
                                <span key={`${requestEntry.id}-${tag}`} className="launcher-request-tag">{tag}</span>
                              ))}
                            </div>
                          ) : null}
                          <div className="launcher-request-entry-text">
                            {requestEntry.status === "active" ? requestEntry.summary : requestEntry.sourceText}
                          </div>
                          <div className="launcher-request-entry-meta">
                            {requestEntry.status === "pending" ? `${analysisStateLabel} | ` : ""}
                            {formatRequestTimestamp(requestEntry.updatedAt || requestEntry.createdAt)}
                          </div>
                          {isActiveRequest && isExpanded ? (
                            <div className="launcher-request-expanded">
                              <div className="launcher-request-expanded-block">
                                <div className="launcher-request-expanded-label">Parsed interpretation</div>
                                <p className="launcher-request-expanded-copy">{requestEntry.summary}</p>
                              </div>
                              <div className="launcher-request-expanded-block">
                                <div className="launcher-request-expanded-label">How we could do that</div>
                                <p className="launcher-request-expanded-copy">{requestEntry.implementationNotes}</p>
                              </div>
                              {requestEntry.sourceText ? (
                                <div className="launcher-request-expanded-block">
                                  <div className="launcher-request-expanded-label">Original submission</div>
                                  <p className="launcher-request-expanded-copy">{requestEntry.sourceText}</p>
                                </div>
                              ) : null}
                            </div>
                          ) : null}
                        </section>
                      );
                    }) : null}
                    </div>
                  ) : null}
                  <div className="changelog-splash-footer">
                    <div className="changelog-splash-footnote">
                      Requests are saved and shared from this launcher. Public rows stay focused on the request itself, while moderation tools and logs stay behind protected admin access.
                    </div>
                  </div>
                </div>
              )}
              {requestsError ? (
                <p className="launcher-request-error">{requestsError}</p>
              ) : null}
            </div>
          </div>
        </section>
      </div>
    </main>
  );
}

export default WorldshaperLauncher;
