// ─────────────────────────────────────────────────────────────
// Section 5 - Risk Profile & Goals
// ─────────────────────────────────────────────────────────────

const RISK_QS = [
  { id: 'q1', q: 'How would you describe your investment knowledge?',
    opts: ['None - I rely entirely on advice','Basic - I know the essentials','Moderate - I read / manage my own','Advanced - I actively trade or invest'] },
  { id: 'q2', q: 'If your investment dropped 20% in a year, what would you do?',
    opts: ['Sell everything - I can\'t handle the loss','Sell some - reduce my exposure','Do nothing - ride it out','Buy more - the cost per unit is reduced'] },
  { id: 'q3', q: 'What is your primary investment goal?',
    opts: ['Protect capital - minimal loss','Steady income','Balance growth and income','Aggressive growth'] },
  { id: 'q4', q: 'How long until you need access to most of these funds?',
    opts: ['Within 2 years','2–5 years','5–10 years','10+ years'] },
  { id: 'q5', q: 'Which best describes your attitude to investment returns?',
    opts: ['I prefer certainty - happy with lower returns','I want some growth but low volatility','I\'ll accept volatility for better returns','I want maximum returns - I accept big swings'] },
  { id: 'q6', q: 'Which option best describes your attitude toward ethical investing?',
    // Hover definition for the "i" beside the question. "Ethical investing" is
    // the one term on this card most clients won't have a settled definition
    // for, and the answer drives product selection (the ethical fund line-up
    // in the super comparison), so it is worth defining rather than assuming.
    tip: 'Ethical investing (also called responsible, sustainable or ESG investing) screens your investments against environmental, social and governance standards - commonly avoiding areas such as tobacco, gambling, weapons and fossil fuels, and favouring companies with stronger practices. Because the screening narrows the pool of investments available, these options typically cost more than a comparable standard portfolio.',
    opts: [
      'I would like to consider Ethical investing knowing that this will likely come at an additional cost to my investment options.',
      'I don\'t have any specific ethical preferences.',
      'I have strong ethical preferences and would like to ensure my investments align with this.',
    ] },
];

// Two clear paths for capturing financial goals.
//   1. 'articulate' - client can describe their own goals, free-text rows
//   2. 'assist'     - client picks from a curated list, we add follow-ups
const GOAL_MODES = {
  ARTICULATE: 'articulate',
  ASSIST:     'assist',
};

// Path A: hard cap on free-text goals (3 mandatory + 7 optional).
const ARTICULATE_MIN = 3;
const ARTICULATE_MAX = 10;

// Path B: pick at least 3, at most 10 from the preset list.
const ASSIST_MIN = 3;
const ASSIST_MAX = 10;

// Curated catalogue of goals the client picks from in Path B. The same
// labels are used as keys into GOAL_FOLLOWUPS below so follow-up cards
// can render the right per-goal questions. Note: the old
// "I would like to write my own" sentinel chip is removed - that's now
// Path A's standalone mode.
//
// "Protect my family with insurance" was removed from this list per
// Ashley's review - insurance gating now happens through the dedicated
// Insurance section. Clients who previously selected it keep their
// follow-up answers in their fact-find (we don't scrub history), but
// new invites can no longer pick it.
const GOAL_CATALOGUE = [
  'Buy a first home',
  'Upgrade or buy a new home',
  'Purchase an investment property',
  'Build investment portfolio outside super',
  'Grow my superannuation',
  'Pay off debt faster',
  'Start or grow a business',
  "Save for children's education",
  'Plan a major lifestyle purchase (car, travel, reno)',
  'Save for a career break / sabbatical',
  'Plan for retirement',
  'Maximise tax efficiency',
  'Structure a will / estate plan',
  'Support parents or family financially',
];

