import type { ReactNode } from 'react';
import { useEffect, useRef, useState } from 'react';
import { motion } from 'motion/react';
import { Box, Divider, Stack, Tabs, Tab } from '@mui/material';
import EmailOutlinedIcon from '@mui/icons-material/EmailOutlined';
import GitHubIcon from '@mui/icons-material/GitHub';
import LinkedInIcon from '@mui/icons-material/LinkedIn';
import LanguageIcon from '@mui/icons-material/Language';
import { Text } from '../text';
import { SkillsChipList } from '../SkillsChipList';
import { CommonLink } from '../CommonLink';
import {
  StaggerChildren,
  MotionItem,
  useMotionScale,
  duration,
  scaleDuration,
  scaleStagger,
} from '../../motion';
import {
  renderExperienceDescriptionContent,
  renderExperienceProjectContent,
  renderExperienceSegments,
} from './experienceContent';
import {
  storyContentContainer,
  storyLabelReveal,
  storyTitleReveal,
  storyMetaReveal,
  storyBodyReveal,
  storyChipsReveal,
  storyLinkReveal,
  storyBulletContainer,
  storyBulletItem,
  storyDividerReveal,
} from '../../motion/variants';
import type { CVStoryItem, CVStoryContactChannel } from '../../types/cv';
import { useComponentStyles } from '../../styles/componentStyles';

type CVStorySectionRendererProps = {
  item: CVStoryItem;
  index: number;
  isRevealed: boolean;
  onSectionSettled?: () => void;
};

const STORY_DELAY_CHILDREN_MS = 250;
const STORY_STAGGER_MS = 140;
const STORY_SLIDE_TIMEOUT_MS = 220;
const STORY_LABEL_DURATION_MS = Math.round(duration.fast * 1000);
const STORY_TITLE_DURATION_MS = Math.round(duration.slow * 1000);
const STORY_META_DURATION_MS = Math.round(duration.normal * 1000);
const STORY_BODY_DURATION_MS = Math.round(duration.normal * 1000);
const STORY_CHIPS_DURATION_MS = Math.round(duration.normal * 1000);
const STORY_LINK_DURATION_MS = Math.round(duration.normal * 1000);

const getStorySequenceStartDelayMs = (sequenceIndex: number, staggerFactor: number) =>
  Math.round(
    scaleStagger(STORY_DELAY_CHILDREN_MS + STORY_STAGGER_MS * sequenceIndex, staggerFactor)
  );

const getStoryMotionItemFinishMs = (
  sequenceIndex: number,
  variantDurationMs: number,
  durationFactor: number,
  staggerFactor: number
) =>
  getStorySequenceStartDelayMs(sequenceIndex, staggerFactor) +
  Math.round(scaleDuration(variantDurationMs, durationFactor));

const getStorySkillsFinishMs = (
  sequenceIndex: number,
  skillCount: number,
  durationFactor: number,
  staggerFactor: number,
  resolvedItemStaggerMs: number
) =>
  getStorySequenceStartDelayMs(sequenceIndex, staggerFactor) +
  Math.round(scaleDuration(STORY_CHIPS_DURATION_MS, durationFactor)) +
  Math.round(scaleDuration(STORY_SLIDE_TIMEOUT_MS, durationFactor)) +
  Math.max(skillCount - 1, 0) * resolvedItemStaggerMs;

