import type { ReactNode } from 'react';
import { injectDatasets, type LessonBlock, type ParsedLesson } from '@core/lesson-parse';
import { chartConfigForSelection } from '@core/vega-themes';
import { SpecProgression } from './SpecProgression';
import { LandingChart } from '../landing/LandingChart';
import { Markdown } from './Markdown';
import styles from './Learn.module.css';

type ChartConfig = ReturnType<typeof chartConfigForSelection>;

/** One lesson, rendered from its parsed blocks in document order, at `/learn/<slug>/`. */
export function LessonView({
  lesson,
  config,
}: {
  lesson: ParsedLesson;
  config: ChartConfig;
}): ReactNode {
  return (
    <article className={styles.article}>
      <a className={styles.backLink} href="/learn/">
        ← All deep dives
      </a>
      <p className={styles.kickerLine}>Deep dive</p>
      <h1 className={styles.title}>{lesson.title}</h1>
      <p className={styles.tagline}>{lesson.tagline}</p>

      {lesson.blocks.map((block, i) => (
        <LessonBlockView key={i} block={block} datasets={lesson.datasets} config={config} />
      ))}

      <div className={styles.cta}>
        <p>
          Open this spec in Astrolabe and keep tweaking — edit the JSON, swap the data, theme it.
        </p>
        <a className={styles.ctaButton} href="/app/">
          Open in Astrolabe →
        </a>
      </div>
    </article>
  );
}

/** Render one lesson block by type — the document is assembled in this order. */
function LessonBlockView({
  block,
  datasets,
  config,
}: {
  block: LessonBlock;
  datasets: Record<string, unknown[]>;
  config: ChartConfig;
}): ReactNode {
  switch (block.type) {
    case 'prose':
      return <Markdown className={styles.prose} source={block.markdown} />;
    case 'progression':
      return (
        <div className={styles.block}>
          <SpecProgression stages={block.stages} datasets={datasets} config={config} />
        </div>
      );
    case 'chart':
      return (
        <div className={styles.block}>
          <LandingChart
            spec={injectDatasets(block.spec, datasets)}
            config={config}
            className={styles.chart}
          />
        </div>
      );
    case 'callout':
      return (
        <Markdown
          className={block.variant === 'sharp-edge' ? styles.sharpEdge : styles.callout}
          source={block.markdown}
        />
      );
    default: {
      const exhaustive: never = block;
      return exhaustive;
    }
  }
}