// Per-goal follow-up question schema for Path B. Sensible defaults per
// goal type so the adviser walks into the strategy meeting with the
// right context. All fields here are required when the parent goal is
// selected. Field types: text, textarea, money, date, number.
const GOAL_FOLLOWUPS = {
  'Buy a first home': [
    { key: 'targetPrice',  label: 'Target purchase price',         type: 'money',    placeholder: 'e.g. 850,000' },
    { key: 'targetYear',   label: 'Ideal year to buy',             type: 'number',   placeholder: 'e.g. 2027' },
    { key: 'depositSaved', label: 'Deposit saved so far ($)',      type: 'money',    placeholder: 'e.g. 65,000' },
    { key: 'location',     label: 'Suburb / area you have in mind', type: 'text',    placeholder: 'e.g. Brisbane inner-north' },
  ],
  'Upgrade or buy a new home': [
    { key: 'targetPrice',     label: 'Target purchase price',          type: 'money',  placeholder: 'e.g. 1,400,000' },
    { key: 'targetYear',      label: 'Ideal year to move',             type: 'number', placeholder: 'e.g. 2028' },
    { key: 'location',        label: 'Suburb / area you have in mind', type: 'text',   placeholder: 'e.g. Hawthorn' },
    { key: 'sellCurrentHome', label: 'Do you plan on selling your current home?', type: 'yesno' },
    { key: 'notes',           label: 'Anything else - schools, must-haves, current home plan?', type: 'textarea', placeholder: '' },
  ],
  'Purchase an investment property': [
    { key: 'targetPrice', label: 'Budget ($)',                    type: 'money',    placeholder: 'e.g. 650,000' },
    { key: 'targetYear',  label: 'Ideal year to buy',             type: 'number',   placeholder: 'e.g. 2027' },
    { key: 'location',    label: 'Preferred location / type',     type: 'text',     placeholder: 'e.g. Outer-suburb townhouse' },
    { key: 'strategy',    label: 'Strategy / income or growth focus?', type: 'textarea', placeholder: 'e.g. Long-term capital growth, neutral cashflow.' },
  ],
  'Build investment portfolio outside super': [
    { key: 'monthlyContrib', label: 'Comfortable monthly contribution ($)', type: 'money', placeholder: 'e.g. 1,500' },
    { key: 'preferences',    label: 'Investment preferences or no-go areas', type: 'textarea', placeholder: 'e.g. Diversified ETFs, no resources stocks.' },
  ],
  'Grow my superannuation': [
    { key: 'retirementIncome',  label: 'How much would you like in retirement income ($ p.a. in today\'s dollars)', type: 'money', placeholder: 'e.g. 90,000' },
    { key: 'extraContribution', label: 'Open to extra concessional contributions?', type: 'textarea', placeholder: 'e.g. Yes, up to $5k/year if cashflow allows.' },
  ],
  // 'Protect my family with insurance' intentionally removed - the
  // dedicated Insurance section already gathers all of this in depth.
  // Removed from GOAL_CATALOGUE too. Kept the schema commented as a
  // restore reference in case it gets brought back.
  'Pay off debt faster': [
    // debtPicker renders chips built from the debts the client already
    // entered in the Assets section (loans, credit facilities, ATO,
    // HELP) plus a free-text fallback. The old "Current balance"
    // question was dropped - those balances are already captured
    // against each debt in Assets.
    { key: 'whichDebt',    label: 'Which debt are we targeting?',  type: 'debtPicker' },
    { key: 'targetPayoffYear', label: 'Target payoff year',        type: 'number', placeholder: 'e.g. 2030' },
  ],
  'Start or grow a business': [
    { key: 'stage',     label: 'Stage (idea, side-hustle, established)', type: 'text',   placeholder: 'e.g. Side-hustle for 18 months' },
    { key: 'capital',   label: 'Capital needed ($)',                 type: 'money',    placeholder: 'e.g. 75,000' },
    { key: 'timeframe', label: 'Target launch / growth date',         type: 'text',    placeholder: 'e.g. Full-time by mid-2027' },
    { key: 'notes',     label: 'Anything else we should know?',       type: 'textarea', placeholder: '' },
  ],
  "Save for children's education": [
    { key: 'children',      label: 'Which children (names + ages)',   type: 'text',     placeholder: 'e.g. Mia (7), Jack (5)' },
    { key: 'schools',       label: 'Which schools / pathway?',        type: 'text',     placeholder: 'e.g. Public primary, private high school (Brisbane Grammar)' },
    { key: 'yearStarting',  label: 'Year fees start',                 type: 'number',   placeholder: 'e.g. 2030' },
    { key: 'annualBudget',  label: 'Estimated annual cost per child ($)', type: 'money', placeholder: 'e.g. 35,000' },
  ],
  'Plan a major lifestyle purchase (car, travel, reno)': [
    { key: 'what',      label: 'What are we planning for?',          type: 'text',     placeholder: 'e.g. Kitchen reno / Europe trip / new EV' },
    { key: 'budget',    label: 'Budget ($)',                         type: 'money',    placeholder: 'e.g. 60,000' },
    { key: 'targetDate', label: 'Target date',                       type: 'text',     placeholder: 'e.g. December 2027' },
  ],
  'Save for a career break / sabbatical': [
    { key: 'targetSavings', label: 'Savings target ($)',             type: 'money',  placeholder: 'e.g. 60,000' },
    { key: 'startDate',     label: 'Ideal start date',               type: 'text',   placeholder: 'e.g. Jan 2028' },
    { key: 'duration',      label: 'How long (months)',              type: 'number', placeholder: 'e.g. 6' },
    { key: 'returnToWork',  label: 'Do you plan to return to work afterwards?', type: 'yesno' },
    // When returning to work, plan it either by days/week or by income.
    { key: 'returnBasis',   label: 'How would you like to plan your return?', type: 'select',
      options: ['Days returning to work per week', 'Estimated annual income'],
      revealIf: { key: 'returnToWork', equals: true } },
    { key: 'returnDays',    label: 'How many days per week will you return to work?', type: 'number',
      placeholder: 'e.g. 3', revealIf: { key: 'returnBasis', equals: 'Days returning to work per week' } },
    { key: 'returnIncome',  label: 'Estimated annual income on return ($)', type: 'money',
      placeholder: 'e.g. 95,000', revealIf: { key: 'returnBasis', equals: 'Estimated annual income' } },
    // Family / childcare branch.
    { key: 'familyStart',   label: 'Is this career break due to starting a family?', type: 'yesno' },
    { key: 'childcareNeeded', label: 'Should childcare be factored in when you return to work?', type: 'yesno',
      revealIf: { key: 'familyStart', equals: true } },
    { key: 'notes',         label: 'Plans for the break?',           type: 'textarea', placeholder: '' },
  ],
  'Plan for retirement': [
    { key: 'targetAge',     label: 'Target retirement age',          type: 'number',   placeholder: 'e.g. 62' },
    { key: 'targetIncome',  label: 'Target annual income in today\'s dollars ($)', type: 'money', placeholder: 'e.g. 90,000' },
    { key: 'lifestyle',     label: 'Lifestyle / location plans',     type: 'textarea', placeholder: 'e.g. Coastal downsize, two overseas trips a year.' },
  ],
  'Maximise tax efficiency': [
    { key: 'concerns',  label: 'Specific tax concerns or recent events', type: 'textarea', placeholder: 'e.g. Recent CGT event; debt-recycling interest; trust distributions.' },
    { key: 'priorities', label: 'Top priority - structure, contribution, deductions?', type: 'text', placeholder: 'e.g. Concessional super contributions and deductions.', optional: true },
  ],
  'Structure a will / estate plan': [
    { key: 'existing',  label: 'Existing arrangements (will, EPOA, super noms)', type: 'textarea', placeholder: 'e.g. Will from 2018, no EPOA, super beneficiary nominations expired.' },
    { key: 'concerns',  label: 'Key concerns or changes needed',     type: 'textarea', placeholder: 'e.g. Update beneficiaries since separation; testamentary trust for kids.' },
  ],
  'Support parents or family financially': [
    { key: 'who',            label: 'Who are you supporting?',            type: 'text',     placeholder: "e.g. Parents' aged-care fees; sibling's deposit." },
    { key: 'type',           label: 'Type of support (regular, one-off, gift, loan)', type: 'text', placeholder: 'e.g. Regular monthly contribution; one-off deposit gift.' },
    { key: 'amount',         label: 'Estimated total amount ($)',         type: 'money',    placeholder: 'e.g. 50,000' },
    { key: 'timeframe',      label: 'Timeframe',                          type: 'text',     placeholder: 'e.g. Ongoing for 5 years.' },
    { key: 'sendsOverseas',  label: 'Do you send money overseas as part of this support?', type: 'yesno' },
  ],
};