const getStorySectionSettleDelayMs = (
  item: CVStoryItem,
  durationFactor: number,
  staggerFactor: number,
  resolvedItemStaggerMs: number
) => {
  if (durationFactor === 0) {
    return 0;
  }

  const finishTimes: number[] = [];
  let sequenceIndex = 0;

  const pushMotionItem = (variantDurationMs: number) => {
    finishTimes.push(
      getStoryMotionItemFinishMs(sequenceIndex, variantDurationMs, durationFactor, staggerFactor)
    );
    sequenceIndex += 1;
  };

  const pushSkills = (skillCount: number) => {
    finishTimes.push(
      getStorySkillsFinishMs(
        sequenceIndex,
        skillCount,
        durationFactor,
        staggerFactor,
        resolvedItemStaggerMs
      )
    );
    sequenceIndex += 1;
  };

  switch (item.kind) {
    case 'about': {
      pushMotionItem(STORY_LABEL_DURATION_MS);
      pushMotionItem(STORY_TITLE_DURATION_MS);
      pushMotionItem(STORY_META_DURATION_MS);
      pushMotionItem(STORY_BODY_DURATION_MS);

      if (item.data.opportunities && item.data.opportunities.length > 0) {
        pushSkills(item.data.opportunities.length);
      }

      if (item.data.bioLink) {
        pushMotionItem(STORY_LINK_DURATION_MS);
      }

      break;
    }

    case 'experience': {
      pushMotionItem(STORY_LABEL_DURATION_MS);
      pushMotionItem(STORY_TITLE_DURATION_MS);
      pushMotionItem(STORY_META_DURATION_MS);

      if (item.data.description) {
        pushMotionItem(STORY_BODY_DURATION_MS);
      }

      if (item.data.projects && item.data.projects.length > 0) {
        pushMotionItem(STORY_BODY_DURATION_MS);
      }

      if (item.data.skills && item.data.skills.length > 0) {
        pushSkills(item.data.skills.length);
      }

      break;
    }

    case 'education': {
      pushMotionItem(STORY_LABEL_DURATION_MS);
      pushMotionItem(STORY_TITLE_DURATION_MS);
      pushMotionItem(STORY_META_DURATION_MS);

      if (item.data.gpa && item.data.gpa.length > 0) {
        pushMotionItem(STORY_META_DURATION_MS);
      }

      pushMotionItem(STORY_BODY_DURATION_MS);

      if (item.data.highlights && item.data.highlights.length > 0) {
        pushMotionItem(STORY_BODY_DURATION_MS);
      }

      if (item.data.skills && item.data.skills.length > 0) {
        pushSkills(item.data.skills.length);
      }

      break;
    }

    case 'certificate': {
      pushMotionItem(STORY_LABEL_DURATION_MS);
      pushMotionItem(STORY_TITLE_DURATION_MS);
      pushMotionItem(STORY_META_DURATION_MS);

      if (item.data.link) {
        pushMotionItem(STORY_LINK_DURATION_MS);
      }

      break;
    }

    case 'volunteering': {
      pushMotionItem(STORY_LABEL_DURATION_MS);
      pushMotionItem(STORY_TITLE_DURATION_MS);
      pushMotionItem(STORY_META_DURATION_MS);
      pushMotionItem(STORY_BODY_DURATION_MS);

      if (item.data.highlights && item.data.highlights.length > 0) {
        pushMotionItem(STORY_BODY_DURATION_MS);
      }

      break;
    }

    case 'coding': {
      const primaryLink = item.data.links?.[0];
      const skillsTabs = (item.data.tabs ?? []).filter(
        (tab): tab is Extract<typeof tab, { kind: 'skills' }> => tab.kind === 'skills'
      );
      const allTabs = item.data.tabs ?? [];

      pushMotionItem(STORY_LABEL_DURATION_MS);
      pushMotionItem(STORY_TITLE_DURATION_MS);
      pushMotionItem(STORY_BODY_DURATION_MS);

      if (primaryLink) {
        pushMotionItem(STORY_LINK_DURATION_MS);
      }

      if (allTabs.length === 1 && skillsTabs.length === 1) {
        pushSkills(skillsTabs[0].skills.length);
      }

      if (allTabs.length > 1) {
        pushMotionItem(STORY_BODY_DURATION_MS);
      }

      break;
    }

    case 'end': {
      pushMotionItem(STORY_TITLE_DURATION_MS);
      pushMotionItem(STORY_BODY_DURATION_MS);
      pushMotionItem(STORY_CHIPS_DURATION_MS);
      break;
    }
  }

  return finishTimes.length > 0 ? Math.max(...finishTimes) : 0;
};

