/* global React, ReactDOM,
   V2_DATA, V2Icon, V2TopBar, V2Sidebar, V2PatientHeader,
   V2PreviousNote, V2Composer, V2Editor, V2ContextPanel, V2DiscardModal,
   TweaksPanel, useTweaks, TweakSection, TweakToggle, TweakRadio, TweakSelect */

const { useState, useEffect, useMemo } = React;

const V2_TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "composerWidth": "regular",
  "writingContextDefault": true,
  "showSourceBanner": true,
  "draftIndicator": "icon-pill"
} /*EDITMODE-END*/;

function V2App() {
  const [tweaks, setTweak] = useTweaks(V2_TWEAK_DEFAULTS);
  const data = V2_DATA;

  const [activePatientId, setActivePatientId] = useState('pt-turner');
  const [sidebarCollapsed, setSidebarCollapsed] = useState(false);
  // Compose-new-note rail starts expanded by default per design review.
  const [composerCollapsed, setComposerCollapsed] = useState(false);
  // Mode: 'quick' | 'writing'
  const [mode, setMode] = useState('quick');
  // Which note is being viewed in the center panel in quick mode (default = latest submitted)
  const [viewingNoteId, setViewingNoteId] = useState(null);
  // Which draft is open in the right panel composer / center editor
  const [activeDraftId, setActiveDraftId] = useState(null);

  // All notes are stored in app state so drafts can be added/removed/changed
  const [allNotes, setAllNotes] = useState(data.notes);

  const [analysing, setAnalysing] = useState(false);
  const [autosave, setAutosave] = useState('saved');
  const [discardTarget, setDiscardTarget] = useState(null);
  const [toast, setToast] = useState(null);

  const activePatient = data.patients.find((p) => p.id === activePatientId) || data.patients[0];
  const patientNotes = allNotes[activePatientId] || [];
  const submittedNotes = patientNotes.filter((n) => n.state === 'submitted');
  const activeDraft = patientNotes.find((n) => n.id === activeDraftId);

  // Set initial viewing note = newest submitted
  useEffect(() => {
    if (!viewingNoteId && submittedNotes.length) {
      setViewingNoteId(submittedNotes[0].id);
    }
  }, [viewingNoteId, submittedNotes]);

  // When draft is open and we're in quick mode, the right panel shows the composer
  // When mode === 'writing' the composer is hidden and editor takes center
  const showComposer = !!activeDraft && mode === 'quick';

  // Autosave debouncer
  useEffect(() => {
    if (!activeDraft) return;
    setAutosave('saving');
    const t = setTimeout(() => setAutosave('saved'), 600);
    return () => clearTimeout(t);
  }, [activeDraft?.sourceText, activeDraft?.body, activeDraft?.typeId]);

  // ─────────── Patient + note selection ───────────
  function handleSelectPatient(id) {
    setActivePatientId(id);
    setActiveDraftId(null);
    setMode('quick');
    setViewingNoteId(null);
  }

  function handleSelectNote(noteId) {
    const note = patientNotes.find((n) => n.id === noteId);
    if (!note) return;
    if (note.state === 'submitted') {
      // View previous note in quick mode (close any draft)
      setViewingNoteId(noteId);
      setMode('quick');
      setActiveDraftId(null);
    } else {
      // Open draft. If it has body (was analysed), expanded. Else compact composer.
      setActiveDraftId(noteId);
      const isReady = note.state === 'ai_draft_ready' || note.state === 'user_reviewed';
      setMode(isReady ? 'writing' : 'quick');
    }
  }

  // ─────────── Draft creation + editing ───────────
  function createNewDraft(typeId = null, seedText = '', subTypeId = null) {
    const t = typeId ? data.noteTypes.find((nt) => nt.id === typeId) : null;
    const sub = (t && subTypeId && t.subTypes) ? t.subTypes.find(s => s.id === subTypeId) : null;
    const id = `n-draft-${Date.now()}`;
    const newDraft = {
      id,
      type: t ? t.label : 'Untitled',
      typeId: t ? t.id : null,
      subType: sub ? sub.label : null,
      subTypeId: sub ? sub.id : null,
      state: 'draft',
      startedAt: 'Today · ' + data.date.clock,
      sortKey: '2026-02-17T09:30',
      author: data.user.name,
      sourceText: seedText || '',
      body: null
    };
    setAllNotes((prev) => ({
      ...prev,
      [activePatientId]: [newDraft, ...(prev[activePatientId] || [])]
    }));
    setActiveDraftId(id);
    setMode('quick');
    return id;
  }

  function updateDraft(patch) {
    if (!activeDraftId) return;
    setAllNotes((prev) => ({
      ...prev,
      [activePatientId]: (prev[activePatientId] || []).map((n) =>
      n.id === activeDraftId ? { ...n, ...patch } : n
      )
    }));
  }

  function handleChangeText(text) {
    updateDraft({ sourceText: text });
  }
  function handleChangeType(typeId) {
    if (!typeId) {
      // Clear back to free-text Untitled draft
      updateDraft({ type: 'Untitled', typeId: null, subType: null, subTypeId: null });
      return;
    }
    const nt = data.noteTypes.find((t) => t.id === typeId);
    if (!nt) return;
    updateDraft({ type: nt.label, typeId: nt.id, subType: null, subTypeId: null });
  }
  function handleChangeSubType(subTypeId) {
    if (!activeDraft) return;
    const nt = data.noteTypes.find((t) => t.id === activeDraft.typeId);
    if (!nt || !nt.subTypes) return;
    const sub = nt.subTypes.find((s) => s.id === subTypeId);
    if (!sub) return;

    // Apply template into the textarea if it's empty (or only contains a previous template).
    const tpl = (window.V2_GET_TEMPLATE && window.V2_GET_TEMPLATE(nt.id, sub.id)) || null;
    const current = activeDraft.sourceText || '';
    const looksLikePrevTemplate =
      /^[A-Z][A-Z .\-]+\s-/m.test(current.split('\n')[0] || '') ||
      current.trim() === '';
    const nextText = (tpl && (current.trim() === '' || looksLikePrevTemplate))
      ? tpl
      : current;

    updateDraft({
      subType: sub.label,
      subTypeId: sub.id,
      sourceText: nextText,
    });
  }
  function handleChangeBody(patch) {
    if (!activeDraft) return;
    const nextBody = { ...(activeDraft.body || {}), ...patch };
    updateDraft({ body: nextBody, state: 'user_reviewed' });
  }

  // ─────────── Analyse ───────────
  function handleAnalyse() {
    if (!activeDraft || !activeDraft.sourceText) return;
    updateDraft({ state: 'analysing' });
    setAnalysing(true);
    setMode('writing');
    setTimeout(() => {
      const ai = data.ai['n-draft-round']; // mock: always use the round AI
      updateDraft({
        state: 'ai_draft_ready',
        body: ai.polished
      });
      setAnalysing(false);
    }, 1400);
  }

  // ─────────── Undo generation ───────────
  function handleUndoGeneration() {
    if (!activeDraft) return;
    updateDraft({ state: 'draft', body: null });
    setMode('quick');
  }

  // ─────────── Expand / Collapse ───────────
  function handleExpand() {
    setMode('writing');
  }
  function handleCollapse() {
    if (!activeDraft) return;
    const t = data.noteTypes.find((nt) => nt.id === activeDraft.typeId);
    if (!t || !t.collapsible) return;
    if (activeDraft.state === 'ai_draft_ready' || activeDraft.state === 'user_reviewed') {
      // Already structurally complex — disallow collapse
      return;
    }
    setMode('quick');
  }

  // ─────────── Discard ───────────
  function requestDiscard(noteId) {
    const note = (allNotes[activePatientId] || []).find((n) => n.id === noteId);
    if (!note) return;
    const hasContent = !!(note.sourceText || note.body);
    if (!hasContent) {
      doDiscard(noteId);
    } else {
      setDiscardTarget({ id: noteId, label: note.type, hasContent });
    }
  }
  function doDiscard(noteId) {
    setAllNotes((prev) => ({
      ...prev,
      [activePatientId]: (prev[activePatientId] || []).filter((n) => n.id !== noteId)
    }));
    if (activeDraftId === noteId) {
      setActiveDraftId(null);
      setMode('quick');
    }
    setDiscardTarget(null);
    setToast('Draft discarded');
  }

  // ─────────── Submit ───────────
  function handleSubmit() {
    if (!activeDraft) return;
    updateDraft({
      state: 'submitted',
      submittedAt: 'Today · ' + data.date.clock
    });
    setToast('Note filed · audit logged');
    setActiveDraftId(null);
    setMode('quick');
  }

  // ─────────── Quick-mode previous note nav ───────────
  const viewingNote = patientNotes.find((n) => n.id === viewingNoteId) || submittedNotes[0];
  const submittedIdx = viewingNote ? submittedNotes.findIndex((n) => n.id === viewingNote.id) : 0;
  const canPrev = submittedIdx < submittedNotes.length - 1;
  const canNext = submittedIdx > 0;
  const goPrev = () => {
    if (!canPrev) return;
    setViewingNoteId(submittedNotes[submittedIdx + 1].id);
  };
  const goNext = () => {
    if (!canNext) return;
    setViewingNoteId(submittedNotes[submittedIdx - 1].id);
  };

  // ─────────── Toast ───────────
  useEffect(() => {
    if (!toast) return;
    const t = setTimeout(() => setToast(null), 2400);
    return () => clearTimeout(t);
  }, [toast]);

  // ─────────── Keyboard shortcuts ───────────
  // ⌘+1–9  jump to note by position
  // N      new note (when not typing)
  // Esc    return focus to note body
  useEffect(() => {
    function isTyping(el) {
      if (!el) return false;
      const tag = el.tagName;
      return tag === 'INPUT' || tag === 'TEXTAREA' || el.isContentEditable;
    }
    function railOrder() {
      const drafts = patientNotes.filter(n =>
        n.state === 'draft' || n.state === 'analysing' ||
        n.state === 'ai_draft_ready' || n.state === 'user_reviewed'
      ).slice().sort((a,b) => (b.sortKey||'').localeCompare(a.sortKey||''));
      const subs = patientNotes.filter(n => n.state === 'submitted')
        .slice().sort((a,b) => (b.sortKey||'').localeCompare(a.sortKey||''));
      return [...drafts, ...subs];
    }
    function onKey(e) {
      const meta = e.metaKey || e.ctrlKey;
      const list = railOrder();

      // ⌘+1–9 jump
      if (meta && /^[1-9]$/.test(e.key)) {
        const target = list[parseInt(e.key, 10) - 1];
        if (target) {
          e.preventDefault();
          handleSelectNote(target.id);
        }
        return;
      }
      // N → new note (when not typing)
      if (!meta && (e.key === 'n' || e.key === 'N') && !isTyping(document.activeElement)) {
        e.preventDefault();
        createNewDraft(null, '', null);
        return;
      }
      // Esc → return focus to note body
      if (e.key === 'Escape') {
        const editor = document.querySelector('[data-note-body]');
        if (editor) {
          editor.focus();
        }
      }
    }
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [patientNotes, activeDraftId, viewingNoteId]);

  // ─────────── Render ───────────
  const draftCanCollapse = activeDraft && (() => {
    const t = data.noteTypes.find((nt) => nt.id === activeDraft.typeId);
    if (!t || !t.collapsible) return false;
    if (activeDraft.state === 'ai_draft_ready' || activeDraft.state === 'user_reviewed') return false;
    return true;
  })();

  return (
    <div style={{ height: '100%', display: 'flex', flexDirection: 'row' }}>
      <V2Sidebar
        patients={data.patients}
        activePatientId={activePatientId}
        onSelectPatient={handleSelectPatient}
        notes={allNotes}
        activeNoteId={activeDraftId || viewingNoteId}
        onSelectNote={handleSelectNote}
        onDiscardDraft={requestDiscard}
        onNewNote={(pid, typeId, seedText) => {if (pid !== activePatientId) setActivePatientId(pid);createNewDraft(typeId || 'round', seedText || '');}}
        collapsed={sidebarCollapsed}
        onToggleCollapsed={() => setSidebarCollapsed(c => !c)} />

      <div style={{ flex: 1, display: 'flex', flexDirection: 'column', minWidth: 0 }}>
        <V2TopBar user={data.user} date={data.date} onSelectPatient={handleSelectPatient} />

        <div style={{ flex: 1, display: 'flex', flexDirection: 'column', minWidth: 0, minHeight: 0 }}>
          <V2PatientHeader
            patient={activePatient}
            mode={mode}
            onBackToQuick={() => setMode('quick')} />

          <div style={{ flex: 1, display: 'flex', minHeight: 0, background: 'var(--sage-50)' }}>
            {/* Center panel */}
            {mode === 'quick' ?
            <div style={{ flex: 1, display: 'flex', minWidth: 0, minHeight: 0 }}>
                {viewingNote ?
                <V2PreviousNote
                  note={viewingNote}
                  onPrev={goPrev} onNext={goNext}
                  canPrev={canPrev} canNext={canNext}
                  idx={submittedIdx} total={submittedNotes.length} /> :

                <div style={{ flex: 1, display: 'grid', placeItems: 'center', color: 'var(--sage-500)' }}>
                    No previous notes.
                  </div>
                }
                <V2ContextPanel patient={activePatient} />
              </div> :


            activeDraft &&
            <V2Editor
              draft={activeDraft}
              ai={data.ai['n-draft-round']}
              onChangeBody={handleChangeBody}
              onSubmit={handleSubmit}
              onDiscard={() => requestDiscard(activeDraft.id)}
              onCollapse={handleCollapse}
              canCollapse={draftCanCollapse} />


            }

            {/* Right panel */}
            {mode === 'quick' ?
            showComposer ?
            <V2Composer
              draft={activeDraft}
              onChangeText={handleChangeText}
              onChangeType={handleChangeType}
              onChangeSubType={handleChangeSubType}
              onAnalyse={handleAnalyse}
              onExpand={handleExpand}
              onDiscard={() => requestDiscard(activeDraft.id)}
              onClose={() => setActiveDraftId(null)}
              noteTypes={data.noteTypes}
              sources={data.ai['n-draft-round'].sources}
              autosave={autosave} /> :


            <QuickActionsRail
              onNewNote={(typeId, seedText, subTypeId) => createNewDraft(typeId || null, seedText || '', subTypeId || null)}
              patient={activePatient}
              collapsed={composerCollapsed}
              onToggleCollapsed={() => setComposerCollapsed(c => !c)} /> :


            <V2ContextPanel
              patient={activePatient}
              draft={activeDraft}
              ai={data.ai['n-draft-round']}
              onUndoGeneration={handleUndoGeneration} />
            }
          </div>
        </div>
      </div>

      <V2DiscardModal
        open={!!discardTarget}
        draftLabel={discardTarget?.label || ''}
        hasContent={!!discardTarget?.hasContent}
        onConfirm={() => discardTarget && doDiscard(discardTarget.id)}
        onCancel={() => setDiscardTarget(null)} />
      

      {toast &&
      <div style={{
        position: 'fixed', bottom: 24, left: '50%', transform: 'translateX(-50%)',
        background: 'var(--sage-900)', color: '#fff',
        padding: '10px 18px', borderRadius: 8,
        fontSize: 12.5, fontFamily: 'var(--font-sans)',
        boxShadow: 'var(--shadow-xl)',
        display: 'flex', alignItems: 'center', gap: 8,
        zIndex: 250,
        animation: 'fadeIn 180ms ease-out'
      }}>
          <V2Icon name="check" size={13} stroke="var(--primary-light)" />
          {toast}
        </div>
      }

      <TweaksPanel title="Tweaks">
        <TweakSection label="Layout">
          <TweakToggle label="Source banner in editor"
          value={tweaks.showSourceBanner}
          onChange={(v) => setTweak('showSourceBanner', v)} />
          <TweakToggle label="Patient context default open"
          value={tweaks.writingContextDefault}
          onChange={(v) => setTweak('writingContextDefault', v)} />
        </TweakSection>
        <TweakSection label="Draft indicator style">
          <TweakRadio
            label="Style"
            value={tweaks.draftIndicator}
            onChange={(v) => setTweak('draftIndicator', v)}
            options={[
            { value: 'icon-pill', label: 'Pencil + pill' },
            { value: 'icon-only', label: 'Pencil only' },
            { value: 'dot', label: 'Dot' }]
            } />
          
        </TweakSection>
      </TweaksPanel>
    </div>);

}

function QuickActionsRail({ onNewNote, patient, collapsed, onToggleCollapsed }) {
  const [seedType, setSeedType] = React.useState(null);
  const [seedSubType, setSeedSubType] = React.useState(null);
  const [seedText, setSeedText] = React.useState('');
  const types = (V2_DATA.noteTypes || []);
  const activeType = types.find(t => t.id === seedType);
  const activeSub  = activeType?.subTypes?.find(s => s.id === seedSubType);

  // Collapsed: narrow vertical strip with affordance to re-expand.
  if (collapsed) {
    return (
      <aside style={{
        width: 44, flexShrink: 0,
        background: 'var(--primary-muted)',
        borderLeft: '1px solid var(--sage-200)',
        display: 'flex', flexDirection: 'column', alignItems: 'center',
        padding: '8px 0', gap: 10,
      }}>
        <button
          onClick={onToggleCollapsed}
          aria-label="Expand compose new note"
          title="Compose new note"
          style={{
            width: 30, height: 30, border: 0, borderRadius: 6,
            background: '#fff',
            boxShadow: 'var(--shadow-sm)',
            color: 'var(--primary)', cursor: 'pointer',
            display: 'grid', placeItems: 'center', flexShrink: 0,
          }}
        >
          <V2Icon name="chevronLeft" size={13} stroke="var(--primary)" />
        </button>
        <button
          onClick={onToggleCollapsed}
          title="Compose new note"
          style={{
            border: 0, background: 'transparent', cursor: 'pointer',
            padding: '6px 0', display: 'flex', flexDirection: 'column',
            alignItems: 'center', gap: 8,
          }}>
          <V2Icon name="pencilOutline" size={14} stroke="var(--primary)" />
          <span style={{
            writingMode: 'vertical-rl',
            transform: 'rotate(180deg)',
            fontSize: 11, fontWeight: 700,
            letterSpacing: '0.08em', textTransform: 'uppercase',
            color: 'var(--primary)',
            fontFamily: 'var(--font-sans)',
          }}>
            New note
          </span>
        </button>
      </aside>
    );
  }

  function handleSeed(text) {
    setSeedText(text);
    if (text && !seedText) {
      // First keystroke — promote seed to a real draft.
      onNewNote(seedType, text, seedSubType);
    }
  }

  function handlePickType(typeId) {
    setSeedType(typeId);
    setSeedSubType(null);
    // For types without sub-types, picking the pill itself starts a draft so the
    // user lands in the full Composer immediately.
    const nt = types.find(t => t.id === typeId);
    if (typeId && (!nt?.subTypes || nt.subTypes.length === 0)) {
      onNewNote(typeId, '', null);
    }
  }

  function handlePickSubType(subTypeId) {
    setSeedSubType(subTypeId);
    // Picking a sub-type triggers template population → start the draft.
    const tpl = (window.V2_GET_TEMPLATE && window.V2_GET_TEMPLATE(seedType, subTypeId)) || '';
    onNewNote(seedType, tpl, subTypeId);
  }

  const placeholderLabel = activeSub?.label?.toLowerCase()
    || activeType?.label?.toLowerCase()
    || 'note';

  return (
    <aside style={{
      width: 360, flexShrink: 0,
      background: '#fff',
      borderLeft: '1px solid var(--sage-200)',
      display: 'flex', flexDirection: 'column',
      minHeight: 0
    }}>
      <div style={{
        padding: '10px 14px',
        borderBottom: '1px solid var(--primary)',
        background: 'var(--primary-muted)',
        display: 'flex', alignItems: 'center', gap: 8,
        flexShrink: 0
      }} data-comment-anchor="70f20cfeaf-button-374-9">
        <V2Icon name="pencilOutline" size={13} stroke="var(--primary)" />
        <span style={{
          fontSize: 11, fontWeight: 700,
          letterSpacing: '0.06em', textTransform: 'uppercase',
          color: 'var(--primary)', flex: 1
        }}>New note · {patient.name}</span>
        <button
          onClick={onToggleCollapsed}
          aria-label="Collapse compose new note"
          title="Collapse"
          style={{
            width: 24, height: 24, border: 0, borderRadius: 6,
            background: 'transparent', color: 'var(--primary)',
            cursor: 'pointer', display: 'grid', placeItems: 'center',
          }}
          onMouseEnter={e => { e.currentTarget.style.background = 'rgba(52, 76, 62, 0.10)'; }}
          onMouseLeave={e => { e.currentTarget.style.background = 'transparent'; }}
        >
          <V2Icon name="chevronRight" size={13} stroke="var(--primary)" />
        </button>
      </div>

      {/* Note-type picker (none selected by default → free text) */}
      <div style={{ padding: '12px 14px 6px 14px', flexShrink: 0 }}>
        <V2NoteTypePicker
          types={types}
          typeId={seedType}
          subTypeId={seedSubType}
          onTypeChange={handlePickType}
          onSubTypeChange={handlePickSubType}
          size="md"
        />
      </div>

      {/* Seed input — promotes to a real draft on first keystroke */}
      <div style={{ padding: '8px 14px 10px 14px', flexShrink: 0 }}>
        <textarea
          value={seedText}
          onChange={e => handleSeed(e.target.value)}
          placeholder={seedType
            ? `Quick rough notes for the ${placeholderLabel}…`
            : `Just start writing… or pick a note type above.\n\nE.g. "D3. Reasonably well o/n. No SOB/CP. Cough settling. Bloods K 6.0 — hyperK. Cancel disch."`}
          style={{
            width: '100%', minHeight: 200,
            padding: '12px 12px',
            border: '1px solid var(--sage-200)',
            borderRadius: 8, outline: 0,
            background: '#fff',
            fontFamily: 'var(--font-serif)',
            fontStyle: seedType ? 'normal' : 'italic',
            fontSize: 13.5, lineHeight: 1.55,
            color: 'var(--sage-800)', resize: 'vertical',
          }}
          onFocus={e => { e.currentTarget.style.borderColor = 'var(--primary)'; e.currentTarget.style.boxShadow = '0 0 0 3px var(--primary-muted)'; }}
          onBlur={e => { e.currentTarget.style.borderColor = 'var(--sage-200)'; e.currentTarget.style.boxShadow = 'none'; }}
        />
        <div style={{
          marginTop: 6, fontSize: 10.5, color: 'var(--sage-500)',
          fontFamily: 'var(--font-mono)',
        }}>
          Type to start a draft. Drafts autosave and appear on the left.
        </div>
      </div>

      <div style={{ padding: '0 14px 14px 14px' }}>
        <div style={{
          padding: '12px 14px', borderRadius: 8,
          background: 'var(--ai-surface)',
          border: '1px solid var(--ai-border)',
          display: 'flex', flexDirection: 'column', gap: 6
        }}>
          <div style={{
            display: 'flex', alignItems: 'center', gap: 6
          }}>
            <V2Icon name="sparkle" size={12} stroke="var(--ai)" fill="var(--ai)" />
            <span style={{
              fontSize: 10.5, fontWeight: 700,
              letterSpacing: '0.06em', textTransform: 'uppercase',
              color: 'var(--ai-text)'
            }}>How it works</span>
          </div>
          <p style={{
            margin: 0, fontSize: 11.5, color: 'var(--ai-text)',
            lineHeight: 1.5, opacity: 0.85
          }}>
            Type rough notes here. They become a draft on the left. Press <strong>Analyse</strong> to generate a structured note from your text plus this patient&rsquo;s active context.
          </p>
        </div>
      </div>
    </aside>);

}

ReactDOM.createRoot(document.getElementById('root')).render(<V2App />);