// Global period selector + saved-views support.
//
// Exports:
//   window.useGlobalPeriod(companyProfile)   — React hook returning
//       { state, setState, resolved, savedViews, save, deleteView, refresh }
//   window.GlobalPeriodSelector              — UI dropdown component
//   window.BusinessProfilePage               — Settings → Business Profile
//
// The hook persists the current state to localStorage keyed by company id so
// every page renders the same period until the user changes it.

const { useState: useGP_useState, useEffect: useGP_useEffect, useRef: useGP_useRef, useMemo: useGP_useMemo } = React;

// ── localStorage helpers ────────────────────────────────────────────────
function gpStorageKey(companyId) { return `perdura.globalPeriod.${companyId || "demo"}`; }

function loadStoredState(companyId) {
  try {
    const raw = localStorage.getItem(gpStorageKey(companyId));
    if (!raw) return null;
    const parsed = JSON.parse(raw);
    if (parsed && typeof parsed === "object" && parsed.period) return parsed;
  } catch (_) { /* ignore */ }
  return null;
}
function persistState(companyId, state) {
  try { localStorage.setItem(gpStorageKey(companyId), JSON.stringify(state)); } catch (_) { /* ignore */ }
}

// ── Hook: useGlobalPeriod ───────────────────────────────────────────────
function useGlobalPeriod(companyProfile) {
  const companyId = companyProfile?.id || null;
  const fyStart = companyProfile?.fiscal_year_start_month || legacyMonthToNum(companyProfile?.fiscal_year_start) || 1;

  const [state, setStateInner] = useGP_useState(() =>
    loadStoredState(companyId) || window.PerduraPeriod.defaultState()
  );
  const [savedViews, setSavedViews] = useGP_useState([]);
  const [hasBudget, setHasBudget] = useGP_useState(false);
  // dataBounds = the real min/max posted_date of this company's gl_transactions.
  // We pull this so presets resolve against the data, not against today —
  // a customer whose latest sync ends six months ago shouldn't land on an
  // empty current window when they pick "This month" or "TTM".
  const [dataBounds, setDataBounds] = useGP_useState(null);

  // Persist whenever state changes
  useGP_useEffect(() => { persistState(companyId, state); }, [state, companyId]);

  // Reload state from storage when companyId changes (admin switching customers)
  useGP_useEffect(() => {
    const stored = loadStoredState(companyId);
    if (stored) setStateInner(stored);
    else setStateInner(window.PerduraPeriod.defaultState());
  }, [companyId]);

  // Load saved views from Supabase
  const refresh = async () => {
    const db = window.supabaseClient;
    if (!db || !companyId) { setSavedViews([]); return; }
    const { data } = await db.from("saved_views")
      .select("id, name, definition, user_id, created_at")
      .eq("company_id", companyId)
      .order("created_at", { ascending: true });
    setSavedViews(data || []);
  };

  useGP_useEffect(() => { refresh(); }, [companyId]);

  // Fetch min/max posted_date so we can anchor presets to real data.
  useGP_useEffect(() => {
    if (!companyId) { setDataBounds(null); return; }
    const db = window.supabaseClient;
    if (!db) return;
    (async () => {
      try {
        const [{ data: mx }, { data: mn }] = await Promise.all([
          db.from("gl_transactions").select("posted_date").eq("company_id", companyId)
            .order("posted_date", { ascending: false }).limit(1).maybeSingle(),
          db.from("gl_transactions").select("posted_date").eq("company_id", companyId)
            .order("posted_date", { ascending: true }).limit(1).maybeSingle(),
        ]);
        if (mx?.posted_date && mn?.posted_date) {
          setDataBounds({ min: mn.posted_date, max: mx.posted_date });
        } else {
          setDataBounds(null);
        }
      } catch (_) { setDataBounds(null); }
    })();
  }, [companyId]);

  // Auto-default the period to a window that *actually contains data*.
  // Respect the user's stored choice; only intervene on first load. We pick
  // the narrowest preset that still covers >= 1 month of data:
  //   • If the data's max is older than this calendar month, the trailing
  //     window built from "today" would be entirely empty — fall back to
  //     "all_time" so the customer sees their historical numbers.
  //   • Otherwise default to "ttm" (trailing 12 months) so KPIs never read
  //     $0 just because today is mid-month or the latest data is partial.
  //   • Comparison defaults to prior_period (matches the legacy MTD/YTD
  //     experience).
  useGP_useEffect(() => {
    if (!dataBounds?.max) return;
    if (loadStoredState(companyId)) return; // user has chosen a period; respect it
    const now = new Date();
    const mx  = new Date(dataBounds.max);
    const firstOfThisMonth = new Date(now.getFullYear(), now.getMonth(), 1);
    const preset = mx < firstOfThisMonth ? "all_time" : "ttm";
    setStateInner({
      period: { kind: "preset", preset },
      compare: { kind: "prior_period" },
    });
  }, [dataBounds?.max, companyId]);

  // Check whether the company has any budget data. Hidden behind a try/catch so
  // a missing table doesn't break the period selector.
  useGP_useEffect(() => {
    if (!companyId) { setHasBudget(false); return; }
    const db = window.supabaseClient;
    if (!db) return;
    (async () => {
      try {
        // We don't have a budgets table yet, so this always returns false.
        // Leaving the hook here so it switches on automatically once one is added.
        setHasBudget(false);
      } catch (_) { setHasBudget(false); }
    })();
  }, [companyId]);

  const resolved = useGP_useMemo(() => {
    // Anchor "now" to max(posted_date) when it's older than the current
    // calendar month, so presets like TTM / This month / YTD land on the
    // most-recent real window for this company.
    let nowOpt = undefined;
    if (dataBounds?.max) {
      const today = new Date();
      const firstOfThisMonth = new Date(today.getFullYear(), today.getMonth(), 1);
      const mx = new Date(dataBounds.max);
      if (mx < firstOfThisMonth) nowOpt = mx;
    }
    return window.PerduraPeriod.resolve(state, {
      fiscalYearStartMonth: fyStart, hasBudget, now: nowOpt,
    });
  }, [state, fyStart, hasBudget, dataBounds?.max]);

  const save = async (name) => {
    const db = window.supabaseClient;
    if (!db || !companyId) return null;
    const { data: { user } } = await db.auth.getUser();
    const { data, error } = await db.from("saved_views").insert({
      company_id: companyId,
      user_id: user?.id || null,
      name,
      definition: window.PerduraPeriod.serialize(state),
    }).select().single();
    if (error) return null;
    setSavedViews(v => [...v, data]);
    return data;
  };

  const deleteView = async (id) => {
    const db = window.supabaseClient;
    if (!db) return;
    await db.from("saved_views").delete().eq("id", id);
    setSavedViews(v => v.filter(x => x.id !== id));
  };

  const setState = (next) => setStateInner(typeof next === "function" ? next : next);

  return { state, setState, resolved, savedViews, save, deleteView, refresh,
           fiscalYearStartMonth: fyStart, hasBudget, dataBounds };
}

