// Vite entry. Loads the mock dataset (as fallback), then fetches real
// Salesforce-backed data from the local API and overlays it onto
// window.GBD_DATA before rendering. Existing JSX files reference globals;
// keeping them is the smallest delta from the original design prototype.

import React from 'react';
import { createRoot } from 'react-dom/client';
import * as ReactDOM from 'react-dom/client';

window.React = React;
window.ReactDOM = ReactDOM;

import './styles.css';
import './data.js';            // sets window.GBD_DATA (mock baseline)
import './tweaks-panel.jsx';   // tweaks panel + useTweaks
import './components.jsx';     // sidebar/topbar/charts/map
import './views.jsx';          // Grand overview, Province + Chapter detail
import './pages.jsx';          // Chapters list + secondary pages
import './app.jsx';            // sets window.App

const PROVINCE_SLUGS = {
  'Northeastern Province': 'northeast',
  'Eastern Province': 'eastern',
  'Southeastern Province': 'southeast',
  'Southern Province': 'southern',
  'Southwestern Province': 'southwest',
  'Middle Western Province': 'midwest',
  'Middle Eastern Province': 'middleeast',
  'North Central Province': 'northcentral',
  'South Central Province': 'southcentral',
  'East Central Province': 'eastcentral',
  'Western Province': 'western',
  'Northern Province': 'northern',
};

const j = (u) => fetch(u).then(r => {
  if (!r.ok) throw new Error(`${u} → ${r.status}`);
  return r.json();
});

