// info-panel.jsx - below-the-fold explainer: how it works, FAQ, popular B42
// mods, wiki links, hosting card. Loaded before sortof-app.jsx.

const WIKI_BASE = 'https://wiki.indifferentbroccoli.com/en/ProjectZomboid';

const WIKI_GUIDES = [
  { href: 'https://wiki.indifferentbroccoli.com/ProjectZomboid/AddMods',
    label: 'add mods to your server',
    blurb: 'where the three lines go in the ini, and in what order' },
  { href: 'https://wiki.indifferentbroccoli.com/ProjectZomboid/AddMapMods',
    label: 'add map mods',
    blurb: 'Map= is its own line and its own set of rules' },
  { href: 'https://wiki.indifferentbroccoli.com/ProjectZomboid/RemoveMod',
    label: 'remove a mod',
    blurb: 'pulling a mod out without wrecking the save' },
];

// Top 10 by how often each appears in a B42 sort on this site.
// Snapshot: 2026-07-31. Thumbnails are the workshop preview images.
const POPULAR_B42 = [
  { wsid: '3171167894', title: 'that DAMN Library',
    blurb: "KI5's shared framework. Every KI5 vehicle mod needs it, and none of them work without it." },
  { wsid: '3330403100', title: 'Trailers!',
    blurb: 'Towable utility and cargo trailers in three sizes, for hauling loot instead of pocketing it.' },
  { wsid: '2896041179', title: 'errorMagnifier',
    blurb: 'Pops a visible button the moment the game throws an error, so players can actually report it.' },
  { wsid: '3077900375', title: 'Mod Update and Alert System',
    blurb: "Shows mod changelogs and update notices in-game. Optional on B41, required by its author's B42 mods." },
  { wsid: '2503622437', title: 'Skill Recovery Journal',
    blurb: 'A craftable journal that lets your next character recover the skills and recipes the last one died with.' },
  { wsid: '2566953935', title: "'86 Oshkosh P19A + Military Trailers",
    blurb: 'A big drivable airfield fire truck in four variants, plus matching military trailers.' },
  { wsid: '3670064951', title: 'Campers!',
    blurb: 'Campers and towed trailers you can sleep in, sit in and store gear in. Built for nomad runs.' },
  { wsid: '3402491515', title: "Tsar's Common Library B42",
    blurb: "Build 42 port of Tsar's shared asset library. A dependency, not something you use directly." },
  { wsid: '2335368829', title: 'Authentic Z',
    blurb: 'Over 150 outfits handed out to zombies based on where they died, so a hospital looks like a hospital.' },
  { wsid: '3508537032', title: 'NeatUI Framework [B42]',
    blurb: 'Shared UI framework for B42 mods. Install it when something else requires it, and load it before that mod.' },
];