function legacyMonthToNum(name) {
  if (!name) return null;
  const idx = window.PerduraPeriod.helpers.MONTH_NAMES.indexOf(name);
  return idx >= 0 ? idx + 1 : null;
}

// ── UI: Custom range picker ────────────────────────────────────────────
function CustomRangeFields({ state, onChange }) {
  const cur = state.period;
  const startYM = cur.startYear ? { year: cur.startYear, month1: cur.startMonth } : { year: new Date().getFullYear(), month1: new Date().getMonth() + 1 };
  const endYM   = cur.endYear   ? { year: cur.endYear,   month1: cur.endMonth }   : startYM;
  const monthOpts = [];
  for (let i = 0; i < 12; i++) monthOpts.push({ v: i + 1, l: window.PerduraPeriod.helpers.MONTH_NAMES[i] });
  const yearOpts = [];
  const nowY = new Date().getFullYear();
  // Cover ~12 years back so customers with multi-year history (e.g. Xero
  // syncs going back to 2021) can pick their earliest months.
  for (let y = nowY - 12; y <= nowY + 1; y++) yearOpts.push(y);

  const upd = (k, v) => {
    const next = { kind: "custom",
      startYear: startYM.year, startMonth: startYM.month1,
      endYear: endYM.year, endMonth: endYM.month1,
      [k]: v };
    onChange({ ...state, period: next });
  };

  return (
    <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 8, marginTop: 8 }}>
      <div>
        <div style={{ fontSize: 10, color: "var(--text-3)", textTransform: "uppercase", letterSpacing: 0.4, marginBottom: 4 }}>Start</div>
        <div style={{ display: "flex", gap: 4 }}>
          <select className="pc-period-select" style={{ flex: 1, fontSize: 12 }} value={startYM.month1} onChange={e => upd("startMonth", parseInt(e.target.value, 10))}>
            {monthOpts.map(o => <option key={o.v} value={o.v}>{o.l}</option>)}
          </select>
          <select className="pc-period-select" style={{ width: 80, fontSize: 12 }} value={startYM.year} onChange={e => upd("startYear", parseInt(e.target.value, 10))}>
            {yearOpts.map(y => <option key={y} value={y}>{y}</option>)}
          </select>
        </div>
      </div>
      <div>
        <div style={{ fontSize: 10, color: "var(--text-3)", textTransform: "uppercase", letterSpacing: 0.4, marginBottom: 4 }}>End</div>
        <div style={{ display: "flex", gap: 4 }}>
          <select className="pc-period-select" style={{ flex: 1, fontSize: 12 }} value={endYM.month1} onChange={e => upd("endMonth", parseInt(e.target.value, 10))}>
            {monthOpts.map(o => <option key={o.v} value={o.v}>{o.l}</option>)}
          </select>
          <select className="pc-period-select" style={{ width: 80, fontSize: 12 }} value={endYM.year} onChange={e => upd("endYear", parseInt(e.target.value, 10))}>
            {yearOpts.map(y => <option key={y} value={y}>{y}</option>)}
          </select>
        </div>
      </div>
    </div>
  );
}