const StorySkillsChipList = ({
  skills,
  isSectionRevealed,
  sequenceIndex,
}: {
  skills: string[];
  isSectionRevealed: boolean;
  sequenceIndex: number;
}) => {
  const { motionTokens } = useComponentStyles();
  const { duration: durationFactor, stagger: staggerFactor } = useMotionScale();
  const [showChips, setShowChips] = useState(durationFactor === 0 ? isSectionRevealed : false);

  useEffect(() => {
    if (!isSectionRevealed) {
      setShowChips(false);
      return;
    }

    if (durationFactor === 0) {
      setShowChips(true);
      return;
    }

    const timerId = window.setTimeout(
      () => setShowChips(true),
      getStorySequenceStartDelayMs(sequenceIndex, staggerFactor) +
        Math.round(scaleDuration(STORY_CHIPS_DURATION_MS, durationFactor))
    );

    return () => {
      window.clearTimeout(timerId);
    };
  }, [durationFactor, isSectionRevealed, sequenceIndex, staggerFactor]);

  return (
    <MotionItem variants={storyChipsReveal}>
      <Box>
        <SkillsChipList
          skills={skills}
          in={showChips}
          animation="slide"
          startDelayMs={0}
          itemStaggerMs={motionTokens.itemStaggerMs}
        />
      </Box>
    </MotionItem>
  );
};

/* ── Rendering helpers (not exported) ── */
const renderBulletList = (items: ReactNode[], max?: number): ReactNode => {
  const visible = max ? items.slice(0, max) : items;
  return (
    <motion.ul
      variants={storyBulletContainer}
      initial="hidden"
      animate="visible"
      style={{ paddingLeft: 20, margin: 0, listStyleType: '"– "' }}
    >
      {visible.map((item, i) => (
        <motion.li key={i} variants={storyBulletItem}>
          <Text role="body">{item}</Text>
        </motion.li>
      ))}
    </motion.ul>
  );
};

const channelIcon: Record<CVStoryContactChannel['icon'], ReactNode> = {
  email: <EmailOutlinedIcon sx={{ fontSize: 20 }} />,
  github: <GitHubIcon sx={{ fontSize: 20 }} />,
  linkedin: <LinkedInIcon sx={{ fontSize: 20 }} />,
  web: <LanguageIcon sx={{ fontSize: 20 }} />,
};

/* ── Section divider between kind transitions ── */

const StorySectionDivider = ({ isRevealed }: { isRevealed: boolean }) => {
  const { duration: durationFactor } = useMotionScale();

  if (durationFactor === 0) {
    return (
      <Box aria-hidden={!isRevealed} sx={{ opacity: isRevealed ? 1 : 0 }}>
        <Divider
          sx={{
            maxWidth: 120,
            mx: 'auto',
            my: { xs: 2, sm: 3 },
            borderColor: 'divider',
          }}
        />
      </Box>
    );
  }

  return (
    <motion.div
      initial="hidden"
      animate={isRevealed ? 'visible' : 'hidden'}
      variants={storyDividerReveal}
      style={{ opacity: isRevealed ? 1 : 0 }}
      aria-hidden={!isRevealed}
    >
      <Divider
        sx={{
          maxWidth: 120,
          mx: 'auto',
          my: { xs: 2, sm: 3 },
          borderColor: 'divider',
        }}
      />
    </motion.div>
  );
};

/* ── Per-kind section layouts ── */

