// ─── Add Module dialog ─────────────────────────────────────────────────────
// Opened from the "+ Add module" button at the bottom of the Modules column
// on Course architecture.
//
// Lets the author:
//   · name a new module
//   · place it in an existing Module Group, create a new group, or leave
//     it ungrouped
//   · optionally write a short summary
//   · choose how to seed the module's layouts:
//       – Blank             → no layouts, fill in later
//       – Generate with AI  → AI drafts ~4–6 layouts from a description
//                             (and optionally a bound source file)
//       – Duplicate         → clone an existing module's layout shape
//
// The dialog is self-contained UI; commit flows back up through onCreate(payload)
// and the App-level state in app.jsx writes the module + group additions.

function AddModuleDialog({ course, sources, defaultSeedMode = 'ai', onCancel, onCreate }) {
  const [title, setTitle] = React.useState('');
  const [summary, setSummary] = React.useState('');

  // ── Group placement ─────────────────────────────────────────────────────
  // groupId: id of an existing group, or '' for ungrouped, or '__new__' for
  // a freshly-typed group title.
  const [groupId, setGroupId] = React.useState(() => {
    // Pre-select the group the user is currently editing in, if any.
    const cur = course.modules[course.modules.length - 1];
    return cur && cur.group ? cur.group : course.moduleGroups[0]?.id || '';
  });
  const [newGroupTitle, setNewGroupTitle] = React.useState('');

  // ── Seed mode ───────────────────────────────────────────────────────────
  const [seedMode, setSeedMode] = React.useState(defaultSeedMode);
  const [aiPrompt, setAiPrompt] = React.useState('');
  const [aiSourceId, setAiSourceId] = React.useState('');
  const [duplicateId, setDuplicateId] = React.useState(course.modules[0]?.id || '');
  const [generating, setGenerating] = React.useState(false);

  // Build group buckets for the picker.
  const groupBuckets = course.moduleGroups.map((g) => ({
    ...g, count: course.modules.filter((m) => m.group === g.id).length
  }));
  const ungroupedCount = course.modules.filter((m) => !m.group).length;

  const isNewGroup = groupId === '__new__';
  const newGroupReady = !isNewGroup || newGroupTitle.trim().length > 0;
  const titleReady = title.trim().length > 0;
  const seedReady =
  seedMode === 'blank' ? true :
  seedMode === 'ai' ? aiPrompt.trim().length > 4 :
  seedMode === 'duplicate' ? !!duplicateId :
  false;
  const canSubmit = titleReady && newGroupReady && seedReady && !generating;

  const primaryLabel =
  seedMode === 'ai' ? 'Generate & add' :
  seedMode === 'duplicate' ? 'Duplicate & add' :
  'Add module';

  // Esc to dismiss.
  React.useEffect(() => {
    const h = (e) => {if (e.key === 'Escape' && !generating) onCancel();};
    window.addEventListener('keydown', h);
    return () => window.removeEventListener('keydown', h);
  }, [onCancel, generating]);

  const handleSubmit = () => {
    if (!canSubmit) return;
    const finalize = (layouts) => {
      onCreate({
        title: title.trim(),
        summary: summary.trim(),
        groupId: isNewGroup ? null : groupId || null,
        newGroupTitle: isNewGroup ? newGroupTitle.trim() : null,
        layouts,
        seedMode
      });
    };
    if (seedMode === 'ai') {
      // Brief in-dialog "generating" state to set expectations.
      setGenerating(true);
      setTimeout(() => {
        const layouts = window.fakeGenerateLayouts(title.trim(), aiPrompt.trim());
        finalize(layouts);
      }, 1400);
    } else if (seedMode === 'duplicate') {
      const m = course.modules.find((x) => x.id === duplicateId);
      const layouts = (m?.layouts || []).map((l, i) => ({
        ...l, id: `_new_L${i + 1}`, status: 'pending',
        summary: l.summary // keep summary for now; user can re-roll later
      }));
      finalize(layouts);
    } else {
      finalize([]);
    }
  };

  return (
    <div onClick={generating ? null : onCancel} style={{
      position: 'fixed', inset: 0, zIndex: 70,
      background: 'color-mix(in oklab, var(--text) 35%, transparent)',
      backdropFilter: 'blur(2px)',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      padding: 24
    }}>
      <div onClick={(e) => e.stopPropagation()} className="slide-in" style={{
        width: 640, maxWidth: '100%', maxHeight: 'calc(100vh - 48px)',
        background: 'var(--surface)', border: '1px solid var(--border)',
        borderRadius: 'var(--radius-md)', boxShadow: 'var(--shadow-xl)',
        display: 'flex', flexDirection: 'column', overflow: 'hidden'
      }}>

        {/* ── Header ───────────────────────────────────────────────── */}
        <div style={{
          padding: '16px 20px',
          borderBottom: '1px solid var(--border)',
          display: 'flex', alignItems: 'center', gap: 12
        }}>
          <span style={{
            width: 30, height: 30, borderRadius: 8,
            background: 'var(--accent-bg)', color: 'var(--accent)',
            display: 'inline-flex', alignItems: 'center', justifyContent: 'center'
          }}>
            <I.Layers size={15} />
          </span>
          <div style={{ flex: 1, minWidth: 0 }}>
            <h2 style={{ margin: 0, fontSize: 14.5, fontWeight: 600 }}>Add module</h2>
            <div style={{ fontSize: 12, color: 'var(--text-muted)' }}>
              New module · M{course.modules.length + 1}{' '}
              <span style={{ color: 'var(--text-faint)' }}>·</span>{' '}
              <span style={{ color: 'var(--text-muted)' }}>{course.title}</span>
            </div>
          </div>
          <button className="btn sm ghost" onClick={onCancel} disabled={generating}
          style={{ width: 28, height: 28, padding: 0, justifyContent: 'center' }}>
            <I.X size={13} />
          </button>
        </div>

        {/* ── Body (scrolls if tall) ───────────────────────────────── */}
        <div style={{
          flex: 1, overflowY: 'auto',
          padding: '16px 20px',
          display: 'flex', flexDirection: 'column', gap: 16
        }}>
          {/* Title + summary block */}
          <div style={{ display: 'grid', gap: 12 }}>
            <AMField label="Module title" required>
              <input value={title} autoFocus
              onChange={(e) => setTitle(e.target.value)}
              placeholder="e.g. After-action reviews"
              className="field"
              style={{ width: '100%', fontSize: 14, height: 36 }} />
            </AMField>
            <AMField label="Summary">
              <textarea value={summary} rows={2}
              onChange={(e) => setSummary(e.target.value)}
              placeholder="One line on what the learner should walk away with."
              className="field"
              style={{ width: '100%', fontSize: 13, lineHeight: 1.5,
                resize: 'vertical', minHeight: 40 }} />
            </AMField>
          </div>

          {/* Group placement */}
          <AMField label="Module group">
            <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, marginTop: 2 }}>
              <GroupChip
                icon={<I.Minus size={11} />}
                label="None"
                hint={ungroupedCount > 0 ? `${ungroupedCount} module${ungroupedCount === 1 ? '' : 's'}` : 'ungrouped'}
                selected={groupId === ''}
                onClick={() => setGroupId('')} />
              {groupBuckets.map((g) =>
              <GroupChip key={g.id}
              icon={<I.Folder size={11} />}
              label={locText(g.title)}
              selected={groupId === g.id}
              onClick={() => setGroupId(g.id)} />
              )}
              <GroupChip
                icon={<I.Plus size={11} />}
                label="New group"
                selected={isNewGroup}
                accent
                onClick={() => setGroupId('__new__')} />
            </div>
            {isNewGroup &&
            <div style={{
              marginTop: 10, display: 'flex', alignItems: 'center', gap: 8,
              padding: '10px 12px',
              background: 'var(--surface-inset)',
              border: '1px solid var(--border)',
              borderRadius: 'var(--radius-md)'
            }}>
                <I.Folder size={13} style={{ color: 'var(--text-muted)' }} />
                <input value={newGroupTitle} autoFocus
              onChange={(e) => setNewGroupTitle(e.target.value)}
              placeholder="Group name — e.g. Difficult escalations"
              className="field"
              style={{ flex: 1, height: 30, background: 'var(--surface)',
                fontSize: 13, fontWeight: 500 }} />
                <span style={{ fontSize: 11, color: 'var(--text-faint)',
                fontFamily: 'var(--font-mono)' }}>
                  +1 group
                </span>
              </div>
            }
          </AMField>

          {/* Seed mode */}
          <AMField label="Seed with">
            <div style={{ display: 'grid', gap: 8, marginTop: 2 }}>
              <SeedOption
                selected={seedMode === 'blank'}
                onSelect={() => setSeedMode('blank')}
                icon={<I.FileText size={14} />}
                title="Blank module"
                desc="" />

              <SeedOption
                selected={seedMode === 'ai'}
                onSelect={() => setSeedMode('ai')}
                icon={<I.Sparkle size={14} />}
                ai
                title="Generate with AI"
                desc="">
                {seedMode === 'ai' &&
                <div style={{ display: 'flex', flexDirection: 'column', gap: 8, marginTop: 10 }}>
                    <textarea value={aiPrompt} rows={3}
                  onChange={(e) => setAiPrompt(e.target.value)}
                  placeholder="Describe what this module should cover. e.g. ‘Three repair moves to use after a difficult conversation — Sarah & Jordan style, with one knowledge check.’"
                  className="field"
                  style={{ width: '100%', fontSize: 13, lineHeight: 1.5,
                    resize: 'vertical', minHeight: 78 }} />
                    <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                      <I.FileText size={12} style={{ color: 'var(--text-muted)' }} />
                      <span style={{ fontSize: 11.5, color: 'var(--text-muted)' }}>
                        Bind a source
                        <span style={{ color: 'var(--text-faint)' }}> · optional</span>
                      </span>
                      <select value={aiSourceId}
                    onChange={(e) => setAiSourceId(e.target.value)}
                    className="field"
                    style={{ flex: 1, height: 28, fontSize: 12 }}>
                        <option value="">No source — generate from description only</option>
                        {(sources || []).filter((s) => s.status === 'ready').map((s) =>
                      <option key={s.id} value={s.id}>{s.name}</option>
                      )}
                      </select>
                    </div>
                  </div>
                }
              </SeedOption>

              <SeedOption
                selected={seedMode === 'duplicate'}
                onSelect={() => setSeedMode('duplicate')}
                icon={<I.Copy size={14} />}
                title="Duplicate from module"
                desc="">
                {seedMode === 'duplicate' &&
                <div style={{ marginTop: 10, display: 'flex', alignItems: 'center', gap: 8 }}>
                    <I.Copy size={12} style={{ color: 'var(--text-muted)' }} />
                    <span style={{ fontSize: 11.5, color: 'var(--text-muted)' }}>
                      Source module
                    </span>
                    <select value={duplicateId}
                      onChange={(e) => setDuplicateId(e.target.value)}
                      onClick={(e) => e.stopPropagation()}
                      className="field"
                      style={{ flex: 1, height: 30, fontSize: 12.5 }}>
                      {(() => {
                        // Group the options under their Module Group so a long
                        // module list stays scannable in the dropdown.
                        const groups = (course.moduleGroups || []).map(g => ({
                          ...g,
                          modules: course.modules.filter(m => m.group === g.id),
                        }));
                        const ungrouped = course.modules.filter(m => !m.group);
                        const opt = (m) => (
                          <option key={m.id} value={m.id}>
                            M{m.n} · {locText(m.title)} · {m.layouts.length} layout{m.layouts.length === 1 ? '' : 's'}
                          </option>
                        );
                        return <>
                          {groups.filter(g => g.modules.length).map(g => (
                            <optgroup key={g.id} label={locText(g.title)}>{g.modules.map(opt)}</optgroup>
                          ))}
                          {ungrouped.length > 0 && (
                            <optgroup label="(Ungrouped)">{ungrouped.map(opt)}</optgroup>
                          )}
                        </>;
                      })()}
                    </select>
                  </div>
                }
              </SeedOption>
            </div>
          </AMField>
        </div>

        {/* ── Footer ───────────────────────────────────────────────── */}
        <div style={{
          padding: '12px 20px',
          borderTop: '1px solid var(--border)',
          background: 'var(--surface-inset)',
          display: 'flex', alignItems: 'center', gap: 10
        }}>
          <span style={{ fontSize: 11, color: 'var(--text-faint)' }}>
            {seedMode === 'duplicate'
              ? <><I.Info size={11} /> Source bindings are not carried over.</>
              : null}
          </span>
          <div style={{ flex: 1 }} />
          <button className="btn sm" onClick={onCancel} disabled={generating}>
            Cancel
          </button>
          <button className="btn sm primary" onClick={handleSubmit}
          disabled={!canSubmit}
          style={{ minWidth: 130, justifyContent: 'center' }}>
            {generating ?
            <><I.Loader size={12} className="spin" />Generating layouts…</> :
            seedMode === 'ai' ?
            <><I.Sparkle size={12} />{primaryLabel}</> :
            seedMode === 'duplicate' ?
            <><I.Copy size={12} />{primaryLabel}</> :
            <><I.Plus size={12} />{primaryLabel}</>}
          </button>
        </div>
      </div>
    </div>);

}