function SectionGoals({ data, set }) {
  const d = data.goals || {};
  // Functional setState so multi-call handlers can't race.
  const update = (patch) => set(prev => {
    const prevGoals = prev.goals || {};
    return { ...prev, goals: { ...prevGoals, ...patch } };
  });

  // Mode picker - 'articulate' (write your own) or 'assist' (pick from
  // catalogue). Both modes share the same drag-to-reorder priority list
  // at the bottom but build the selectedGoals array differently.
  const mode = d.mode;
  const selectedGoals = d.selected || [];
  // Path A "add more" up to MAX. We store extras under goals.customExtra
  // (array of strings) so the existing custom1/2/3 keys stay untouched
  // and the validator can keep its current 3-required rule.
  const customExtra = d.customExtra || [];

  const toggleAssistGoal = (g) => {
    const isOn = selectedGoals.includes(g);
    if (!isOn && selectedGoals.length >= ASSIST_MAX) return;
    update({ selected: isOn ? selectedGoals.filter(x => x !== g) : [...selectedGoals, g] });
  };

  const updateFollowup = (goal, key, val) => {
    const fu = { ...(d.followups || {}) };
    fu[goal] = { ...(fu[goal] || {}), [key]: val };
    update({ followups: fu });
  };

  // Pull the household's children (the dependants already entered in the
  // Personal section) into the children's-education goal so the client
  // doesn't have to retype them. Built as "Name (age)".
  const householdChildren = React.useMemo(() => {
    const deps = (data && data.personal && data.personal.primary && data.personal.primary.deps) || [];
    return deps
      .filter(dep => dep && ['Child', 'Step-child'].includes(dep.relationship) && (dep.name || dep.dob))
      .map(dep => {
        const age = dep.dob ? Math.floor((Date.now() - new Date(dep.dob).getTime()) / (365.25 * 24 * 3600 * 1000)) : null;
        const nm = (dep.name || '').trim() || 'Child';
        return (age != null && age >= 0) ? `${nm} (${age})` : nm;
      })
      .join(', ');
  }, [data]);

  const EDU_GOAL = "Save for children's education";
  const eduSelected = selectedGoals.includes(EDU_GOAL);
  React.useEffect(() => {
    if (!eduSelected || !householdChildren) return;
    const cur = ((d.followups || {})[EDU_GOAL] || {}).children;
    if (cur && String(cur).trim()) return; // never clobber the client's own edit
    updateFollowup(EDU_GOAL, 'children', householdChildren);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [eduSelected, householdChildren]);

  const addExtraCustom = () => {
    // Total = 3 fixed + extras. Cap at ARTICULATE_MAX.
    if (3 + customExtra.length >= ARTICULATE_MAX) return;
    update({ customExtra: [...customExtra, ''] });
  };
  const updateExtraCustom = (i, val) => {
    const next = [...customExtra]; next[i] = val;
    update({ customExtra: next });
  };
  const removeExtraCustom = (i) => {
    const next = [...customExtra]; next.splice(i, 1);
    update({ customExtra: next });
  };

  // When the user changes mode, scrub stale state so the validator sees
  // a clean slate for the new path. Articulate mode doesn't use
  // selected[] / followups{}; assist mode doesn't use custom1/2/3 /
  // customExtra[]. We deliberately don't blow away the OTHER mode's
  // data on toggle - the user might switch back, and the existing
  // values are still useful context.
  const switchMode = (next) => {
    if (next === mode) return;
    update({ mode: next });
  };

  // Drag-to-reorder state for the priority list. We only need a single index
  // (the one being dragged); the drop target rearranges the array.
  const [dragIdx, setDragIdx] = React.useState(null);
  const onDragStart = (i) => () => { setDragIdx(i); };
  const onDragOver = (i) => (e) => {
    e.preventDefault(); // required to allow drop
    if (dragIdx === null || dragIdx === i) return;
  };
  const onDrop = (i) => (e) => {
    e.preventDefault();
    if (dragIdx === null || dragIdx === i) { setDragIdx(null); return; }
    const next = [...selectedGoals];
    const [moved] = next.splice(dragIdx, 1);
    next.splice(i, 0, moved);
    update({ selected: next });
    setDragIdx(null);
  };
  const onDragEnd = () => setDragIdx(null);

  // Helper for the per-question required asterisk styling.
  const reqAst = <span className="req" aria-label="required" style={{ marginLeft: 6 }}>*</span>;

  // Per-client risk profile. When advice is for a couple AND the primary
  // is completing the partner's details here (rather than the partner
  // filling their own fact-find), we capture a SEPARATE risk profile for
  // each person. Partner answers live under goals.pq1..pq6.
  const primaryP = (data && data.personal && data.personal.primary) || {};
  const partnerP = (data && data.personal && data.personal.partner) || {};
  const isCouple = ['Married', 'De facto'].includes(primaryP.relStatus);
  const partnerRisk = isCouple && primaryP.coupleAdvice === true
    && ((data.personal && data.personal.partnerCompletion) === 'self');
  const primaryNm = [primaryP.firstName, primaryP.lastName].filter(Boolean).join(' ').trim();
  const partnerNm = [partnerP.firstName, partnerP.lastName].filter(Boolean).join(' ').trim();

  const renderRiskCard = (title, prefix) => (
    <div className="card">
      <div className="card-title">{title}</div>
      <div className="risk-intro">
        {RISK_QS.length} quick questions - there are no wrong answers. This helps us recommend investments that match how you actually feel about risk.
      </div>
      {RISK_QS.map((q, i) => {
        const key = prefix + q.id;
        return (
          <div key={key} className="risk-q" data-ff-name={`goals.${key}`}>
            <div className="risk-q-head">
              <div className="risk-q-num">{i + 1}</div>
              <div className="risk-q-text">{q.q}{reqAst}{q.tip ? <InfoIcon tip={q.tip} /> : null}</div>
            </div>
            <div className="risk-q-opts">
              {q.opts.map((o, oi) => (
                <button
                  type="button"
                  key={oi}
                  className={cx('risk-opt', d[key] === oi && 'on')}
                  onClick={() => update({ [key]: oi })}
                >
                  <span className="risk-letter">{String.fromCharCode(65 + oi)}</span>
                  <span className="risk-text">{o}</span>
                </button>
              ))}
            </div>
          </div>
        );
      })}
    </div>
  );

  return (
    <div className="section-body">
      {renderRiskCard(partnerRisk ? `Risk profile - ${primaryNm || 'you'}` : 'Risk profile', '')}
      {partnerRisk && renderRiskCard(`Risk profile - ${partnerNm || 'your partner'}`, 'p')}

      <div className="card">
        <div className="card-title">Financial goals{reqAst}</div>

        {/* Mode picker - two clear paths. Renders as two big "card"-style
            buttons so the choice is obvious. Until one is picked, the
            rest of the card stays hidden. */}
        <div className="goals-sub" style={{ marginBottom: 14 }} data-ff-name="goals.mode">
          How would you like to approach your financial goals?{reqAst}
        </div>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12, marginBottom: mode ? 18 : 0 }}
          className="goals-mode-picker">
          <button type="button"
            className={cx('chip goals-mode-chip', mode === GOAL_MODES.ARTICULATE && 'on')}
            style={{
              flexDirection: 'column', alignItems: 'flex-start', padding: '16px 18px',
              minHeight: 96, textAlign: 'left', gap: 4,
            }}
            onClick={() => switchMode(GOAL_MODES.ARTICULATE)}>
            <strong style={{ fontSize: 15 }}>I can clearly articulate my financial goals and would like to list them</strong>
            <span style={{ fontSize: 12, color: 'var(--mute)' }}>Free-text - describe each goal in your own words.</span>
          </button>
          <button type="button"
            className={cx('chip goals-mode-chip', mode === GOAL_MODES.ASSIST && 'on')}
            style={{
              flexDirection: 'column', alignItems: 'flex-start', padding: '16px 18px',
              minHeight: 96, textAlign: 'left', gap: 4,
            }}
            onClick={() => switchMode(GOAL_MODES.ASSIST)}>
            <strong style={{ fontSize: 15 }}>I would like some assistance forming my financial goals</strong>
            <span style={{ fontSize: 12, color: 'var(--mute)' }}>Pick from a curated list - we'll guide the detail.</span>
          </button>
        </div>

        {/* ─── Path A · articulate ───────────────────────── */}
        {mode === GOAL_MODES.ARTICULATE && (
          <div>
            <Callout kind="info" icon="💡">
              <strong>Tip:</strong> describe each goal with a clear <strong>$ value</strong>, a <strong>timeframe</strong>, and the
              <strong> outcome you're after</strong>. Concrete goals get concrete plans.
              <br />
              <em style={{ display: 'inline-block', marginTop: 4 }}>
                e.g. "Save $200k deposit for a Brisbane home by Dec 2028 so we can stop renting before the kids start school."
              </em>
            </Callout>
            <div className="grid-1" style={{ marginTop: 12, display: 'grid', gap: 14 }} data-ff-name="goals.articulate">
              {[1, 2, 3].map(n => (
                <Field key={n} label={`Goal ${n}`} required name={`goals.custom${n}`}
                  hint={n === 1 ? 'Include $, timeframe, and the outcome.' : null}>
                  <Textarea rows={2}
                    value={d[`custom${n}`] || ''}
                    onChange={e => update({ [`custom${n}`]: e.target.value })}
                    placeholder={n === 1
                      ? 'e.g. Save $200k deposit for a $1.1M Brisbane home by Dec 2028.'
                      : (n === 2
                        ? 'e.g. Reach $1.5M super balance by 65 so we can retire on $90k/yr.'
                        : 'e.g. Pay off our $400k home loan within 10 years to be debt-free by 50.')} />
                </Field>
              ))}
              {/* Extra optional rows - up to ARTICULATE_MAX total. */}
              {customExtra.map((val, i) => (
                <div key={i} style={{ position: 'relative' }}>
                  <Field label={`Goal ${i + 4}`} required name={`goals.extra${i}`}
                    hint="Same shape - $, timeframe, outcome.">
                    <Textarea rows={2}
                      value={val}
                      onChange={e => updateExtraCustom(i, e.target.value)}
                      placeholder="e.g. Build a $250k investment portfolio outside super in 8 years." />
                  </Field>
                  <button type="button" className="priority-remove"
                    style={{ position: 'absolute', top: 0, right: 0 }}
                    onClick={() => removeExtraCustom(i)}
                    title="Remove this goal">×</button>
                </div>
              ))}
              {(3 + customExtra.length) < ARTICULATE_MAX && (
                <AddBtn onClick={addExtraCustom}>Add another goal</AddBtn>
              )}
              <div style={{ fontSize: 12, color: 'var(--mute)' }}>
                {3 + customExtra.length} of {ARTICULATE_MAX} goals listed.
              </div>
            </div>
          </div>
        )}

        {/* ─── Path B · assist ───────────────────────────── */}
        {mode === GOAL_MODES.ASSIST && (
          <div>
            <div className="goals-head" style={{ marginTop: 4 }}>
              <div className="goals-sub">
                Please select up to <strong>{ASSIST_MAX}</strong> (minimum <strong>{ASSIST_MIN}</strong>) of the below
                common goals you would like to achieve.{reqAst}
              </div>
              <div className={cx('goals-count',
                selectedGoals.length >= ASSIST_MAX && 'full',
                selectedGoals.length < ASSIST_MIN && 'goals-count-low')}>
                {selectedGoals.length} / {ASSIST_MAX} selected
              </div>
            </div>
            <div className="goals-bar">
              <div className="goals-bar-fill"
                style={{ width: `${Math.min(100, (selectedGoals.length / ASSIST_MAX) * 100)}%` }} />
            </div>
            <div className="chip-group" style={{ marginTop: 16 }} data-ff-name="goals.selected">
              {GOAL_CATALOGUE.map(g => {
                const on = selectedGoals.includes(g);
                const blocked = !on && selectedGoals.length >= ASSIST_MAX;
                return (
                  <button
                    type="button"
                    key={g}
                    className={cx('chip', on && 'on', blocked && 'chip-disabled')}
                    onClick={() => toggleAssistGoal(g)}
                    disabled={blocked}
                  >{g}</button>
                );
              })}
            </div>
          </div>
        )}

        {/* Priority list (drag-to-reorder hierarchy) - only relevant in
            Path B because Path A's goals are already ordered by row. */}
        {mode === GOAL_MODES.ASSIST && selectedGoals.length > 0 && (
          <div className="goals-priority">
            <div className="goals-priority-title">
              Your selected goals
              <span style={{ display: 'block', fontSize: 12, fontWeight: 500, color: 'var(--mute)', marginTop: 4 }}>
                You can drag these in order of priority.
              </span>
            </div>
            {selectedGoals.map((g, i) => {
              const isDragging = dragIdx === i;
              return (
                <div key={g}
                  className={cx('priority-row', isDragging && 'is-dragging')}
                  draggable
                  onDragStart={onDragStart(i)}
                  onDragOver={onDragOver(i)}
                  onDrop={onDrop(i)}
                  onDragEnd={onDragEnd}
                  style={{ cursor: 'grab', opacity: isDragging ? 0.4 : 1 }}
                >
                  <div className="priority-num" style={{
                    background: ['var(--green)','var(--blue)','var(--accent)','var(--magenta)','var(--mute)'][Math.min(i, 4)]
                  }}>{i+1}</div>
                  <div className="priority-label">{g}</div>
                  <span className="priority-grab" aria-hidden="true"
                    style={{ marginRight: 8, color: 'var(--mute)', userSelect: 'none', fontSize: 18, lineHeight: 1 }}>⋮⋮</span>
                  <button type="button" className="priority-remove" onClick={() => toggleAssistGoal(g)}>×</button>
                </div>
              );
            })}
          </div>
        )}

        {/* Per-goal follow-up cards - Path B only. Each selected goal
            renders its sensible-default question set from GOAL_FOLLOWUPS.
            Rendered in priority order so the most important goals come
            first. */}
        {mode === GOAL_MODES.ASSIST && selectedGoals.length >= ASSIST_MIN && (
          <div style={{ marginTop: 24 }}>
            <div className="goals-priority-title" style={{ marginBottom: 12 }}>
              Tell us more about each goal
              <span style={{ display: 'block', fontSize: 12, fontWeight: 500, color: 'var(--mute)', marginTop: 4 }}>
                The more concrete you can be, the better your adviser can plan.
              </span>
            </div>
            {selectedGoals.map((g, i) => {
              const spec = GOAL_FOLLOWUPS[g];
              if (!spec) return null;
              const vals = (d.followups || {})[g] || {};
              return (
                <div key={g} className="card" style={{
                  background: 'var(--surface)', border: '1px solid var(--line)',
                  marginTop: 12, padding: '18px 18px 10px',
                }} data-ff-name={`goals.followup.${g}`}>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 12 }}>
                    <div className="priority-num" style={{
                      background: ['var(--green)','var(--blue)','var(--accent)','var(--magenta)','var(--mute)'][Math.min(i, 4)],
                      minWidth: 28, height: 28, fontSize: 13,
                    }}>{i + 1}</div>
                    <strong style={{ fontSize: 15 }}>{g}</strong>
                  </div>
                  <div className="grid-2">
                    {spec.map(field => {
                      // Conditional fields (revealIf) only render when the
                      // referenced sibling field matches. Used for things
                      // like "Estimated income on return" which only shows
                      // when the client said Yes to "return to work?".
                      if (field.revealIf) {
                        const trigger = vals[field.revealIf.key];
                        if (trigger !== field.revealIf.equals) return null;
                      }
                      const inputType = field.type === 'number' ? 'number'
                                      : field.type === 'date'   ? 'date'
                                      : undefined;
                      const fieldName = `goals.fu.${g}.${field.key}`;
                      // YesNo fields span the full row for readability and
                      // use the existing YesNo primitive so they look the
                      // same as the rest of the questionnaire.
                      // `optional: true` in the field spec opts a
                      // follow-up out of the mandatory star + the
                      // submit-gate validator. Used for "Top priority"
                      // in tax efficiency.
                      const fieldRequired = !field.optional;
                      if (field.type === 'yesno') {
                        return (
                          <Field key={field.key} label={field.label} required={fieldRequired} name={fieldName} span={2}>
                            <YesNo value={vals[field.key]}
                              onChange={v => updateFollowup(g, field.key, v)} />
                          </Field>
                        );
                      }
                      // debtPicker: chips built from the debts already
                      // captured in the Assets section, plus a free-text
                      // fallback for anything not listed there.
                      if (field.type === 'debtPicker') {
                        const a = data.assets || {};
                        const opts = [];
                        (a.loans || []).forEach((ln, idx) => {
                          const label = [ln.lender, ln.purpose].filter(Boolean).join(' - ');
                          opts.push(label || `Loan ${idx + 1}`);
                        });
                        (a.credit || []).forEach((c2, idx) => {
                          const label = [c2.provider, c2.type].filter(Boolean).join(' - ');
                          opts.push(label || `Credit facility ${idx + 1}`);
                        });
                        if (a.atoDebt === true) opts.push('ATO debt');
                        if (a.hecs === true) opts.push('HELP debt');
                        const picked = Array.isArray(vals.whichDebtList) ? vals.whichDebtList : [];
                        return (
                          <Field key={field.key} label={field.label} required={fieldRequired} name={fieldName} span={2}
                            hint={opts.length
                              ? 'Pick from the debts you entered in the Assets section - select as many as apply - or describe another below.'
                              : 'We couldn\'t find any debts in your Assets section - describe the debt below.'}>
                            {opts.length > 0 && (
                              <ChipGroup multi options={opts} value={picked}
                                onChange={arr => updateFollowup(g, 'whichDebtList', arr)} />
                            )}
                            <Input style={{ marginTop: opts.length ? 8 : 0 }}
                              value={vals.whichDebtOther || ''}
                              onChange={e => updateFollowup(g, 'whichDebtOther', e.target.value)}
                              placeholder="Or write your own - e.g. car loan with Toyota Finance" />
                          </Field>
                        );
                      }
                      if (field.type === 'select') {
                        return (
                          <Field key={field.key} label={field.label} required={fieldRequired} name={fieldName} span={2}>
                            <Select value={vals[field.key] || ''}
                              onChange={e => updateFollowup(g, field.key, e.target.value)}>
                              <option value="">Select…</option>
                              {(field.options || []).map(o => <option key={o}>{o}</option>)}
                            </Select>
                          </Field>
                        );
                      }
                      return (
                        <Field key={field.key} label={field.label} required={fieldRequired} name={fieldName}
                          span={field.type === 'textarea' ? 2 : undefined}>
                          {field.type === 'textarea'
                            ? <Textarea rows={2}
                                value={vals[field.key] || ''}
                                onChange={e => updateFollowup(g, field.key, e.target.value)}
                                placeholder={field.placeholder} />
                            : field.type === 'money'
                            ? <MoneyInput
                                value={vals[field.key] || ''}
                                onChange={e => updateFollowup(g, field.key, e.target.value)}
                                placeholder={field.placeholder} />
                            : <Input
                                type={inputType}
                                value={vals[field.key] || ''}
                                onChange={e => updateFollowup(g, field.key, e.target.value)}
                                placeholder={field.placeholder} />}
                        </Field>
                      );
                    })}
                  </div>
                </div>
              );
            })}
          </div>
        )}
      </div>

      <div className="card">
        <div className="card-title">Upcoming life events (next 1–5 years)</div>
        <ChipGroup multi
          options={['Getting married','Having a child','Children starting school','Buying a home','Moving interstate / overseas','Starting a business','Receiving an inheritance','Career change','Retirement / semi-retirement','None in particular']}
          value={d.lifeEvents}
          onChange={v => update({ lifeEvents: v })}
        />
      </div>

      <div className="card">
        <div className="card-title">Anything else?</div>
        <Field label="Other goals, concerns, or context for your adviser">
          <Textarea rows={5} value={d.freeText || ''} onChange={e => update({ freeText: e.target.value })}
            placeholder="Anything on your mind - budgeting concerns, upcoming changes, questions you have for us…" />
        </Field>
      </div>
    </div>
  );
}

Object.assign(window, { SectionGoals });