const FAQ_ITEMS = [
  {
    q: 'it says "cache miss" and starts indexing. did it break?',
    a: <>No. That means we've never opened those workshop items before, so
       we're downloading each one to read its <code>mod.info</code>. Wait about
       30 seconds and hit sort again. Every later sort with those mods is
       instant.</>,
  },
  {
    q: 'i pasted the lines and the mods still are not loading',
    a: <>All three lines have to land in the same <code>servertest.ini</code> (or
       whatever your server is named), the server has to be fully stopped when
       you edit it, and the values take no spaces after the <code>=</code>.
       Full walkthrough: <a className="info-link" href={WIKI_GUIDES[0].href}
       target="_blank" rel="noopener noreferrer">add mods to your server</a>.</>,
  },
  {
    q: 'what is a "missing dependency" warning?',
    a: <>A mod declared <code>require=SomethingElse</code> and that something
       else is not in your list. The game will load the mod and then break the
       moment it reaches for the missing code. Use the <strong>[add]</strong>
       button on the warning to drop the required workshop id straight into
       your input, then sort again.</>,
  },
  {
    q: 'my map mod does not show up, or spawns are wrong',
    a: <>Map folders are their own line and their own fight: when two maps claim
       the same cell, the one listed <em>first</em> in <code>Map=</code> wins.
       We put <code>Muldraugh, KY</code> last so vanilla never eats a custom
       cell. Detail: <a className="info-link" href={WIKI_GUIDES[1].href}
       target="_blank" rel="noopener noreferrer">add map mods</a>.</>,
  },
  {
    q: 'half my mods are flagged "build mismatch"',
    a: <>You are sorting on the wrong build. B41 and B42 mods are not
       interchangeable, and Steam tags each item with the build it targets.
       Flip the B41 / B42 toggle and sort again. Some items ship both builds in
       one workshop id; those get a branch picker instead of a warning.</>,
  },
  {
    q: 'two mods have the same mod id',
    a: <>Two separate workshop items ship the same internal mod id, so the game
       loads exactly one of them and silently ignores the other. Keep whichever
       one you actually want and drop the other from your list.</>,
  },
  {
    q: 'does the order of WorkshopItems matter?',
    a: <>No. <code>WorkshopItems=</code> is only the download list. Load order
       comes from <code>Mods=</code>, and map priority from <code>Map=</code>.
       We still emit all three because the server needs all three.</>,
  },
  {
    q: 'i want to drop a mod mid-save',
    a: <>Removing a mod mid-save can strip items, vehicles or whole map cells
       out from under your players. Read <a className="info-link"
       href={WIKI_GUIDES[2].href} target="_blank" rel="noopener noreferrer">remove
       a mod</a> first, then re-sort the shortened list here.</>,
  },
  {
    q: 'i sorted the same list twice and got a different answer',
    a: <>A mod author published an update in between. We key our cache on
       Steam's <code>time_updated</code>, so when a mod changes we re-read its
       <code>mod.info</code> and its declared requirements may have moved.</>,
  },
];

function HowItWorks() {
  return (
    <section className="info-card" aria-labelledby="how-it-works-h">
      <h2 className="info-h" id="how-it-works-h">how it works</h2>
      <p className="info-p">
        Project Zomboid loads mods top to bottom in the order you list them in
        <code> Mods=</code>. Get that order wrong and you get missing textures,
        recipes that never register, and a server that dies on boot with a stack
        trace nobody wants to read. Sorting it by hand is miserable past about
        fifteen mods. So: paste ids, get the three lines.
      </p>
      <ol className="info-steps">
        <li>
          <strong>read</strong>
          <span>For every workshop id we fetch the item's <code>mod.info</code>,
          the small manifest each mod ships. That is where its real mod id,
          its map folders and its declared relationships live.</span>
        </li>
        <li>
          <strong>graph</strong>
          <span>Each mod can say <code>require=</code> (load these before me),
          <code> incompatible=</code> (never load with me), and
          <code> loadFirst</code> / <code>loadLast</code>. Add any sorting rules
          you paste in yourself, and that is a dependency graph.</span>
        </li>
        <li>
          <strong>sort</strong>
          <span>A topological sort walks that graph so nothing loads before
          something it needs. Mods with no opinion about each other keep the
          order you gave them, which is why the same input always gives the same
          output. Tiers run first, then normal, then last, then patches.</span>
        </li>
        <li>
          <strong>emit</strong>
          <span>Three lines out: <code>WorkshopItems=</code> (what to download),
          <code> Mods=</code> (load order), <code>Map=</code> (map folder
          priority). Anything we could not reconcile becomes a warning instead
          of a silent guess.</span>
        </li>
      </ol>
      <p className="info-note">
        The first sort touching a brand-new mod is slow, we have to download it
        to read the manifest. After that it stays cached until its author
        publishes an update, at which point we re-read it automatically.
      </p>
    </section>
  );
}