// ─── Helpers ───────────────────────────────────────────────────────────────

function AMField({ label, subtitle, required, children }) {
  return (
    <label style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
      <span style={{ fontSize: 11.5, fontWeight: 600, color: 'var(--text-muted)',
        letterSpacing: '.02em' }}>
        {label}{required && <span style={{ color: 'var(--accent)', marginLeft: 2 }}>*</span>}
      </span>
      {children}
      {subtitle &&
      <span style={{ fontSize: 11, color: 'var(--text-faint)', marginTop: 2 }}>{subtitle}</span>
      }
    </label>);

}

function GroupChip({ icon, label, hint, selected, accent, onClick }) {
  // The "+ New group" chip is a primary-style affordance: it always carries
  // the accent tint so the create action stands out from the existing groups.
  const bg =
    accent ? 'var(--accent-bg)' :
    selected ? 'var(--accent-bg)' : 'var(--surface)';
  const borderColor =
    accent ? 'var(--accent-border)' :
    selected ? 'var(--accent-border)' : 'var(--border)';
  const color =
    accent ? 'var(--accent-text)' :
    selected ? 'var(--text)' : 'var(--text)';
  const iconColor =
    accent ? 'var(--accent)' :
    selected ? 'var(--text-muted)' : 'var(--text-muted)';
  return (
    <button onClick={onClick}
    style={{
      display: 'inline-flex', alignItems: 'center', gap: 6,
      padding: '6px 10px',
      background: bg,
      border: '1px solid',
      borderColor,
      color,
      borderRadius: 'var(--radius)',
      boxShadow: selected ? '0 0 0 1px ' + (accent ? 'var(--accent)' : 'var(--accent-border)') : 'none',
      fontFamily: 'inherit', fontSize: 12.5, fontWeight: 500,
      cursor: 'default',
      transition: 'border-color 120ms, background 120ms'
    }}>
      <span style={{ display: 'inline-flex', color: iconColor }}>{icon}</span>
      <span>{label}</span>
      {hint && <span style={{ fontSize: 10.5, color: 'var(--text-faint)',
        fontFamily: 'var(--font-mono)' }}>{hint}</span>}
    </button>);

}