const AboutSection = ({
  item,
  isRevealed,
}: {
  item: Extract<CVStoryItem, { kind: 'about' }>;
  isRevealed: boolean;
}) => {
  const { data: about } = item;

  return (
    <Stack spacing={3}>
      <Stack spacing={0.5}>
        <MotionItem variants={storyLabelReveal}>
          <Text role="sectionEyebrow" tone="support">
            About
          </Text>
        </MotionItem>
        <MotionItem variants={storyTitleReveal}>
          <Text role="sectionTitle">{about.name}</Text>
        </MotionItem>
        <MotionItem variants={storyMetaReveal}>
          <Text role="metaStrong" sx={{ display: 'inline' }}>
            {about.title}
          </Text>
          <Text role="meta" sx={{ display: 'inline' }}>
            {' '}
            •{' '}
          </Text>
          <Text role="meta" sx={{ display: 'inline' }}>
            {about.location}
          </Text>
        </MotionItem>
      </Stack>
      <MotionItem variants={storyBodyReveal}>
        <Text role="body" sx={{ whiteSpace: 'pre-line', lineHeight: 1.75 }}>
          {about.bio}
        </Text>
      </MotionItem>
      {about.opportunities && about.opportunities.length > 0 && (
        <StorySkillsChipList
          skills={about.opportunities}
          isSectionRevealed={isRevealed}
          sequenceIndex={4}
        />
      )}
      {about.bioLink && (
        <MotionItem variants={storyLinkReveal}>
          <CommonLink href={about.bioLink.url} target="_blank" rel="noopener noreferrer">
            {about.bioLink.text}
          </CommonLink>
        </MotionItem>
      )}
    </Stack>
  );
};

const ExperienceSection = ({
  item,
  isRevealed,
}: {
  item: Extract<CVStoryItem, { kind: 'experience' }>;
  isRevealed: boolean;
}) => {
  const { data: exp } = item;
  let nextSequenceIndex = 3;
  const descriptionSequenceIndex = exp.description ? nextSequenceIndex++ : null;
  const projectsSequenceIndex =
    exp.projects && exp.projects.length > 0 ? nextSequenceIndex++ : null;
  const skillsSequenceIndex = exp.skills && exp.skills.length > 0 ? nextSequenceIndex++ : null;

  return (
    <Stack spacing={2.5}>
      <Stack spacing={0.5}>
        <MotionItem variants={storyLabelReveal}>
          <Text role="sectionEyebrow" tone="support">
            {exp.companyUrl ? (
              <CommonLink
                href={exp.companyUrl}
                target="_blank"
                rel="noopener noreferrer"
                data-tooltip-content={exp.companyTooltip}
              >
                {exp.company}
              </CommonLink>
            ) : (
              exp.company
            )}
          </Text>
        </MotionItem>
        <MotionItem variants={storyTitleReveal}>
          <Text role="sectionTitle">{exp.title}</Text>
        </MotionItem>
      </Stack>
      <MotionItem variants={storyMetaReveal}>
        <Text role="meta">
          {exp.startDate} – {exp.endDate}
          {exp.industry ? ` · ${exp.industry}` : ''}
        </Text>
      </MotionItem>
      {exp.description && descriptionSequenceIndex !== null && (
        <MotionItem variants={storyBodyReveal}>
          <Text role="body">{renderExperienceDescriptionContent(exp.description)}</Text>
        </MotionItem>
      )}
      {exp.projects && exp.projects.length > 0 && projectsSequenceIndex !== null && (
        <MotionItem variants={storyBodyReveal}>
          {renderBulletList(exp.projects.map(renderExperienceProjectContent))}
        </MotionItem>
      )}
      {exp.skills && exp.skills.length > 0 && skillsSequenceIndex !== null && (
        <StorySkillsChipList
          skills={exp.skills}
          isSectionRevealed={isRevealed}
          sequenceIndex={skillsSequenceIndex}
        />
      )}
    </Stack>
  );
};