// ── UI: GlobalPeriodSelector ────────────────────────────────────────────
function GlobalPeriodSelector({ state, setState, resolved, savedViews, onSaveView, onDeleteView, hasBudget }) {
  const [open, setOpen] = useGP_useState(false);
  const [showSaveDialog, setShowSaveDialog] = useGP_useState(false);
  const [newName, setNewName] = useGP_useState("");
  const ref = useGP_useRef(null);

  useGP_useEffect(() => {
    if (!open) return;
    const handler = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener("mousedown", handler);
    return () => document.removeEventListener("mousedown", handler);
  }, [open]);

  const periodKind = state?.period?.kind || "preset";
  const periodPreset = state?.period?.preset || "ttm";
  const compareKind = state?.compare?.kind || "none";

  const presetClick = (k) => {
    if (k === "custom") {
      // Switch to a real custom-range state — kind must be "custom" or the
      // CustomRangeFields below never render. Seed with the current month so
      // the selects show something sensible until the user changes them, but
      // preserve any prior custom range the user already entered.
      const existing = state?.period?.kind === "custom" ? state.period : null;
      const now = new Date();
      const y = now.getFullYear(), m = now.getMonth() + 1;
      setState({ ...state, period: existing || {
        kind: "custom",
        startYear: y, startMonth: m,
        endYear:   y, endMonth:   m,
      }});
      // Keep the dropdown open so the user can pick start/end immediately.
    } else {
      setState({ ...state, period: { kind: "preset", preset: k } });
      setOpen(false);
    }
  };
  const compareClick = (k) => {
    if (k === "custom") setState({ ...state, compare: { kind: "custom", custom: state.compare?.custom || null } });
    else               setState({ ...state, compare: { kind: k } });
  };
  const applySavedView = (sv) => {
    if (!sv?.definition) return;
    setState(window.PerduraPeriod.deserialize(sv.definition));
    setOpen(false);
  };

  const handleSave = async () => {
    if (!newName.trim() || !onSaveView) return;
    const r = await onSaveView(newName.trim());
    if (r) { setNewName(""); setShowSaveDialog(false); }
  };

  const compareModes = window.PerduraPeriod.COMPARE_MODES.filter(m => m.key !== "budget" || hasBudget);

  // Display label
  const displayLabel = resolved.label + (resolved.compare ? ` · vs ${resolved.compare.label}` : "");

  return (
    <div ref={ref} style={{ position: "relative" }}>
      <button
        className="pc-period-trigger"
        onClick={() => setOpen(o => !o)}
        style={{
          height: 32, padding: "0 12px",
          background: "var(--bg-elev-1)", border: "1px solid var(--border)",
          borderRadius: 6, color: "var(--text)", fontSize: 12, fontWeight: 500,
          display: "inline-flex", alignItems: "center", gap: 8, cursor: "pointer",
        }}
        title="Choose period"
      >
        <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
          <rect x="3" y="4" width="18" height="18" rx="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/>
        </svg>
        <span style={{ maxWidth: 320, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{displayLabel}</span>
        <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round"><polyline points="6 9 12 15 18 9"/></svg>
      </button>

      {open && (
        <div style={{
          position: "absolute", top: "calc(100% + 6px)", right: 0, zIndex: 220,
          width: 360, background: "var(--bg-card-solid)", border: "1px solid var(--border-strong)",
          borderRadius: 10, boxShadow: "0 12px 32px rgba(0,0,0,0.18)", overflow: "hidden",
        }}>
          {/* Presets */}
          <div style={{ padding: "10px 12px 6px", fontSize: 10, color: "var(--text-3)", textTransform: "uppercase", letterSpacing: 0.5 }}>
            Period
          </div>
          <div style={{ padding: "0 8px 8px", display: "grid", gridTemplateColumns: "1fr 1fr", gap: 4 }}>
            {window.PerduraPeriod.PRESETS.map(p => {
              const active = periodKind === "preset" ? periodPreset === p.key : (p.key === "custom" && periodKind === "custom");
              return (
                <button key={p.key}
                  onClick={() => presetClick(p.key)}
                  style={{
                    padding: "6px 8px", fontSize: 12,
                    background: active ? "rgba(5,150,105,0.10)" : "transparent",
                    border: "1px solid " + (active ? "var(--accent)" : "var(--border)"),
                    borderRadius: 5, color: active ? "var(--accent)" : "var(--text-2)",
                    textAlign: "left", cursor: "pointer",
                  }}>{p.label}</button>
              );
            })}
          </div>

          {/* Custom range fields if custom */}
          {periodKind === "custom" && (
            <div style={{ padding: "0 12px 8px" }}>
              <CustomRangeFields state={state} onChange={setState} />
            </div>
          )}

          {/* Compare to */}
          <div style={{ padding: "8px 12px 6px", borderTop: "1px solid var(--border)", fontSize: 10, color: "var(--text-3)", textTransform: "uppercase", letterSpacing: 0.5 }}>
            Compare to
          </div>
          <div style={{ padding: "0 8px 8px" }}>
            {compareModes.map(c => (
              <button key={c.key}
                onClick={() => compareClick(c.key)}
                style={{
                  display: "block", width: "100%", padding: "6px 8px", fontSize: 12,
                  background: compareKind === c.key ? "rgba(5,150,105,0.10)" : "transparent",
                  border: "1px solid " + (compareKind === c.key ? "var(--accent)" : "var(--border)"),
                  borderRadius: 5, color: compareKind === c.key ? "var(--accent)" : "var(--text-2)",
                  textAlign: "left", marginBottom: 4, cursor: "pointer",
                }}>{c.label}</button>
            ))}
          </div>

          {/* Saved views */}
          {savedViews && savedViews.length > 0 && (
            <>
              <div style={{ padding: "8px 12px 6px", borderTop: "1px solid var(--border)", fontSize: 10, color: "var(--text-3)", textTransform: "uppercase", letterSpacing: 0.5 }}>
                Saved views
              </div>
              <div style={{ padding: "0 8px 8px" }}>
                {savedViews.map(sv => (
                  <div key={sv.id} style={{ display: "flex", gap: 4, alignItems: "center" }}>
                    <button onClick={() => applySavedView(sv)}
                      style={{ flex: 1, padding: "6px 8px", fontSize: 12, background: "transparent",
                               border: "1px solid var(--border)", borderRadius: 5, color: "var(--text-2)",
                               textAlign: "left", marginBottom: 4, cursor: "pointer" }}>
                      {sv.name}
                    </button>
                    {onDeleteView && (
                      <button onClick={() => onDeleteView(sv.id)}
                        title="Delete saved view"
                        style={{ padding: "4px 8px", fontSize: 11, background: "transparent",
                                 border: "1px solid var(--border)", borderRadius: 5,
                                 color: "var(--text-3)", marginBottom: 4, cursor: "pointer" }}>×</button>
                    )}
                  </div>
                ))}
              </div>
            </>
          )}

          {/* Save current view */}
          <div style={{ padding: "8px 12px", borderTop: "1px solid var(--border)" }}>
            {showSaveDialog ? (
              <div style={{ display: "flex", gap: 6 }}>
                <input
                  className="pc-period-select"
                  style={{ flex: 1, fontSize: 12 }}
                  placeholder="Name this view…"
                  value={newName}
                  onChange={e => setNewName(e.target.value)}
                  onKeyDown={e => e.key === "Enter" && handleSave()}
                  autoFocus
                />
                <button className="pc-btn-mini" onClick={handleSave}>Save</button>
                <button className="pc-btn-mini ghost" onClick={() => { setShowSaveDialog(false); setNewName(""); }}>×</button>
              </div>
            ) : (
              <button className="pc-btn-mini ghost" style={{ width: "100%", justifyContent: "center" }}
                      onClick={() => setShowSaveDialog(true)}>
                + Save this view
              </button>
            )}
          </div>
        </div>
      )}
    </div>
  );
}

// ── BusinessProfilePage ────────────────────────────────────────────────
function BusinessProfilePage({ companyProfile, scopedCompanyId, onProfileSaved }) {
  const cid = scopedCompanyId || companyProfile?.id || null;
  const [form, setForm] = useGP_useState(() => initFormFromProfile(companyProfile));
  const [saving, setSaving] = useGP_useState(false);
  const [savedFlash, setSavedFlash] = useGP_useState(false);
  const [resolvedCompanyId, setResolvedCompanyId] = useGP_useState(cid);

  // Resolve companyId from session if not provided
  useGP_useEffect(() => {
    if (cid) { setResolvedCompanyId(cid); return; }
    const db = window.supabaseClient;
    if (!db) return;
    (async () => {
      const { data: { session } } = await db.auth.getSession();
      if (!session) return;
      const { data: m } = await db.from("company_users").select("company_id").eq("user_id", session.user.id).in("status", ["Active", "Pending"]).maybeSingle();
      if (m?.company_id) {
        setResolvedCompanyId(m.company_id);
        const { data: co } = await db.from("companies").select("*").eq("id", m.company_id).maybeSingle();
        if (co) setForm(initFormFromProfile(co));
      }
    })();
  }, [cid]);

  useGP_useEffect(() => {
    if (companyProfile) setForm(initFormFromProfile(companyProfile));
  }, [companyProfile?.id]);

  const upd = (k, v) => setForm(f => ({ ...f, [k]: v }));

  const onSave = async () => {
    if (!resolvedCompanyId) return;
    const db = window.supabaseClient;
    if (!db) return;
    setSaving(true);
    // Industries that lock the nonprofit overlay regardless of the
    // is_nonprofit checkbox — picking "Non-profit" or "Faith / Religious
    // organization" forces it on.
    const lockedNonprofit = ["nonprofit", "faith"].includes((form.industry || "").toLowerCase());
    const update = {
      display_name: form.display_name || form.name || null,
      industry: form.industry || null,
      industry_subtype: form.industry_subtype || null,
      business_type: form.business_type || form.industry || null,
      is_nonprofit: lockedNonprofit || !!form.is_nonprofit,
      country: form.country || null,
      currency: form.currency || "USD",
      date_format: form.date_format || null,
      number_format: form.number_format || null,
      negative_style: form.negative_style || "minus",
      reporting_basis: form.reporting_basis || "accrual",
      default_period: form.default_period || "this_month",
      comparison_basis: form.comparison_basis || "prior_period",
      holds_inventory: !!form.holds_inventory,
      is_subscription: !!form.is_subscription,
      is_manufacturing: !!form.is_manufacturing,
      is_services: !!form.is_services,
      track_restricted_funds: !!form.track_restricted_funds,
      functional_expense_reporting: !!form.functional_expense_reporting,
      materiality_threshold: form.materiality_threshold === "" || form.materiality_threshold == null ? null : Number(form.materiality_threshold),
      // Business dimensions — the per-X denominators that drive per-X metrics.
      business_dimensions: Array.isArray(form.business_dimensions)
        ? form.business_dimensions
            .map(d => ({
              key:     String(d.key || "").trim(),
              label:   String(d.label || "").trim(),
              value:   Number(d.value) || 0,
              unit:    d.unit || null,
              primary: !!d.primary,
            }))
            .filter(d => d.key && d.label)
        : [],
      // Back-compat: keep member_count in sync with a "members" dimension
      // so old code paths still work. Persisted but not user-facing.
      member_count: (() => {
        const m = (form.business_dimensions || []).find(d => d.key === "members");
        return m && Number(m.value) > 0 ? Number(m.value) : null;
      })(),
      fiscal_year_start_month: parseInt(form.fiscal_year_start_month, 10) || 1,
      base_currency: form.currency || "USD",
      key_drivers: form.key_drivers || null,
      notes: form.notes || null,
    };
    const { error } = await db.from("companies").update(update).eq("id", resolvedCompanyId);
    setSaving(false);
    if (!error) {
      setSavedFlash(true);
      setTimeout(() => setSavedFlash(false), 2500);
      // Update PerduraFormat immediately so the currency change applies app-wide
      // without a reload.
      if (window.PerduraFormat) window.PerduraFormat.setProfile({ ...(companyProfile || {}), ...update });
      if (onProfileSaved) onProfileSaved({ ...(companyProfile || {}), ...update });
    }
  };

  // Industry list — single standardized set used for taxonomy/dashboards.
  const INDUSTRIES = [
    { v: "nonprofit",            l: "Non-profit" },
    { v: "faith",                l: "Faith / Religious organization" },
    { v: "professional_services",l: "Professional services" },
    { v: "retail",               l: "Retail / E-commerce" },
    { v: "wholesale",            l: "Wholesale / Distribution" },
    { v: "manufacturing",        l: "Manufacturing" },
    { v: "construction",         l: "Construction" },
    { v: "real_estate",          l: "Real estate" },
    { v: "hospitality",          l: "Hospitality" },
    { v: "healthcare",           l: "Healthcare" },
    { v: "education",            l: "Education" },
    { v: "saas",                 l: "Technology / SaaS" },
    { v: "financial_services",   l: "Financial services" },
    { v: "agriculture",          l: "Agriculture" },
    { v: "logistics",            l: "Logistics" },
  ];
  const NONPROFIT_SUBTYPES = [
    { v: "religious_congregation", l: "Religious congregation" },
    { v: "charity",                l: "Charity" },
    { v: "foundation",             l: "Foundation" },
    { v: "educational",            l: "Educational" },
  ];
  const BIZ_TYPES = [
    { v: "product",       l: "Product / e-commerce" },
    { v: "service",       l: "Service / consulting" },
    { v: "retail",        l: "Retail / brick-and-mortar" },
    { v: "manufacturing", l: "Manufacturing" },
    { v: "subscription",  l: "Subscription / SaaS" },
    { v: "nonprofit",     l: "Non-profit" },
  ];
  // Currencies and countries are sourced from the format helper, so any
  // future additions there appear here automatically.
  const FMT = window.PerduraFormat || { CURRENCIES: [], COUNTRIES: [], DATE_FORMATS: [], NUMBER_FORMATS: [] };
  const CURRENCIES = FMT.CURRENCIES;
  const COUNTRIES  = FMT.COUNTRIES;
  const DATE_FMTS  = FMT.DATE_FORMATS;
  const NUM_FMTS   = FMT.NUMBER_FORMATS;
  const MONTHS = window.PerduraPeriod.helpers.MONTH_NAMES;

  const showNonprofitFields = ["nonprofit", "faith"].includes((form.industry || "").toLowerCase()) || !!form.is_nonprofit;
  // When the user picks a country, fill in currency/date/number defaults
  // (only if those fields haven't been explicitly chosen yet).
  const onCountryChange = (code) => {
    const c = (COUNTRIES || []).find(x => x.code === code);
    setForm(f => ({
      ...f,
      country: code || null,
      currency:      f.currency      || c?.currency || "USD",
      date_format:   f.date_format   || c?.dateFormat || "MM/dd/yyyy",
      number_format: f.number_format || c?.numberFormat || "en-US",
    }));
  };

  return (
    <div className="pc-page">
      <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", gap: 12 }}>
        <div>
          <div style={{ fontSize: 11, color: "var(--text-3)", textTransform: "uppercase", letterSpacing: 0.5 }}>Settings</div>
          <h2 style={{ margin: "2px 0 0", fontSize: 22, fontWeight: 600, letterSpacing: -0.3 }}>Business Profile</h2>
          <div style={{ fontSize: 13, color: "var(--text-2)", marginTop: 6, maxWidth: 720, lineHeight: 1.55 }}>
            Tell us about your business in plain language. We use this to tailor the dashboards — which views to show, how to roll up your numbers, and what counts as a fiscal year.
          </div>
        </div>
        <div style={{ display: "flex", gap: 8, alignItems: "center" }}>
          {savedFlash && <span style={{ fontSize: 12, color: "var(--positive)" }}>✓ Saved</span>}
          <button className="pc-btn primary" disabled={saving || !resolvedCompanyId} onClick={onSave}>
            {saving ? "Saving…" : "Save changes"}
          </button>
        </div>
      </div>

      <Card title="Identity & locale" subtitle="Names what shows in headers/exports and seeds your currency, dates, and numbers.">
        <div className="pc-form-grid">
          <Field label="Organisation display name" hint="Used in headers, reports, and exports.">
            <input type="text" value={form.display_name || ""} onChange={e => upd("display_name", e.target.value)} placeholder="e.g. Beth Israel Synagogue" />
          </Field>
          <Field label="Country / region" hint="Auto-sets currency, date format, number format, and tax terminology — editable below.">
            <select value={form.country || ""} onChange={e => onCountryChange(e.target.value)}>
              <option value="">— Select —</option>
              {COUNTRIES.map(c => <option key={c.code} value={c.code}>{c.label}</option>)}
            </select>
          </Field>
        </div>
      </Card>

      <Card title="Industry" subtitle="Drives which dashboards appear and which account-mapping taxonomy we use (general vs nonprofit overlay).">
        <div className="pc-form-grid">
          <Field label="Industry">
            <select value={form.industry || ""} onChange={e => upd("industry", e.target.value)}>
              <option value="">— Select —</option>
              {INDUSTRIES.map(i => <option key={i.v} value={i.v}>{i.l}</option>)}
            </select>
          </Field>
          {showNonprofitFields && (
            <Field label="Sub-type">
              <select value={form.industry_subtype || ""} onChange={e => upd("industry_subtype", e.target.value)}>
                <option value="">— Select —</option>
                {NONPROFIT_SUBTYPES.map(s => <option key={s.v} value={s.v}>{s.l}</option>)}
              </select>
            </Field>
          )}
          <Field label="Business model (legacy)">
            <select value={form.business_type || ""} onChange={e => upd("business_type", e.target.value)}>
              <option value="">— Select —</option>
              {BIZ_TYPES.map(b => <option key={b.v} value={b.v}>{b.l}</option>)}
            </select>
          </Field>
        </div>
      </Card>

      <Card title="How do you make money?" subtitle="Tick everything that applies — these toggle whole sections of the dashboard on or off.">
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 10 }}>
          <ProfileCheckbox label="We hold physical inventory" hint="Stock-on-hand, COGS, reorder points" checked={!!form.holds_inventory} onChange={v => upd("holds_inventory", v)} />
          <ProfileCheckbox label="We bill recurring revenue (subscription / SaaS)" hint="MRR, ARR, churn, retention" checked={!!form.is_subscription} onChange={v => upd("is_subscription", v)} />
          <ProfileCheckbox label="We manufacture goods ourselves" hint="BOMs, work orders, OEE" checked={!!form.is_manufacturing} onChange={v => upd("is_manufacturing", v)} />
          <ProfileCheckbox label="We bill services / time" hint="Utilization, project margin, bench cost" checked={!!form.is_services} onChange={v => upd("is_services", v)} />
        </div>
      </Card>

      <Card title="Accounting & periods" subtitle="How totals are computed and which period every dashboard opens to.">
        <div className="pc-form-grid">
          <Field label="Reporting basis" hint="Cash recognises money when received/paid; Accrual when earned/incurred.">
            <select value={form.reporting_basis || "accrual"} onChange={e => upd("reporting_basis", e.target.value)}>
              <option value="accrual">Accrual</option>
              <option value="cash">Cash</option>
            </select>
          </Field>
          <Field label="Default reporting period">
            <select value={form.default_period || "this_month"} onChange={e => upd("default_period", e.target.value)}>
              <option value="this_month">This month</option>
              <option value="this_quarter">This quarter</option>
              <option value="ytd">Year-to-date</option>
              <option value="ttm">Trailing 12 months</option>
              <option value="t13m">Trailing 13 months</option>
              <option value="last_year">Last full year</option>
            </select>
          </Field>
          <Field label="Comparison basis" hint="What the ▲▼ columns compare against on every dashboard.">
            <select value={form.comparison_basis || "prior_period"} onChange={e => upd("comparison_basis", e.target.value)}>
              <option value="prior_period">Prior period</option>
              <option value="prior_year">Prior year</option>
              <option value="budget">Budget</option>
            </select>
          </Field>
          <Field label="Fiscal year starts in">
            <select value={form.fiscal_year_start_month || 1} onChange={e => upd("fiscal_year_start_month", parseInt(e.target.value, 10))}>
              {MONTHS.map((m, i) => <option key={m} value={i + 1}>{m}</option>)}
            </select>
          </Field>
        </div>
      </Card>

      <Card title="Display" subtitle="Used wherever money, numbers, or dates appear in the app.">
        <div className="pc-form-grid">
          <Field label="Currency" hint="Applied app-wide. ZAR shows as R, GBP as £, etc.">
            <select value={form.currency || "USD"} onChange={e => upd("currency", e.target.value)}>
              {CURRENCIES.map(c => <option key={c.code} value={c.code}>{c.label}</option>)}
            </select>
          </Field>
          <Field label="Date format">
            <select value={form.date_format || "MM/dd/yyyy"} onChange={e => upd("date_format", e.target.value)}>
              {DATE_FMTS.map(d => <option key={d.code} value={d.code}>{d.sample}</option>)}
            </select>
          </Field>
          <Field label="Number format">
            <select value={form.number_format || "en-US"} onChange={e => upd("number_format", e.target.value)}>
              {NUM_FMTS.map(n => <option key={n.code} value={n.code}>{n.sample}</option>)}
            </select>
          </Field>
          <Field label="Negative numbers">
            <select value={form.negative_style || "minus"} onChange={e => upd("negative_style", e.target.value)}>
              <option value="minus">−123 (minus sign)</option>
              <option value="parens">(123) (parentheses)</option>
            </select>
          </Field>
        </div>
      </Card>

      {showNonprofitFields && (
        <Card title="Nonprofit-specific" subtitle="Only shown when industry is Non-profit or Faith / Religious organisation.">
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 10 }}>
            <ProfileCheckbox label="Track restricted vs unrestricted funds" hint="Splits Net Assets With/Without Donor Restrictions" checked={!!form.track_restricted_funds} onChange={v => upd("track_restricted_funds", v)} />
            <ProfileCheckbox label="Functional expense reporting" hint="Program / Management & General / Fundraising" checked={!!form.functional_expense_reporting} onChange={v => upd("functional_expense_reporting", v)} />
          </div>
        </Card>
      )}

      {/* ── Business Dimensions ─────────────────────────────────────────────
          The "per-X" denominators this business cares about. The metric
          engine generates per-dimension metrics dynamically — so a synagogue
          with Members + Family Units gets BOTH "Giving per Member" AND
          "Giving per Family", a SaaS with Accounts + Seats gets per-Account
          AND per-Seat metrics, a manufacturer with Units Produced gets
          cost-per-unit, etc. Industry defaults are suggested; the user can
          edit/add/remove freely. */}
      <DimensionsEditor form={form} upd={upd} />


      <Card title="Insight tuning" subtitle="Filter out noise from insights and variance tables.">
        <div className="pc-form-grid">
          <Field label="Materiality threshold" hint="Variances below this dollar amount are hidden from insights.">
            <input type="number" min="0" value={form.materiality_threshold == null ? "" : form.materiality_threshold} onChange={e => upd("materiality_threshold", e.target.value)} placeholder="e.g. 1000" />
          </Field>
        </div>
      </Card>

      <Card title="What numbers do you watch most?" subtitle="Free-form notes. Helps your accountant and the dashboard prioritise what surfaces first.">
        <Field label="Key drivers (one per line)">
          <textarea
            rows={4}
            placeholder="e.g.&#10;Cash on hand &gt; $200k&#10;Gross margin &gt; 55%&#10;Top 5 customer concentration &lt; 40%"
            value={form.key_drivers || ""}
            onChange={e => upd("key_drivers", e.target.value)}
            style={{ width: "100%", padding: 10, background: "var(--bg-elev-1)",
                     border: "1px solid var(--border-strong)", borderRadius: 6, color: "var(--text)",
                     fontFamily: "inherit", fontSize: 13, resize: "vertical" }}
          />
        </Field>
        <Field label="Notes (internal context)">
          <textarea
            rows={3}
            placeholder="Anything we should know — seasonality, recent changes, upcoming events…"
            value={form.notes || ""}
            onChange={e => upd("notes", e.target.value)}
            style={{ width: "100%", padding: 10, background: "var(--bg-elev-1)",
                     border: "1px solid var(--border-strong)", borderRadius: 6, color: "var(--text)",
                     fontFamily: "inherit", fontSize: 13, resize: "vertical" }}
          />
        </Field>
      </Card>
    </div>
  );
}