function SeedOption({ selected, onSelect, icon, title, desc, ai, children }) {
  const hasDesc = desc && String(desc).trim().length > 0;
  return (
    <div onClick={onSelect}
    style={{
      padding: '10px 14px',
      background: selected ? 'var(--surface)' : 'var(--surface)',
      border: '1px solid',
      borderColor: selected ? 'var(--accent-border)' : 'var(--border)',
      boxShadow: selected ? '0 0 0 1px var(--accent-border)' : 'none',
      borderRadius: 'var(--radius-md)',
      cursor: 'default',
      transition: 'border-color 120ms, box-shadow 120ms'
    }}
    onMouseOver={(e) => {if (!selected) e.currentTarget.style.borderColor = 'var(--text-faint)';}}
    onMouseOut={(e) => {if (!selected) e.currentTarget.style.borderColor = 'var(--border)';}}>
      <div style={{ display: 'grid',
        gridTemplateColumns: 'auto auto 1fr', gap: 10,
        alignItems: 'center' }}>
        <span style={{
          width: 16, height: 16, borderRadius: '50%',
          border: '1.5px solid', borderColor: selected ? 'var(--accent)' : 'var(--border-strong)',
          background: selected ? 'var(--accent)' : 'transparent',
          display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
          flexShrink: 0,
        }}>
          {selected && <span style={{ width: 6, height: 6, borderRadius: '50%',
            background: 'var(--text-on-accent)' }} />}
        </span>
        <span style={{
          width: 26, height: 26, borderRadius: 7,
          background: ai ?
          'color-mix(in oklab, var(--ai) 14%, transparent)' :
          'var(--surface-inset)',
          color: ai ? 'var(--ai)' : 'var(--text-muted)',
          display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
          flexShrink: 0,
        }}>{icon}</span>
        <div style={{ minWidth: 0, display: 'flex', alignItems: 'center', gap: 6 }}>
          <span style={{ fontSize: 13.5, fontWeight: 600, color: 'var(--text)' }}>{title}</span>
          {ai && <span className="pill ai" style={{ fontSize: 10 }}>AI</span>}
          {hasDesc && (
            <span style={{ fontSize: 12, color: 'var(--text-muted)',
              lineHeight: 1.4, marginLeft: 4 }}>· {desc}</span>
          )}
        </div>
      </div>
      {children &&
      <div onClick={(e) => e.stopPropagation()} style={{ paddingLeft: 36 }}>
          {children}
        </div>
      }
    </div>);

}