const EducationSection = ({
  item,
  isRevealed,
}: {
  item: Extract<CVStoryItem, { kind: 'education' }>;
  isRevealed: boolean;
}) => {
  const { data: entry } = item;
  let nextSequenceIndex = 3;
  const gpaSequenceIndex = entry.gpa && entry.gpa.length > 0 ? nextSequenceIndex++ : null;
  const summarySequenceIndex = nextSequenceIndex++;
  const highlightsSequenceIndex =
    entry.highlights && entry.highlights.length > 0 ? nextSequenceIndex++ : null;
  const skillsSequenceIndex = entry.skills && entry.skills.length > 0 ? nextSequenceIndex++ : null;

  return (
    <Stack spacing={2.5}>
      <Stack spacing={0.5}>
        <MotionItem variants={storyLabelReveal}>
          <Text role="sectionEyebrow" tone="support">
            {entry.university}
          </Text>
        </MotionItem>
        <MotionItem variants={storyTitleReveal}>
          <Text role="sectionTitle">{entry.program}</Text>
        </MotionItem>
      </Stack>
      <Stack spacing={0.5}>
        <MotionItem variants={storyMetaReveal}>
          <Text role="meta">{entry.dateRange ?? entry.expectedCompletion ?? ''}</Text>
        </MotionItem>
        {entry.gpa && entry.gpa.length > 0 && gpaSequenceIndex !== null && (
          <MotionItem variants={storyMetaReveal}>
            <Text role="meta">{entry.gpa.map((g) => `${g.label}: ${g.value}`).join('  ·  ')}</Text>
          </MotionItem>
        )}
      </Stack>
      {summarySequenceIndex >= 0 && (
        <MotionItem variants={storyBodyReveal}>
          <Text role="body">{entry.summary}</Text>
        </MotionItem>
      )}
      {entry.highlights && entry.highlights.length > 0 && highlightsSequenceIndex !== null && (
        <MotionItem variants={storyBodyReveal}>{renderBulletList(entry.highlights)}</MotionItem>
      )}
      {entry.skills && entry.skills.length > 0 && skillsSequenceIndex !== null && (
        <StorySkillsChipList
          skills={entry.skills}
          isSectionRevealed={isRevealed}
          sequenceIndex={skillsSequenceIndex}
        />
      )}
    </Stack>
  );
};

const CertificateSection = ({ item }: { item: Extract<CVStoryItem, { kind: 'certificate' }> }) => {
  const { data: cert } = item;
  return (
    <Stack spacing={2} sx={{ alignItems: 'center', textAlign: 'center' }}>
      <MotionItem variants={storyLabelReveal}>
        <Text role="sectionEyebrow" tone="support">
          {cert.issuer}
        </Text>
      </MotionItem>
      <MotionItem variants={storyTitleReveal}>
        <Text role="sectionTitle">{cert.title}</Text>
      </MotionItem>
      <MotionItem variants={storyMetaReveal}>
        <Text role="meta">{cert.date}</Text>
      </MotionItem>
      {cert.link && (
        <MotionItem variants={storyLinkReveal}>
          <CommonLink href={cert.link} target="_blank" rel="noopener noreferrer">
            View certificate
          </CommonLink>
        </MotionItem>
      )}
    </Stack>
  );
};

const VolunteeringSection = ({
  item,
}: {
  item: Extract<CVStoryItem, { kind: 'volunteering' }>;
}) => {
  const { data: entry } = item;
  return (
    <Stack spacing={2.5}>
      <Stack spacing={0.5}>
        <MotionItem variants={storyLabelReveal}>
          <Text role="sectionEyebrow" tone="support">
            {entry.organizationUrl ? (
              <CommonLink href={entry.organizationUrl} target="_blank" rel="noopener noreferrer">
                {entry.organization}
              </CommonLink>
            ) : (
              entry.organization
            )}
          </Text>
        </MotionItem>
        <MotionItem variants={storyTitleReveal}>
          <Text role="sectionTitle">{entry.role}</Text>
        </MotionItem>
      </Stack>
      <MotionItem variants={storyMetaReveal}>
        <Text role="meta">
          {entry.dateRange}
          {entry.location ? ` · ${entry.location}` : ''}
        </Text>
      </MotionItem>
      <MotionItem variants={storyBodyReveal}>
        <Text role="body">{entry.summary}</Text>
      </MotionItem>
      {entry.highlights && entry.highlights.length > 0 && (
        <MotionItem variants={storyBodyReveal}>{renderBulletList(entry.highlights)}</MotionItem>
      )}
    </Stack>
  );
};

