/* Kestrel dataset loader.
 *
 * Loads `data/kestrel_summary.json` + `data/kestrel_passages.json` at app start
 * and populates the same window globals the rest of the site already reads:
 *   COMPANIES, DISCLOSURES, THEME_AREAS, CSV_LABELS, CSV_SHORT, EVIDENCE_GRADE,
 *   byId(), companyName(), PASSAGES, KESTREL_SUMMARY
 *
 * The file also exposes `useKestrelData()` — a React hook — so <App> can block
 * on the fetch and show a loading shell. Passages stay available under
 * `window.PASSAGES` for the explorer; the summary rollups power dashboards
 * and scorecard charts.
 */

/* ─── Constants: label dictionaries, pillar+theme names ────────────────── */
const CSV_LABELS = {
  'true':  'True shared value',
  'ambig': 'Ambiguous',
  'none':  'No measurable value',
};
const CSV_SHORT = { 'true':'True', 'ambig':'Ambiguous', 'none':'None' };

const EVIDENCE_GRADE = {
  'A':'Independently verified',
  'B':'Third-party reviewed',
  'C':'Self-reported, partial',
  'D':'Unsupported narrative',
};

/* Pillars → human labels (match the analysis schema) */
const PILLAR_LABEL = {
  value_chain:         'Value-chain productivity',
  cluster_development: 'Local cluster development',
  products_markets:    'Products & markets',
  multiple:            'Multiple pillars',
  none:                'No pillar mapping',
};

/* Initiative types → human labels */
const INITIATIVE_LABEL = {
  no_initiative:    'No initiative',
  transactional:    'Transactional',
  transitional:     'Transitional',
  transformational: 'Transformational',
};

/* Linkage / evidence → grades for the disclosure panel rubric.
 * Mapping draws on the Kestrel CSRD schema so what the user sees in the
 * panel is traceable to the codebook. */
const LINKAGE_TO_GRADE   = { quantified:'A', explicit:'B', implied:'C', none:'D', '':'D', null:'D', undefined:'D' };
const EVIDENCE_TO_GRADE  = { strong:'A', moderate:'B', weak:'C', none:'D', '':'D', '3':'B', '2':'C', '1':'D', null:'D', undefined:'D' };
const LABEL_TO_MATERIAL  = { positive:'A', ambiguous:'C', negative:'D' };
const CONF_TO_VERIF      = { high:'A', medium:'B', low:'C', '':'D', null:'D', undefined:'D' };

/* Themes (used in the Explore theme filter). Built from pillar labels so the
 * filter chip always matches the data, plus a small set of common topics for
 * variety in the scorecards. */
const THEME_AREAS = [
  'Value-chain productivity',
  'Local cluster development',
  'Products & markets',
  'Skills & training',
  'Water stewardship',
  'Indigenous agreements',
  'Local procurement',
  'Community infrastructure',
  'Biodiversity',
  'Decarbonisation',
  'Mine closure',
];

/* ─── Empty globals so components mount without errors before the fetch ── */
let COMPANIES = [];
let DISCLOSURES = [];
let PASSAGES = [];
let KESTREL_SUMMARY = null;

const byId = (id) => (window.COMPANIES || []).find(c => c.id === id);
const companyName = (id) => byId(id)?.name ?? id;

/* ─── Mapping helpers ──────────────────────────────────────────────────── */

/* Map a single passage record → the shape the Explore table + DisclosurePanel
 * already consume (was "DISCLOSURES" in the mock). Everything stays 1:1 to
 * the passage so analysts can see every field in the panel. */