// ─── Fake AI layout generator ─────────────────────────────────────────────
// Produces a plausible sequence of layouts seeded from the title + prompt
// so the prototype feels like the real flow. Real implementation hits the
// model and returns actual proposals.
function fakeGenerateLayouts(title, prompt) {
  const t = (title || '').toLowerCase();
  const p = (prompt || '').toLowerCase();
  const wantsVideo = /video|interview|sme|footage/.test(p);
  const wantsScenario = /scenario|story|sarah|jordan|customer|dialogue|walk/.test(p);
  const wantsAssess = /question|check|assess|quiz|test/.test(p);
  const wantsCompare = /compare|vs\.?|side[- ]by[- ]side|framework/.test(p);

  const layouts = [
  { type: 'title', summary: title || 'Section opener' },
  { type: 'fullscreen_text_and_image',
    summary: 'Why this matters — opening claim with hero image.' }];

  if (wantsCompare) {
    layouts.push({ type: 'vertical_tabs',
      summary: 'Side-by-side compare · key distinctions in 2–3 tabs.' });
  } else {
    layouts.push({ type: 'text_and_image',
      summary: 'Three principles, each with a paired example.' });
  }
  if (wantsScenario) {
    layouts.push({ type: 'sequence',
      summary: '6-step scenario · grounded in the source material.' });
  }
  if (wantsVideo) {
    layouts.push({ type: 'small_video',
      summary: 'SME clip · ~2 min · auto-cued from the bound source.' });
  }
  layouts.push({ type: wantsAssess ? 'mandatoryQuestion' : 'question',
    summary: wantsAssess ?
    'Mandatory check — must pass to continue.' :
    'Light knowledge check — non-blocking.' });

  return layouts.slice(0, 6).map((l, i) => ({
    id: `_gen_L${i + 1}`,
    n: i + 1,
    type: l.type,
    status: 'proposed',
    summary: l.summary
  }));
}

Object.assign(window, { AddModuleDialog, fakeGenerateLayouts });