// Hub Report — generates a print-ready HTML document from the user's live
// Assets / Routines / Contacts data and opens it in a new tab with the
// browser's Print dialog primed for "Save as PDF". No libraries, no network.
//
// Public API: window.HubReport.open()  →  opens the report in a new window.

(function () {
  // ---------- small helpers ----------
  const esc = s => String(s == null ? '' : s)
    .replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;').replace(/'/g, '&#39;');
  const blank = v => v == null || v === '' || v === '—' || v === '? gap';
  const dash = v => blank(v) ? '—' : esc(v);
  const dashRaw = v => blank(v) ? '—' : v;

  const A = () => (window.ASSETS || []);
  const R = () => (window.ROUTINES || []);
  const C = () => (window.CONTACTS || []);

  const findA = id => A().find(x => x.id === id);
  const findC = id => C().find(x => x.id === id);

  function fmtDateLong(d) {
    return d.toLocaleDateString('en-US',
      { weekday: 'long', month: 'long', day: 'numeric', year: 'numeric' });
  }
  function fmtDateShort(iso) {
    if (!iso) return '—';
    const d = new Date(iso + 'T00:00:00');
    if (isNaN(d)) return '—';
    return d.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' });
  }

  // Contacts attached to an asset (via routine OR explicit contact.assets[]).
  function contactsForAsset(assetId) {
    const ids = new Set();
    R().filter(r => r.asset === assetId && r.contact).forEach(r => ids.add(r.contact));
    C().forEach(c => { if ((c.assets || []).includes(assetId)) ids.add(c.id); });
    return [...ids].map(findC).filter(Boolean);
  }
  // Assets attached to a contact (via routine OR contact.assets[]).
  function assetsForContact(contactId) {
    const ids = new Set();
    R().filter(r => r.contact === contactId && r.asset).forEach(r => ids.add(r.asset));
    const c = findC(contactId);
    if (c && c.assets) c.assets.forEach(id => ids.add(id));
    return [...ids].map(findA).filter(Boolean);
  }

  // ---------- section builders ----------
  function coverHTML(household, counts, now) {
    const subtitle = household.location ? esc(household.location) : 'Home record · Generated by Home Hub';
    return `
      <section class="cover">
        <div class="cover-eyebrow">HOME HUB</div>
        <h1 class="cover-title">${esc(household.name || 'Household')}</h1>
        <div class="cover-sub">${subtitle}</div>
        <div class="cover-rule"></div>
        <dl class="cover-meta">
          <div><dt>Report date</dt><dd>${esc(fmtDateLong(now))}</dd></div>
          <div><dt>Assets on record</dt><dd>${counts.assets}</dd></div>
          <div><dt>Routines tracked</dt><dd>${counts.routines}</dd></div>
          <div><dt>Contacts on file</dt><dd>${counts.contacts}</dd></div>
        </dl>
        <div class="cover-foot">
          This report is a snapshot of everything you've recorded in Home Hub as of the
          date above. Keep it with your property documents, share it with a partner, or
          hand it off when the home changes hands.
        </div>
      </section>
    `;
  }

  function assetRow(a) {
    const linkedRoutines = R().filter(r => r.asset === a.id);
    const linkedContacts = contactsForAsset(a.id);
    const facts = [
      ['Make',   dashRaw(a.make)],
      ['Model',  dashRaw(a.model)],
      ['Year',   dashRaw(a.year)],
      ['Serial', dashRaw(a.serial)],
    ];
    return `
      <article class="row">
        <header class="row-head">
          <h3>${dash(a.name)}</h3>
          <span class="row-tag">${dash(a.cat)}</span>
        </header>
        <dl class="kv">
          ${facts.map(([k, v]) =>
            `<div><dt>${k}</dt><dd>${esc(v)}</dd></div>`).join('')}
        </dl>
        ${a.notes ? `<p class="row-notes">${esc(a.notes)}</p>` : ''}
        <div class="row-links">
          <div>
            <span class="row-links-label">Routines</span>
            ${linkedRoutines.length
              ? `<ul>${linkedRoutines.map(r =>
                  `<li>${esc(r.task)} <span class="muted">· ${esc(r.freq || '—')} · next ${esc(r.nextLabel || '—')}</span></li>`
                ).join('')}</ul>`
              : `<span class="muted">None tracked</span>`}
          </div>
          <div>
            <span class="row-links-label">Contacts</span>
            ${linkedContacts.length
              ? `<ul>${linkedContacts.map(c =>
                  `<li>${esc(c.co || '—')} <span class="muted">· ${esc(c.cat || '')}</span></li>`
                ).join('')}</ul>`
              : `<span class="muted">None linked</span>`}
          </div>
        </div>
      </article>
    `;
  }

  function assetsSectionHTML() {
    const all = A();
    if (!all.length) return emptySection('Assets', 'No assets have been added yet.');
    const groups = {};
    all.forEach(a => { (groups[a.cat || 'Uncategorized'] ||= []).push(a); });
    const cats = Object.keys(groups).sort();
    return `
      <section class="sheet">
        ${sectionHead('Assets', `${all.length} item${all.length === 1 ? '' : 's'}`)}
        ${cats.map(cat => `
          <div class="group">
            <h2 class="group-head">${esc(cat)} <span class="group-count">${groups[cat].length}</span></h2>
            ${groups[cat].map(assetRow).join('')}
          </div>
        `).join('')}
      </section>
    `;
  }

  function routineRow(r) {
    const asset = r.asset ? findA(r.asset) : null;
    const contact = r.contact ? findC(r.contact) : null;
    return `
      <article class="row">
        <header class="row-head">
          <h3>${dash(r.task)}</h3>
          <span class="row-tag tag-${esc(r.status || 'ok')}">${esc(r.nextLabel || 'Not scheduled')}</span>
        </header>
        <dl class="kv">
          <div><dt>Asset</dt><dd>${asset ? esc(asset.name) : '—'}</dd></div>
          <div><dt>Frequency</dt><dd>${dash(r.freq)}</dd></div>
          <div><dt>Season</dt><dd>${dash(r.season)}</dd></div>
          <div><dt>Performed by</dt><dd>${dash(r.who)}</dd></div>
          <div><dt>Next due</dt><dd>${esc(fmtDateShort(r.date))}</dd></div>
          <div><dt>Contact</dt><dd>${contact ? esc(contact.co || '—') : '—'}</dd></div>
        </dl>
        ${r.notes ? `<p class="row-notes">${esc(r.notes)}</p>` : ''}
      </article>
    `;
  }

  function routinesSectionHTML() {
    const all = R();
    if (!all.length) return emptySection('Routines', 'No routines have been scheduled yet.');
    const buckets = { overdue: [], soon: [], ok: [], unscheduled: [] };
    all.forEach(r => {
      const unscheduled = !r.date || !r.nextLabel ||
        ['Not scheduled', 'Unscheduled', 'TBD', '—', ''].includes(r.nextLabel);
      if (unscheduled) buckets.unscheduled.push(r);
      else if (r.status === 'overdue') buckets.overdue.push(r);
      else if (r.status === 'soon')    buckets.soon.push(r);
      else                             buckets.ok.push(r);
    });
    const order = [
      ['overdue',     'Overdue'],
      ['soon',        'Due soon'],
      ['ok',          'Scheduled'],
      ['unscheduled', 'Unscheduled'],
    ];
    // Sort each bucket by date asc (nulls last).
    Object.values(buckets).forEach(arr =>
      arr.sort((a, b) => (a.date || '9999').localeCompare(b.date || '9999')));
    return `
      <section class="sheet">
        ${sectionHead('Routines', `${all.length} task${all.length === 1 ? '' : 's'}`)}
        ${order.map(([key, label]) => buckets[key].length ? `
          <div class="group">
            <h2 class="group-head">${label} <span class="group-count">${buckets[key].length}</span></h2>
            ${buckets[key].map(routineRow).join('')}
          </div>
        ` : '').join('')}
      </section>
    `;
  }

  function contactRow(c) {
    const linkedAssets = assetsForContact(c.id);
    const ppl = (c.people || []).filter(p => p.name || p.phone || p.email);
    return `
      <article class="row">
        <header class="row-head">
          <h3>${dash(c.co)}</h3>
          <span class="row-tag">${dash(c.cat)}</span>
        </header>
        ${ppl.length ? `
          <div class="people">
            ${ppl.map(p => `
              <div class="person">
                <div class="person-name">${dash(p.name)}${p.role ? ` <span class="muted">· ${esc(p.role)}</span>` : ''}</div>
                <div class="person-cont">
                  ${blank(p.phone) ? '' : `<span>${esc(p.phone)}</span>`}
                  ${blank(p.email) ? '' : `<span>${esc(p.email)}</span>`}
                </div>
              </div>
            `).join('')}
          </div>
        ` : '<p class="muted small">No people on this record.</p>'}
        ${c.notes ? `<p class="row-notes">${esc(c.notes)}</p>` : ''}
        <div class="row-links single">
          <div>
            <span class="row-links-label">Linked assets</span>
            ${linkedAssets.length
              ? `<ul>${linkedAssets.map(a => `<li>${esc(a.name)} <span class="muted">· ${esc(a.cat || '')}</span></li>`).join('')}</ul>`
              : `<span class="muted">None linked</span>`}
          </div>
        </div>
      </article>
    `;
  }

  function contactsSectionHTML() {
    const all = C();
    if (!all.length) return emptySection('Contacts', 'No contacts have been added yet.');
    const groups = {};
    all.forEach(c => { (groups[c.cat || 'Uncategorized'] ||= []).push(c); });
    const cats = Object.keys(groups).sort();
    return `
      <section class="sheet">
        ${sectionHead('Contacts', `${all.length} contact${all.length === 1 ? '' : 's'}`)}
        ${cats.map(cat => `
          <div class="group">
            <h2 class="group-head">${esc(cat)} <span class="group-count">${groups[cat].length}</span></h2>
            ${groups[cat].map(contactRow).join('')}
          </div>
        `).join('')}
      </section>
    `;
  }

  function sectionHead(title, sub) {
    return `
      <header class="section-head">
        <div class="section-eyebrow">SECTION</div>
        <h1 class="section-title">${esc(title)}</h1>
        <div class="section-sub">${esc(sub)}</div>
      </header>
    `;
  }
  function emptySection(title, msg) {
    return `
      <section class="sheet">
        ${sectionHead(title, '0 items')}
        <p class="empty">${esc(msg)}</p>
      </section>
    `;
  }

  // ---------- Document shell + print CSS ----------
  function reportHTML() {
    const household = window.HOUSEHOLD || { name: 'Household', location: '' };
    const counts = { assets: A().length, routines: R().length, contacts: C().length };
    const now = new Date();
    const title = `${household.name || 'Home Hub'} — Home Record`;
    return `<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>${esc(title)}</title>
<link href="https://fonts.googleapis.com/css2?family=Source+Serif+4:opsz,wght@8..60,400;8..60,600;8..60,700&family=Inter:wght@400;500;600&display=swap" rel="stylesheet"/>
<style>
  :root {
    --ink: #1f2226;
    --ink-soft: #5d6470;
    --rule: #d9dbe0;
    --rule-soft: #ecedf0;
    --accent: #2b5d3a;
    --tag-bg: #f1f0eb;
    --overdue: #a03426;
    --soon: #b56b1e;
    --ok: #2b5d3a;
  }
  * { box-sizing: border-box; }
  html, body { margin: 0; padding: 0; background: #f3f1ec; color: var(--ink); }
  body { font-family: 'Inter', -apple-system, system-ui, sans-serif; font-size: 11pt; line-height: 1.45; }

  /* Toolbar — shown on screen only */
  .toolbar {
    position: sticky; top: 0; z-index: 10;
    background: #1f2226; color: #fff;
    padding: 12px 24px; display: flex; align-items: center; gap: 16px;
    font-size: 13px;
  }
  .toolbar b { font-weight: 600; }
  .toolbar .grow { flex: 1; }
  .toolbar button {
    background: #fff; color: #1f2226; border: 0;
    padding: 8px 14px; border-radius: 8px; font: inherit; font-weight: 600;
    cursor: pointer;
  }
  .toolbar button.ghost {
    background: transparent; color: #fff; border: 1px solid rgba(255,255,255,0.3);
  }
  .toolbar .hint { color: #a8acb3; font-size: 12px; }

  /* Each printable page */
  .sheet, .cover {
    width: 8.5in; min-height: 11in;
    margin: 24px auto;
    padding: 0.7in 0.65in 0.75in;
    background: #fff;
    box-shadow: 0 8px 28px rgba(0,0,0,0.08);
    page-break-after: always;
  }
  .cover { display: flex; flex-direction: column; }

  /* COVER */
  .cover-eyebrow {
    font-family: 'Inter', sans-serif; font-size: 10pt; letter-spacing: 0.18em;
    color: var(--ink-soft); margin-top: 1in;
  }
  .cover-title {
    font-family: 'Source Serif 4', Georgia, serif;
    font-size: 56pt; font-weight: 600; line-height: 1.02;
    margin: 18px 0 8px; letter-spacing: -0.01em;
  }
  .cover-sub { color: var(--ink-soft); font-size: 13pt; }
  .cover-rule { height: 1px; background: var(--rule); margin: 36px 0 28px; }
  .cover-meta { margin: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 18px 36px; }
  .cover-meta div { margin: 0; }
  .cover-meta dt { font-size: 9pt; letter-spacing: 0.1em; color: var(--ink-soft); text-transform: uppercase; margin-bottom: 2px; }
  .cover-meta dd { margin: 0; font-size: 14pt; font-family: 'Source Serif 4', serif; font-weight: 600; }
  .cover-foot { margin-top: auto; color: var(--ink-soft); font-size: 10.5pt; max-width: 5.5in; line-height: 1.55; }

  /* Section heads */
  .section-head { border-bottom: 1px solid var(--rule); padding-bottom: 14px; margin-bottom: 22px; }
  .section-eyebrow { font-size: 9pt; letter-spacing: 0.18em; color: var(--ink-soft); }
  .section-title { font-family: 'Source Serif 4', serif; font-weight: 600; font-size: 34pt; margin: 6px 0 2px; letter-spacing: -0.01em; }
  .section-sub { color: var(--ink-soft); font-size: 11pt; }

  /* Group */
  .group { margin-bottom: 22px; break-inside: avoid; }
  .group-head {
    font-family: 'Source Serif 4', serif; font-weight: 600;
    font-size: 15pt; margin: 18px 0 10px;
    display: flex; align-items: baseline; gap: 10px;
    border-bottom: 1px solid var(--rule-soft); padding-bottom: 6px;
  }
  .group-count {
    font-family: 'Inter', sans-serif; font-size: 10pt; font-weight: 500;
    color: var(--ink-soft);
  }

  /* Row */
  .row { break-inside: avoid; padding: 12px 0 14px; border-bottom: 1px solid var(--rule-soft); }
  .row:last-child { border-bottom: 0; }
  .row-head { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; margin-bottom: 8px; }
  .row-head h3 { margin: 0; font-family: 'Source Serif 4', serif; font-size: 13.5pt; font-weight: 600; }
  .row-tag {
    font-size: 9.5pt; font-weight: 500;
    background: var(--tag-bg); color: var(--ink-soft);
    padding: 3px 9px; border-radius: 4px; white-space: nowrap;
  }
  .tag-overdue { background: #f5e1de; color: var(--overdue); }
  .tag-soon    { background: #f7ead2; color: var(--soon); }
  .tag-ok      { background: #e2ebe4; color: var(--ok); }

  .kv {
    margin: 0 0 6px; display: grid; grid-template-columns: 1fr 1fr;
    gap: 4px 24px;
  }
  .kv > div { margin: 0; display: flex; gap: 8px; font-size: 10.5pt; }
  .kv dt { color: var(--ink-soft); min-width: 80px; }
  .kv dd { margin: 0; font-weight: 500; }

  .row-notes {
    margin: 8px 0 6px; padding-left: 12px;
    border-left: 2px solid var(--rule); color: var(--ink-soft);
    font-style: italic; font-size: 10.5pt;
  }

  .row-links { display: grid; grid-template-columns: 1fr 1fr; gap: 16px 24px; margin-top: 8px; }
  .row-links.single { grid-template-columns: 1fr; }
  .row-links-label {
    display: block; font-size: 9pt; letter-spacing: 0.1em;
    text-transform: uppercase; color: var(--ink-soft); margin-bottom: 4px;
  }
  .row-links ul { margin: 0; padding-left: 16px; font-size: 10.5pt; }
  .row-links li { margin-bottom: 2px; }

  .people { margin: 4px 0 6px; display: grid; gap: 6px; }
  .person { display: flex; justify-content: space-between; gap: 16px; font-size: 10.5pt; }
  .person-name { font-weight: 500; }
  .person-cont { color: var(--ink-soft); display: flex; gap: 14px; }

  .muted { color: var(--ink-soft); }
  .small { font-size: 10pt; }
  .empty { color: var(--ink-soft); font-style: italic; padding: 24px 0; }

  /* Print: drop the toolbar + shadow, let pages flow naturally */
  @page { size: Letter; margin: 0.5in; }
  @media print {
    body { background: #fff; }
    .toolbar { display: none; }
    .sheet, .cover {
      width: auto; min-height: 0; margin: 0; padding: 0;
      box-shadow: none; page-break-after: always;
    }
    .sheet:last-child, .cover:last-child { page-break-after: auto; }
    .cover-foot { margin-top: 48px; } /* no flex stretch in print */
  }
</style>
</head>
<body>
  <div class="toolbar">
    <b>${esc(title)}</b>
    <span class="hint">Use your browser's print dialog → <b>Save as PDF</b>.</span>
    <span class="grow"></span>
    <button onclick="window.print()">Save as PDF</button>
    <button class="ghost" onclick="window.close()">Close</button>
  </div>
  ${coverHTML(household, counts, now)}
  ${assetsSectionHTML()}
  ${routinesSectionHTML()}
  ${contactsSectionHTML()}
  <script>
    // Auto-open the print dialog once fonts have settled.
    window.addEventListener('load', () => {
      const fire = () => setTimeout(() => window.print(), 350);
      if (document.fonts && document.fonts.ready) document.fonts.ready.then(fire);
      else fire();
    });
  <\/script>
</body>
</html>`;
  }

  // ---------- public ----------
  function open() {
    const html = reportHTML();
    const w = window.open('', '_blank');
    if (!w) {
      alert('Pop-up blocked. Please allow pop-ups for this page to download the report.');
      return;
    }
    w.document.open();
    w.document.write(html);
    w.document.close();
  }

  function totalRecords() {
    return A().length + R().length + C().length;
  }

  window.HubReport = { open, totalRecords };
})();