const CodingSection = ({
  item,
  isRevealed,
}: {
  item: Extract<CVStoryItem, { kind: 'coding' }>;
  isRevealed: boolean;
}) => {
  const { data: example } = item;
  const [activeTab, setActiveTab] = useState(0);

  const primaryLink = example.links?.[0];
  let isGitHub = false;
  if (primaryLink) {
    try {
      const host = new URL(primaryLink).hostname;
      isGitHub = host === 'github.com' || host.endsWith('.github.com');
    } catch {
      // invalid URL — not GitHub
    }
  }

  const skillsTabs = (example.tabs ?? []).filter(
    (t): t is Extract<typeof t, { kind: 'skills' }> => t.kind === 'skills'
  );
  const allTabs = example.tabs ?? [];
  let nextSequenceIndex = 3;
  const primaryLinkSequenceIndex = primaryLink ? nextSequenceIndex++ : null;
  const singleSkillsSequenceIndex =
    allTabs.length === 1 && skillsTabs.length === 1 ? nextSequenceIndex++ : null;
  const tabsSequenceIndex = allTabs.length > 1 ? nextSequenceIndex++ : null;

  return (
    <Stack spacing={2.5}>
      <Stack spacing={0.5}>
        <MotionItem variants={storyLabelReveal}>
          <Text role="sectionEyebrow" tone="support">
            Project
          </Text>
        </MotionItem>
        <MotionItem variants={storyTitleReveal}>
          <Text role="sectionTitle">{example.title}</Text>
        </MotionItem>
      </Stack>
      <MotionItem variants={storyBodyReveal}>
        <Text role="body">{example.description}</Text>
      </MotionItem>
      {primaryLink && primaryLinkSequenceIndex !== null && (
        <MotionItem variants={storyLinkReveal}>
          <CommonLink href={primaryLink} target="_blank" rel="noopener noreferrer">
            {isGitHub ? 'View on GitHub' : 'View project'}
          </CommonLink>
        </MotionItem>
      )}
      {allTabs.length === 1 && skillsTabs.length === 1 && singleSkillsSequenceIndex !== null && (
        <StorySkillsChipList
          skills={skillsTabs[0].skills}
          isSectionRevealed={isRevealed}
          sequenceIndex={singleSkillsSequenceIndex}
        />
      )}
      {allTabs.length > 1 && tabsSequenceIndex !== null && (
        <MotionItem variants={storyBodyReveal}>
          <Tabs
            value={activeTab}
            onChange={(_, v) => setActiveTab(v)}
            variant="scrollable"
            scrollButtons="auto"
            sx={{ mb: 1.5 }}
          >
            {allTabs.map((tab) => (
              <Tab key={tab.value} label={tab.label} />
            ))}
          </Tabs>
          {allTabs.map((tab, i) => (
            <Box key={tab.value} sx={{ display: activeTab === i ? 'block' : 'none' }}>
              {tab.kind === 'skills' ? (
                <SkillsChipList skills={tab.skills} animation="slide" />
              ) : (
                renderBulletList(
                  tab.items.map((item) =>
                    Array.isArray(item) ? renderExperienceSegments(item) : item
                  ),
                  3
                )
              )}
            </Box>
          ))}
        </MotionItem>
      )}
    </Stack>
  );
};

