/* Markdown parser + lesson reader for AI-Native PM OS */
const { useState: useStateMD, useEffect: useEffectMD, useRef: useRefMD } = React;

/* ---------- Markdown parser ---------- */
function escapeHTML(s) {
  return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
}
function inline(s) {
  let out = escapeHTML(s);
  out = out.replace(/`([^`]+)`/g, '<code>$1</code>');
  out = out.replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>');
  out = out.replace(/\*([^*]+)\*/g, '<em>$1</em>');
  out = out.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2" target="_blank" rel="noopener noreferrer">$1</a>');
  return out;
}

function parseMarkdown(md) {
  const lines = md.split(/\r?\n/);
  const blocks = [];
  let i = 0;
  while (i < lines.length) {
    const line = lines[i];
    // fenced code
    if (/^```/.test(line)) {
      const lang = line.replace(/^```/, '').trim();
      const codeLines = [];
      i++;
      while (i < lines.length && !/^```/.test(lines[i])) {
        codeLines.push(lines[i]); i++;
      }
      i++; // close
      blocks.push({ type: 'code', lang, code: codeLines.join('\n') });
      continue;
    }
    // heading
    const h = line.match(/^(#{1,6})\s+(.*)$/);
    if (h) {
      blocks.push({ type: 'heading', level: h[1].length, text: h[2] });
      i++; continue;
    }
    // hr
    if (/^---+\s*$/.test(line)) { blocks.push({ type: 'hr' }); i++; continue; }
    // blockquote
    if (/^>\s?/.test(line)) {
      const buf = [];
      while (i < lines.length && /^>\s?/.test(lines[i])) {
        buf.push(lines[i].replace(/^>\s?/, '')); i++;
      }
      blocks.push({ type: 'quote', text: buf.join(' ') });
      continue;
    }
    // unordered list
    if (/^\s*[-*]\s+/.test(line)) {
      const items = [];
      while (i < lines.length && /^\s*[-*]\s+/.test(lines[i])) {
        items.push(lines[i].replace(/^\s*[-*]\s+/, '')); i++;
      }
      blocks.push({ type: 'ul', items });
      continue;
    }
    // ordered list
    if (/^\s*\d+\.\s+/.test(line)) {
      const items = [];
      while (i < lines.length && /^\s*\d+\.\s+/.test(lines[i])) {
        items.push(lines[i].replace(/^\s*\d+\.\s+/, '')); i++;
      }
      blocks.push({ type: 'ol', items });
      continue;
    }
    // table: header row + separator row of dashes/colons + body rows
    if (/^\s*\|.*\|\s*$/.test(line) && i + 1 < lines.length && /^\s*\|?\s*:?-{2,}:?\s*(\|\s*:?-{2,}:?\s*)+\|?\s*$/.test(lines[i+1])) {
      const splitRow = (row) => {
        let s = row.trim();
        if (s.startsWith('|')) s = s.slice(1);
        if (s.endsWith('|')) s = s.slice(0, -1);
        return s.split('|').map(c => c.trim());
      };
      const header = splitRow(line);
      const sepCells = splitRow(lines[i+1]);
      const align = sepCells.map(c => {
        const left = c.startsWith(':'); const right = c.endsWith(':');
        if (left && right) return 'center';
        if (right) return 'right';
        if (left) return 'left';
        return null;
      });
      i += 2;
      const rows = [];
      while (i < lines.length && /^\s*\|.*\|\s*$/.test(lines[i])) {
        rows.push(splitRow(lines[i])); i++;
      }
      blocks.push({ type: 'table', header, align, rows });
      continue;
    }
    // blank
    if (/^\s*$/.test(line)) { i++; continue; }
    // paragraph (collect until blank or block start)
    const buf = [line];
    i++;
    while (i < lines.length && !/^\s*$/.test(lines[i]) && !/^```/.test(lines[i]) && !/^#{1,6}\s/.test(lines[i]) && !/^---+\s*$/.test(lines[i]) && !/^>\s?/.test(lines[i]) && !/^\s*[-*]\s+/.test(lines[i]) && !/^\s*\d+\.\s+/.test(lines[i])) {
      buf.push(lines[i]); i++;
    }
    blocks.push({ type: 'p', text: buf.join(' ') });
  }
  return blocks;
}

/* ---------- Surface detector ---------- */
function detectSurface(lang, code) {
  const l = (lang || '').toLowerCase();
  if (l === 'bash' || l === 'sh' || l === 'shell' || l === 'zsh') return 'terminal';
  if (l === 'claude' || l === 'claude-code') return 'claude';
  // heuristic on content
  const first = (code || '').split('\n').find(x => x.trim()) || '';
  if (/^(npm|brew|sudo|node|claude\s+(--|config|\/)|cd\s|mkdir|ls\s|git\s|export\s|curl\s)/.test(first.trim())) return 'terminal';
  if (/^claude\s/.test(first.trim())) return 'terminal'; // claude CLI command
  if (/^\s*\//.test(first) && /^\/[a-z]/.test(first.trim())) return 'claude'; // /init, /load
  if (l === 'json' || l === 'yaml' || l === 'yml' || l === 'md' || l === 'markdown' || l === 'txt') return 'file';
  return 'code';
}

const SURFACE_META = {
  terminal: { label: 'Terminal', icon: '▸', hint: 'Run this in your terminal (macOS Terminal, iTerm, or Windows PowerShell).' },
  claude:   { label: 'Claude Code', icon: '✦', hint: 'Type this inside Claude Code (the agent prompt, not your shell).' },
  file:     { label: 'File contents', icon: '◧', hint: 'Paste this into a file in your project.' },
  code:     { label: 'Code', icon: '·', hint: 'Reference snippet - copy as needed.' },
};

/* ---------- Code block ---------- */
function CodeBlock({ lang, code }) {
  const surface = detectSurface(lang, code);
  const meta = SURFACE_META[surface];
  const [copied, setCopied] = useStateMD(false);
  const [copyErr, setCopyErr] = useStateMD(false);
  const copy = async () => {
    let ok = false;
    // Try modern API first
    try {
      if (navigator.clipboard && window.isSecureContext) {
        await navigator.clipboard.writeText(code);
        ok = true;
      }
    } catch (e) { /* fall through */ }
    // Fallback: hidden textarea + execCommand
    if (!ok) {
      try {
        const ta = document.createElement('textarea');
        ta.value = code;
        ta.setAttribute('readonly', '');
        ta.style.position = 'fixed';
        ta.style.top = '0';
        ta.style.left = '0';
        ta.style.opacity = '0';
        ta.style.pointerEvents = 'none';
        document.body.appendChild(ta);
        ta.focus();
        ta.select();
        ta.setSelectionRange(0, code.length);
        ok = document.execCommand('copy');
        document.body.removeChild(ta);
      } catch (e) { ok = false; }
    }
    if (ok) {
      setCopied(true);
      setCopyErr(false);
      setTimeout(() => setCopied(false), 1600);
    } else {
      setCopyErr(true);
      setTimeout(() => setCopyErr(false), 2400);
    }
  };
  return (
    <div className={`mdcode mdcode-${surface}`}>
      <div className="mdcode-bar">
        <span className="mdcode-surface">
          <span className="mdcode-icon">{meta.icon}</span>
          {meta.label}{lang ? <span className="mdcode-lang">· {lang}</span> : null}
        </span>
        <button
          className={`mdcode-copy ${copied ? 'ok' : ''} ${copyErr ? 'err' : ''}`}
          onClick={copy}
          type="button"
        >
          {copied ? '✓ Copied' : copyErr ? 'Select & copy ↓' : 'Copy'}
        </button>
      </div>
      <div className="mdcode-hint">{meta.hint}</div>
      <pre><code>{code}</code></pre>
    </div>
  );
}

/* ---------- Renderer ---------- */
function MarkdownRender({ md }) {
  const blocks = React.useMemo(() => parseMarkdown(md), [md]);
  return (
    <div className="md">
      {blocks.map((b, i) => {
        switch (b.type) {
          case 'heading':
            return React.createElement(`h${Math.min(6, b.level)}`, { key: i, dangerouslySetInnerHTML: { __html: inline(b.text) } });
          case 'p':
            return <p key={i} dangerouslySetInnerHTML={{__html: inline(b.text)}}/>;
          case 'ul':
            return <ul key={i}>{b.items.map((it, j) => <li key={j} dangerouslySetInnerHTML={{__html: inline(it)}}/>)}</ul>;
          case 'ol':
            return <ol key={i}>{b.items.map((it, j) => <li key={j} dangerouslySetInnerHTML={{__html: inline(it)}}/>)}</ol>;
          case 'quote':
            return <blockquote key={i} dangerouslySetInnerHTML={{__html: inline(b.text)}}/>;
          case 'hr':
            return <hr key={i}/>;
          case 'code':
            return <CodeBlock key={i} lang={b.lang} code={b.code}/>;
          case 'table':
            return (
              <div key={i} className="md-table-wrap">
                <table className="md-table">
                  <thead>
                    <tr>
                      {b.header.map((h, j) => (
                        <th key={j} style={b.align[j] ? {textAlign: b.align[j]} : null} dangerouslySetInnerHTML={{__html: inline(h)}}/>
                      ))}
                    </tr>
                  </thead>
                  <tbody>
                    {b.rows.map((r, ri) => (
                      <tr key={ri}>
                        {r.map((c, ci) => (
                          <td key={ci} style={b.align[ci] ? {textAlign: b.align[ci]} : null} dangerouslySetInnerHTML={{__html: inline(c)}}/>
                        ))}
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
            );
          default:
            return null;
        }
      })}
    </div>
  );
}

/* ---------- Lesson Reader ---------- */
const LESSON_PATHS = {
  '0-1':'content/module-0/0-1-install-and-setup.md','0-2':'content/module-0/0-2-claude-modes.md','0-3':'content/module-0/0-3-build-four-folders.md','0-4':'content/module-0/0-4-two-core-files.md','0-5':'content/module-0/0-5-slash-commands-and-skills.md','0-6':'content/module-0/0-6-connect-first-tool.md','0-7':'content/module-0/0-7-pm-ai-mental-model.md','0-8':'content/module-0/0-8-token-economics.md',
  '1-1':'content/module-1/1-1-claude-md-hierarchy.md','1-2':'content/module-1/1-2-what-goes-in-each-layer.md','1-3':'content/module-1/1-3-claude-md-templates.md','1-4':'content/module-1/1-4-self-improving-claude-md.md','1-5':'content/module-1/1-5-team-claude-md.md',
  '2-1':'content/module-2/2-1-read-write-reference-files.md','2-2':'content/module-2/2-2-learning-companion.md','2-3':'content/module-2/2-3-sub-agents-parallel-tasks.md','2-4':'content/module-2/2-4-project-memory.md','2-5':'content/module-2/2-5-pm-vault-organization.md',
  '3-1':'content/module-3/3-1-prd-from-scratch.md','3-2':'content/module-3/3-2-multi-perspective-review.md','3-3':'content/module-3/3-3-prd-to-ticket-pipeline.md','3-4':'content/module-3/3-4-lightweight-specs.md','3-5':'content/module-3/3-5-prd-versioning.md',
  '4-1':'content/module-4/4-1-connecting-to-data.md','4-2':'content/module-4/4-2-narrative-analytics.md','4-3':'content/module-4/4-3-retention-churn-analysis.md','4-4':'content/module-4/4-4-ab-test-design.md','4-5':'content/module-4/4-5-automated-weekly-digest.md',
  '5-1':'content/module-5/5-1-interview-synthesis.md','5-2':'content/module-5/5-2-support-ticket-mining.md','5-3':'content/module-5/5-3-competitive-intelligence.md','5-4':'content/module-5/5-4-jtbd-mapping.md','5-5':'content/module-5/5-5-discovery-memo.md',
  '6-1':'content/module-6/6-1-opportunity-sizing.md','6-2':'content/module-6/6-2-roadmap-reasoning.md','6-3':'content/module-6/6-3-executive-narrative.md','6-4':'content/module-6/6-4-objection-simulation.md','6-5':'content/module-6/6-5-qbr-and-strategy-docs.md',
  '7-1':'content/module-7/7-1-what-is-mcp.md','7-2':'content/module-7/7-2-connecting-jira.md','7-3':'content/module-7/7-3-connecting-slack.md','7-4':'content/module-7/7-4-connecting-amplitude.md','7-5':'content/module-7/7-5-connecting-notion.md','7-6':'content/module-7/7-6-connecting-google-workspace.md','7-7':'content/module-7/7-7-custom-mcp-servers.md','7-8':'content/module-7/7-8-additional-connectors.md',
  '8-1':'content/module-8/8-1-shared-team-claude-md.md','8-2':'content/module-8/8-2-decision-log.md','8-3':'content/module-8/8-3-shared-context-design.md','8-4':'content/module-8/8-4-knowledge-map.md','8-5':'content/module-8/8-5-vault-audit.md',
  '9-1':'content/module-9/9-1-build-loop.md','9-2':'content/module-9/9-2-metrics-dashboard.md','9-3':'content/module-9/9-3-research-portal.md','9-4':'content/module-9/9-4-interactive-prototypes.md','9-5':'content/module-9/9-5-deploy-on-vercel.md',
  '10-1':'content/module-10/10-1-choose-capstone.md','10-2a':'content/module-10/10-2a-capstone-zero-to-one.md','10-2b':'content/module-10/10-2b-capstone-scale.md','10-2c':'content/module-10/10-2c-capstone-platform.md','10-3':'content/module-10/10-3-four-mental-models.md','10-4':'content/module-10/10-4-peer-review.md','10-5':'content/module-10/10-5-pm-ai-principles.md',
};

const lessonCache = {};

function LessonReader({ lessonId, lesson, onClose, onComplete, isDone, onNav }) {
  const [md, setMd] = useStateMD(null);
  const [err, setErr] = useStateMD(null);
  const scrollRef = useRefMD(null);

  useEffectMD(() => {
    if (!lessonId) return;
    setMd(null); setErr(null);
    if (lessonCache[lessonId]) { setMd(lessonCache[lessonId]); return; }
    const path = LESSON_PATHS[lessonId];
    if (!path) { setErr('Lesson content not yet wired in.'); return; }
    fetch(path)
      .then(r => r.ok ? r.text() : Promise.reject(r.status))
      .then(t => { lessonCache[lessonId] = t; setMd(t); })
      .catch(e => setErr('Could not load lesson (' + e + ').'));
    if (scrollRef.current) scrollRef.current.scrollTop = 0;
  }, [lessonId]);

  useEffectMD(() => {
    if (!lessonId) return;
    const onKey = (e) => {
      if (e.key === 'Escape') onClose();
    };
    document.addEventListener('keydown', onKey);
    return () => {
      document.removeEventListener('keydown', onKey);
    };
  }, [lessonId, onClose]);

  useEffectMD(() => {
    if (lessonId) {
      document.body.style.overflow = 'hidden';
    } else {
      document.body.style.overflow = '';
    }
  }, [lessonId]);

  if (!lessonId) return null;

  return (
    <div className="reader-shell" role="dialog" aria-modal="true">
      <div className="reader-backdrop" onClick={onClose}></div>
      <div className="reader">
        <header className="reader-head">
          <div className="reader-crumb">
            <span className="reader-id">Lesson {lessonId}</span>
            <span className="reader-title-mini">{lesson?.title}</span>
          </div>
          <div className="reader-actions">
            <button className="reader-btn ghost" onClick={() => onNav(-1)} type="button" title="Previous lesson">← Prev</button>
            <button className="reader-btn ghost" onClick={() => onNav(1)} type="button" title="Next lesson">Next →</button>
            <button
              className={`reader-btn complete ${isDone ? 'done' : ''}`}
              onClick={onComplete}
              type="button"
            >
              {isDone ? '✓ Completed' : 'Mark complete'}
            </button>
            <button className="reader-close" onClick={onClose} type="button" aria-label="Close">×</button>
          </div>
        </header>
        <div className="reader-body" ref={scrollRef}>
          {!md && !err && <div className="reader-loading">Loading lesson…</div>}
          {err && (
            <div className="reader-error">
              <strong>Heads up.</strong>
              <p>{err} The full lesson lives in the GitHub repo.</p>
              <a href="https://github.com/vishalmdi/ai-native-pm-os" target="_blank" rel="noopener noreferrer" className="btn btn-primary">Open on GitHub →</a>
            </div>
          )}
          {md && (
            <article>
              <MarkdownRender md={md}/>
              <div className="reader-finish">
                <button
                  className={`reader-btn-big ${isDone ? 'done' : ''}`}
                  onClick={onComplete}
                  type="button"
                >
                  {isDone ? '✓ Lesson completed - go again' : 'Mark this lesson complete'}
                </button>
                <button className="reader-btn ghost" onClick={() => onNav(1)} type="button">
                  Next lesson →
                </button>
              </div>
            </article>
          )}
        </div>
      </div>
    </div>
  );
}

window.LessonReader = LessonReader;