function ProfileCheckbox({ label, hint, checked, onChange }) {
  return (
    <label style={{
      display: "flex", alignItems: "flex-start", gap: 10, padding: "10px 12px",
      background: checked ? "rgba(5,150,105,0.06)" : "var(--bg-elev-1)",
      border: "1px solid " + (checked ? "rgba(5,150,105,0.4)" : "var(--border)"),
      borderRadius: 6, cursor: "pointer",
    }}>
      <input type="checkbox" checked={checked} onChange={e => onChange(e.target.checked)} style={{ marginTop: 3, cursor: "pointer" }} />
      <div>
        <div style={{ fontSize: 13, fontWeight: 500 }}>{label}</div>
        {hint && <div style={{ fontSize: 11.5, color: "var(--text-3)", marginTop: 2 }}>{hint}</div>}
      </div>
    </label>
  );
}

function initFormFromProfile(p) {
  const blank = {
    display_name: "", country: "", currency: "USD",
    date_format: "", number_format: "", negative_style: "minus",
    industry: "", industry_subtype: "", business_type: "", is_nonprofit: false,
    holds_inventory: false, is_subscription: false, is_manufacturing: false, is_services: false,
    reporting_basis: "accrual", default_period: "this_month", comparison_basis: "prior_period",
    track_restricted_funds: false, functional_expense_reporting: false,
    materiality_threshold: "",
    business_dimensions: [],
    fiscal_year_start_month: 1, key_drivers: "", notes: "",
  };
  if (!p) return blank;
  // Resolve dimensions via PerduraDimensions so the editor opens on the
  // industry-suggested defaults (with value=0) when nothing is saved yet,
  // and includes the legacy member_count as a "members" dimension.
  const dims = (typeof window !== "undefined" && window.PerduraDimensions)
    ? window.PerduraDimensions.effectiveDimensions(p)
    : (Array.isArray(p.business_dimensions) ? p.business_dimensions : []);
  return {
    ...blank,
    display_name: p.display_name || p.name || "",
    country: p.country || "",
    currency: p.currency || p.base_currency || "USD",
    date_format: p.date_format || "",
    number_format: p.number_format || "",
    negative_style: p.negative_style || "minus",
    industry: p.industry || "",
    industry_subtype: p.industry_subtype || "",
    business_type: p.business_type || "",
    is_nonprofit: !!p.is_nonprofit,
    holds_inventory: !!p.holds_inventory,
    is_subscription: !!p.is_subscription,
    is_manufacturing: !!p.is_manufacturing,
    is_services:    !!p.is_services,
    reporting_basis: p.reporting_basis || "accrual",
    default_period:  p.default_period  || "this_month",
    comparison_basis:p.comparison_basis || "prior_period",
    track_restricted_funds: !!p.track_restricted_funds,
    functional_expense_reporting: !!p.functional_expense_reporting,
    materiality_threshold: p.materiality_threshold == null ? "" : p.materiality_threshold,
    business_dimensions: dims,
    fiscal_year_start_month: p.fiscal_year_start_month || legacyMonthToNum(p.fiscal_year_start) || 1,
    key_drivers: p.key_drivers || "",
    notes: p.notes || "",
  };
}