const EndSection = ({ item }: { item: Extract<CVStoryItem, { kind: 'end' }> }) => {
  const { data: endData } = item;
  return (
    <Stack spacing={3} sx={{ alignItems: 'center', textAlign: 'center' }}>
      <MotionItem variants={storyTitleReveal}>
        <Text role="sectionTitle">{endData.headline}</Text>
      </MotionItem>
      <MotionItem variants={storyBodyReveal}>
        <Text role="body" sx={{ maxWidth: 520, mx: 'auto', lineHeight: 1.75 }}>
          {endData.body}
        </Text>
      </MotionItem>
      <MotionItem variants={storyChipsReveal}>
        <Stack spacing={1.5} sx={{ alignItems: 'center', mt: 1 }}>
          {endData.channels.map((channel) => (
            <CommonLink
              key={channel.url}
              href={channel.url}
              target={channel.icon === 'email' ? undefined : '_blank'}
              rel={channel.icon === 'email' ? undefined : 'noopener noreferrer'}
              sx={{
                display: 'inline-flex',
                alignItems: 'center',
                gap: 1,
              }}
            >
              {channelIcon[channel.icon]}
              {channel.label}
            </CommonLink>
          ))}
        </Stack>
      </MotionItem>
    </Stack>
  );
};

/* ── Main renderer — scroll-triggered section wrapper ── */

export const CVStorySectionRenderer = ({
  item,
  index,
  isRevealed,
  onSectionSettled,
}: CVStorySectionRendererProps) => {
  const { motionTokens } = useComponentStyles();
  const { duration: durationFactor, stagger: staggerFactor } = useMotionScale();
  const hasReportedSettledRef = useRef(false);
  const onSectionSettledRef = useRef(onSectionSettled);
  const isFirstItem = index === 0;
  const resolvedStoryChipItemStaggerMs = Math.round(
    scaleStagger(motionTokens.itemStaggerMs, staggerFactor)
  );
  const sectionSettleDelayMs = getStorySectionSettleDelayMs(
    item,
    durationFactor,
    staggerFactor,
    resolvedStoryChipItemStaggerMs
  );

  useEffect(() => {
    onSectionSettledRef.current = onSectionSettled;
  }, [onSectionSettled]);

  useEffect(() => {
    if (!isRevealed) {
      hasReportedSettledRef.current = false;
      return;
    }

    if (!onSectionSettledRef.current || hasReportedSettledRef.current) {
      return;
    }

    if (sectionSettleDelayMs <= 0) {
      hasReportedSettledRef.current = true;
      onSectionSettledRef.current?.();
      return;
    }

    const timerId = window.setTimeout(() => {
      hasReportedSettledRef.current = true;
      onSectionSettledRef.current?.();
    }, sectionSettleDelayMs);

    return () => {
      window.clearTimeout(timerId);
    };
  }, [isRevealed, sectionSettleDelayMs]);

  return (
    <>
      {!isFirstItem && <StorySectionDivider isRevealed={isRevealed} />}
      <StaggerChildren
        containerVariants={storyContentContainer}
        initial="hidden"
        animate={isRevealed ? 'visible' : 'hidden'}
        style={{
          maxWidth: 720,
          margin: '0 auto',
          opacity: isRevealed ? 1 : 0,
          pointerEvents: isRevealed ? 'auto' : 'none',
        }}
        aria-hidden={!isRevealed}
      >
        <Box sx={{ px: { xs: 3, sm: 4 }, py: { xs: 3, sm: 4 }, width: '100%' }}>
          {item.kind === 'about' && <AboutSection item={item} isRevealed={isRevealed} />}
          {item.kind === 'experience' && <ExperienceSection item={item} isRevealed={isRevealed} />}
          {item.kind === 'education' && <EducationSection item={item} isRevealed={isRevealed} />}
          {item.kind === 'certificate' && <CertificateSection item={item} />}
          {item.kind === 'volunteering' && <VolunteeringSection item={item} />}
          {item.kind === 'coding' && <CodingSection item={item} isRevealed={isRevealed} />}
          {item.kind === 'end' && <EndSection item={item} />}
        </Box>
      </StaggerChildren>
    </>
  );
};