function passageToDisclosure(p) {
  const label = p.label_short || 'none';
  const pillar = p.csv_pillar || 'none';
  const theme = PILLAR_LABEL[pillar] || 'No pillar mapping';

  // "Title" — the first line / clause of the passage, capped to keep the
  // table readable. Passages are raw report text; there's no separate title.
  const raw = (p.passage_text || '').replace(/\s+/g, ' ').trim();
  const firstStop = raw.search(/[.!?]\s/);
  const cut = firstStop > 0 && firstStop < 110 ? firstStop + 1 : 110;
  const title = raw.length > cut ? raw.slice(0, cut).replace(/[,; ]+$/, '') + '…' : raw;

  const co = byId(p.company_id);
  const coName = co ? co.name : (p.company || '');
  const year = p.year || '';
  const rtype = p.report_type || '';
  const page = p.page ? `, p.${p.page}` : '';
  const src = `${coName} ${year}${rtype ? ' ' + rtype : ''} report${page}`;

  // Criteria grades from the rubric.
  const measurability = EVIDENCE_TO_GRADE[String(p.evidence_strength ?? '').toLowerCase()] || 'D';
  const linkage       = LINKAGE_TO_GRADE[String(p.linkage_strength ?? '').toLowerCase()] || 'D';
  const materiality   = LABEL_TO_MATERIAL[p.label_primary] || 'D';
  const verification  = CONF_TO_VERIF[String(p.confidence ?? '').toLowerCase()] || 'D';

  return {
    id: p.id,
    co: p.company_id,
    title,
    theme,
    c: label,
    conf: p.confidence_num || 0,
    year,
    src,
    excerpt: raw,
    reasoning: p.justification || '',
    criteria: { materiality, measurability, linkage, verification },
    // extra raw fields kept around so the panel can show the full record
    _raw: p,
  };
}

/* Build the COMPANIES array from the summary JSON in the shape the charts
 * already expect. Keys mirror the mock for a drop-in swap:
 *   n_disc  — number of passages reviewed
 *   t_pct   — % true shared value (positive label)
 *   a_pct   — % ambiguous
 *   n_pct   — % negative / no measurable value
 *   conf    — aggregate confidence 0–100 */
function summaryToCompanies(summary) {
  return (summary.companies || []).map(c => ({
    id: c.id,
    name: c.name,
    country: c.country || '',
    commodity: c.commodity || '',
    short: c.short || '',
    n_disc: c.n_passages,
    t_pct: +(c.positive_pct ?? 0).toFixed(2),
    a_pct: +(c.ambiguous_pct ?? 0).toFixed(2),
    n_pct: +(c.negative_pct ?? 0).toFixed(2),
    conf:  Math.round(c.avg_confidence ?? 0),
    // detailed breakdowns — used by Scorecard charts
    initiative_type: c.initiative_type || {},
    csv_pillar:      c.csv_pillar || {},
    linkage_strength:c.linkage_strength || {},
    evidence_strength:c.evidence_strength || {},
    remediation_flag:c.remediation_flag || {},
    by_year:         c.by_year || {},
  }));
}

/* ─── Fetch + hook ─────────────────────────────────────────────────────── */

let _loadPromise = null;
function loadKestrelData() {
  if (_loadPromise) return _loadPromise;
  _loadPromise = Promise.all([
    fetch('data/kestrel_summary.json').then(r => r.json()),
    fetch('data/kestrel_passages.json').then(r => r.json()),
  ]).then(([summary, passages]) => {
    KESTREL_SUMMARY = summary;
    COMPANIES = summaryToCompanies(summary);
    PASSAGES = passages.passages || [];
    // Also expose classic "DISCLOSURES" globally for existing components.
    DISCLOSURES = PASSAGES.map(passageToDisclosure);
    // push everything back onto window so lookups through globals work
    Object.assign(window, { COMPANIES, DISCLOSURES, PASSAGES, KESTREL_SUMMARY });
    return { summary, passages };
  });
  return _loadPromise;
}

/* React hook — returns { ready, error, summary }. Components above the data
 * boundary (the rest of the site) only read window globals, so once
 * `ready===true` it's safe to render them. */
function useKestrelData() {
  const [state, setState] = React.useState({ ready: false, error: null, summary: null });
  React.useEffect(() => {
    let mounted = true;
    loadKestrelData().then(({ summary }) => {
      if (mounted) setState({ ready: true, error: null, summary });
    }).catch(err => {
      console.error('Kestrel data load failed', err);
      if (mounted) setState({ ready: false, error: err, summary: null });
    });
    return () => { mounted = false; };
  }, []);
  return state;
}

/* Seed window globals with empty arrays immediately so component code that
 * runs before `useKestrelData` resolves doesn't throw on `COMPANIES.map`. */
Object.assign(window, {
  COMPANIES, DISCLOSURES, PASSAGES, KESTREL_SUMMARY,
  CSV_LABELS, CSV_SHORT, EVIDENCE_GRADE,
  PILLAR_LABEL, INITIATIVE_LABEL, THEME_AREAS,
  byId, companyName,
  loadKestrelData, useKestrelData, passageToDisclosure,
});