// ── DimensionsEditor ──────────────────────────────────────────────────────
// Inline editor for the business_dimensions array. Suggests industry
// defaults when empty. The user can edit labels, values, mark a primary,
// add custom dimensions, or remove any line.
function DimensionsEditor({ form, upd }) {
  const dims = Array.isArray(form.business_dimensions) ? form.business_dimensions : [];
  const Dims = (typeof window !== "undefined") ? window.PerduraDimensions : null;
  const suggested = Dims ? Dims.defaultsForIndustry(form.industry || form.business_type) : [];
  const usingDefaults = dims.length === 0 || dims.every(d => Number(d.value) === 0);

  const setDim = (idx, patch) => {
    const next = dims.map((d, i) => i === idx ? { ...d, ...patch } : d);
    upd("business_dimensions", next);
  };
  const removeDim = (idx) => upd("business_dimensions", dims.filter((_, i) => i !== idx));
  const addDim = () => upd("business_dimensions", [...dims, { key: "", label: "", value: 0, unit: "", primary: false }]);
  const seedFromIndustry = () => upd("business_dimensions", suggested.map(d => ({ ...d })));

  const list = dims.length ? dims : suggested;

  return (
    <Card title="Business dimensions"
          subtitle={"The per-X denominators we should track for this business. Drives metrics like “Giving per Member”, “Revenue per Seat”, “Cost per Unit”."}>
      {usingDefaults && (
        <div style={{ padding: "10px 14px", background: "var(--bg-elev-1)", border: "1px solid var(--border)", borderRadius: 8, fontSize: 12.5, color: "var(--text-2)", marginBottom: 12 }}>
          We've suggested defaults for your industry. Edit the counts to unlock per-dimension metrics, or add your own dimensions below.
        </div>
      )}
      <table className="pc-table" style={{ width: "100%" }}>
        <thead>
          <tr>
            <th style={{ width: "30%" }}>Label</th>
            <th style={{ width: "20%" }}>Count</th>
            <th style={{ width: "20%" }}>Unit (optional)</th>
            <th style={{ width: "15%" }}>Primary</th>
            <th style={{ width: "15%" }}></th>
          </tr>
        </thead>
        <tbody>
          {list.map((d, idx) => (
            <tr key={(d.key || "row") + "-" + idx}>
              <td>
                <input
                  type="text"
                  value={d.label || ""}
                  onChange={e => setDim(idx, { label: e.target.value, key: d.key || e.target.value.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "") })}
                  placeholder={d.hint || "e.g. Members"}
                  style={{ width: "100%" }}
                />
              </td>
              <td>
                <input
                  type="number"
                  min="0"
                  value={d.value == null ? "" : d.value}
                  onChange={e => setDim(idx, { value: e.target.value === "" ? 0 : Number(e.target.value) })}
                  placeholder="0"
                  style={{ width: "100%", fontFamily: "ui-monospace, monospace" }}
                />
              </td>
              <td>
                <input
                  type="text"
                  value={d.unit || ""}
                  onChange={e => setDim(idx, { unit: e.target.value })}
                  placeholder="member"
                  style={{ width: "100%" }}
                />
              </td>
              <td style={{ textAlign: "center" }}>
                <input
                  type="radio"
                  name="primary-dim"
                  checked={!!d.primary}
                  onChange={() => {
                    const next = list.map((x, i) => ({ ...x, primary: i === idx }));
                    upd("business_dimensions", next);
                  }}
                />
              </td>
              <td style={{ textAlign: "right" }}>
                <button className="pc-btn-mini ghost" type="button" onClick={() => removeDim(idx)}>Remove</button>
              </td>
            </tr>
          ))}
        </tbody>
      </table>
      <div style={{ display: "flex", gap: 8, marginTop: 12 }}>
        <button className="pc-btn-mini" type="button" onClick={addDim}>+ Add dimension</button>
        {Dims && suggested.length > 0 && usingDefaults && (
          <button className="pc-btn-mini ghost" type="button" onClick={seedFromIndustry}>Use industry defaults</button>
        )}
        <div style={{ flex: 1 }} />
        <div style={{ fontSize: 11.5, color: "var(--text-3)", alignSelf: "center" }}>
          Marked <b>Primary</b> appears in KPI strips. All non-zero dimensions get per-X metric cards.
        </div>
      </div>
    </Card>
  );
}

Object.assign(window, { useGlobalPeriod, GlobalPeriodSelector, BusinessProfilePage });