function Faq() {
  return (
    <section className="info-card" aria-labelledby="faq-h">
      <h2 className="info-h" id="faq-h">faq</h2>
      <div className="faq-list">
        {FAQ_ITEMS.map((item, i) => (
          <details className="faq-item" key={i}>
            <summary className="faq-q">{item.q}</summary>
            <div className="faq-a">{item.a}</div>
          </details>
        ))}
      </div>
    </section>
  );
}

function PopularB42({ onLoadWsids }) {
  return (
    <section className="info-card" aria-labelledby="popular-h">
      <h2 className="info-h" id="popular-h">10 most-sorted b42 mods</h2>
      <p className="info-p info-p-tight">
        Counted across every B42 sort run on this site, most recent snapshot.
        Not a recommendation, just what people actually run.
      </p>
      <ol className="popular-list">
        {POPULAR_B42.map((m, i) => (
          <li className="popular-row" key={m.wsid}>
            <span className="popular-rank" aria-hidden="true">{i + 1}</span>
            <img
              className="popular-thumb"
              src={`/img/mods/${m.wsid}.png`}
              alt=""
              loading="lazy"
              width="48" height="48"
            />
            <a
              className="popular-title"
              href={`https://steamcommunity.com/sharedfiles/filedetails/?id=${m.wsid}`}
              target="_blank" rel="noopener noreferrer"
            >{m.title}</a>
            <span className="popular-note">{m.blurb}</span>
          </li>
        ))}
      </ol>
      {onLoadWsids && (
        <button
          type="button"
          className="copy-btn popular-load"
          onClick={() => onLoadWsids(POPULAR_B42.map(m => m.wsid))}
        >load all 10 into the box</button>
      )}
    </section>
  );
}

function WikiLinks() {
  return (
    <section className="info-card" aria-labelledby="wiki-h">
      <h2 className="info-h" id="wiki-h">server guides</h2>
      <p className="info-p info-p-tight">
        The longer how-tos live on the{' '}
        <a className="info-link" href={WIKI_BASE} target="_blank" rel="noopener noreferrer">
          Project Zomboid wiki
        </a>.
      </p>
      <ul className="wiki-list">
        {WIKI_GUIDES.map(g => (
          <li key={g.href}>
            <a className="wiki-link" href={g.href} target="_blank" rel="noopener noreferrer">
              {g.label} <span aria-hidden="true">→</span>
            </a>
            <span className="wiki-blurb">{g.blurb}</span>
          </li>
        ))}
      </ul>
    </section>
  );
}

function HostingCard() {
  return (
    <aside className="hosting-card" aria-labelledby="hosting-h">
      <img
        className="hosting-art"
        src="/img/pz-hosting.jpg"
        alt=""
        loading="lazy"
        width="560" height="560"
      />
      <div className="hosting-body">
        <div className="hosting-head">
          <img
            className="hosting-icon"
            src="/img/broccoli_shadow_square.png"
            alt=""
            loading="lazy"
            width="32" height="32"
          />
          <h2 className="hosting-h" id="hosting-h">run your own pz server</h2>
        </div>
        <p className="hosting-p">
          If you don't already have a server to paste these lines into,
          Indifferent Broccoli rents Project Zomboid servers. No port
          forwarding, and the mod lines go in the same three fields.
        </p>
        <a
          className="hosting-cta"
          href="https://indifferentbroccoli.com/project-zomboid-server-hosting"
          target="_blank" rel="noopener noreferrer"
        >see pz server pricing <span aria-hidden="true">→</span></a>
      </div>
    </aside>
  );
}

// Right rail, rendered as the third column of main on wide screens.
function InfoRail({ onLoadWsids }) {
  return (
    <>
      <HostingCard />
      <PopularB42 onLoadWsids={onLoadWsids} />
      <WikiLinks />
    </>
  );
}

// Full-width prose, rendered below main.
function InfoSections() {
  return (
    <div className="info-sections">
      <HowItWorks />
      <Faq />
    </div>
  );
}

Object.assign(window, { InfoRail, InfoSections });