async function overlayRealData() {
  const D = window.GBD_DATA;
  try {
    const [grand, provinces, chapters, delegates, insurance, spring26, compliance, compliance990, matrix, officer, reclaim, trajectory] = await Promise.all([
      j('/api/grand/totals'),
      j('/api/provinces'),
      j('/api/chapters'),
      j('/api/delegates').catch(() => []),
      j('/api/insurance').catch(() => null),
      j('/api/initiates/spring26').catch(() => []),
      j('/api/990/summary').catch(() => null),
      j('/api/990/chapters').catch(() => []),
      j('/api/grand/chapter-matrix').catch(() => null),
      j('/api/grand/officer-reports').catch(() => null),
      j('/api/grand/reclaim-fy').catch(() => null),
      j('/api/grand/membership-trajectory').catch(() => null),
    ]);

    // Map SF account id → derived 990 status so each chapter row can show it.
    const taxByChapter = new Map(
      (compliance990 || []).map(c => [c.sfId, c.status])
    );

    const nameToSlug = (n) => PROVINCE_SLUGS[n] || (n || 'unknown')
      .toLowerCase().replace(/province/g, '').trim().replace(/\s+/g, '-');

    // Provinces — keep slug ids so existing UI keys still line up.
    D.provinces = provinces.map((p, i) => {
      const slug = nameToSlug(p.name);
      const ch = chapters.filter(c => c.provinceName === p.name);
      const ug = ch.filter(c => c.kind === 'Undergraduate').length;
      const al = ch.filter(c => c.kind === 'Alumni').length;
      const totalMembers = p.members || ch.reduce((s, c) => s + c.members, 0);
      const totalConfirmed = p.confirmedMembers || ch.reduce((s, c) => s + (c.confirmedMembers || 0), 0);
      const duesPct = totalMembers ? Math.round((totalConfirmed / totalMembers) * 100) : 0;
      const insured = ch.filter(c => c.insurancePaid).length;
      const insuredPct = p.insuredPct ?? (ch.length ? Math.round((insured / ch.length) * 100) : 0);
      const uninsuredChapters = p.uninsuredChapters ?? (ch.length - insured);
      return {
        id: slug,
        sfId: p.id,
        name: p.name,
        states: p.states || '',
        polemarch: p.polemarch || '—',
        seat: p.seat || '—',
        founded: p.founded || null,
        chapters: p.chapters || ch.length,
        undergrad: ug,
        alumni: al,
        members: totalMembers,
        confirmedMembers: totalConfirmed,
        duesPct,
        insuredPct,
        uninsuredChapters,
        servicePct: p.servicePct || 0,
        reclamation: p.reclaimed ?? ch.reduce((s, c) => s + c.reclaimed, 0),
        events: 0,
        revenue: p.revenue || Math.round((p.outstandingBalance || 0) / 1000),
        yoy: p.yoy || 0,
        compliant: insuredPct >= 70,
      };
    });

    // Chapters — graft slug-based provinceId for the existing drill UI.
    D.chapters = chapters.map(c => {
      const province = D.provinces.find(p => p.name === c.provinceName);
      return {
        id: c.id,
        sfId: c.id,
        designation: c.designation,
        kind: c.kind,
        provinceId: province?.id || null,
        provinceName: c.provinceName,
        city: c.city || '—',
        host: c.host || (c.kind === 'Alumni' ? 'Alumni Chapter' : 'University'),
        members: c.members,
        confirmedMembers: c.confirmedMembers,
        duesPct: c.members ? Math.round((c.confirmedMembers / c.members) * 100) : 0,
        servicePct: 0,
        eventsYTD: 0,
        reclaimed: c.reclaimed,
        founded: c.founded || null,
        polemarch: c.polemarch || '—',
        scholarshipK: 0,
        risk: c.insurancePaid ? 'ok' : (c.outstandingBalance > 0 ? 'high' : 'watch'),
        outstandingBalance: c.outstandingBalance,
        insurancePaid: c.insurancePaid,
        status: c.status,
        certStatus: c.certStatus,
        rosterStatus: c.rosterStatus,
        leadershipStatus: c.leadershipStatus,
        taxStatus: taxByChapter.get(c.id) || null,
      };
    });

    D.grandTotals = {
      ...D.grandTotals,
      members: grand.members,
      membersDelta: 0,
      activeChapters: grand.activeChapters,
      activeAlumniChapters: grand.activeAlumniChapters,
      activeUgChapters: grand.activeUgChapters,
      chaptersDelta: 0,
      igs: grand.igs,
      ngs: grand.ngs,
      life: grand.life,
      subscribingLife: grand.subscribingLife,
      // IGS sub-totals (Member Type)
      igsAlumni: grand.igsAlumni,
      igsUg: grand.igsUg,
      // IGS sub-totals (Dues Type)
      annualDuesPaying: grand.annualDuesPaying,
      igsLife: grand.igsLife,
      igsSubLife: grand.igsSubLife,
      reclaimed: grand.reclaimed,
      reclaimedFY: grand.reclaimedFY,
      reclaimFYLabel: grand.reclaimFYLabel,
      chapterInvisible: grand.chapterInvisible,
      allTimeInitiates: grand.allTimeInitiates,
      spring26Initiates: grand.spring26Initiates,
      fiftyYearMembers: grand.fiftyYearMembers,
      seventyFiveYearMembers: grand.seventyFiveYearMembers,
      ug: grand.ug,
      alumni: grand.alumni,
      uninsuredChapters: grand.uninsuredChapters,
      insuredPct: grand.activeChapters
        ? Math.round(((grand.activeChapters - grand.uninsuredChapters) / grand.activeChapters) * 100)
        : 0,
    };

    D.chapterMatrix = matrix;
    D.officerReports = officer;
    D.reclaimFY = reclaim;

    D.delegates = delegates;
    D.insurance = insurance;
    D.spring26Initiates = spring26;
    D.compliance990 = compliance;
    if (trajectory) {
      D.membershipTS = trajectory;
    }

    window.__GBD_LIVE__ = true;
  } catch (err) {
    console.warn('[grand-board] Live SF data unavailable, using mock fallback.', err);
    window.__GBD_LIVE__ = false;
  }
}

overlayRealData().finally(() => {
  createRoot(document.getElementById('root')).render(
    React.createElement(window.App)
  );
});
