const { useEffect, useRef, useMemo, useState, useCallback } = React;
const {
  Box, Container, Typography, Button, Chip, Stack, Card, CardContent,
  AppBar, Toolbar, Link, Snackbar, Alert,
} = MaterialUI;

const CATALOG = window.GEOMETRY_CATALOG;
const PACKAGES = window.SKETCH_PACKAGES || {};
const MANIM = window.MANIM_CATALOG || {};

const NAV = [
  { s: 'home', label: 'Todo' },
  { s: 'rectangle', label: 'Rectangle' },
  { s: 'circle', label: 'Circle' },
  { s: 'segment', label: 'Segment' },
];

function stateHref(s) {
  return s === 'home' ? '?' : `?s=${s}`;
}

function directUrl(methodId) {
  const base = location.href.split('?')[0];
  return `${base}?s=${methodId}`;
}

function parseState(s) {
  const raw = s || 'home';
  if (raw === 'home' || raw === 'all') return { mode: 'home' };
  if (raw === 'rectangle' || raw === 'circle' || raw === 'segment') return { mode: 'lib', lib: raw };
  for (const section of CATALOG.sections) {
    if (section.methods.some((m) => m.id === raw)) return { mode: 'demo', demo: raw };
  }
  return { mode: 'home' };
}

function SketchCanvas({ demoId, perfMode = 'gallery' }) {
  const hostRef = useRef(null);
  const mountRef = useRef(null);
  const pausedRef = useRef(false);
  const hasPackage = Boolean(PACKAGES[demoId]);

  useEffect(() => {
    const host = hostRef.current;
    if (!host || !window.SketchRunner || !hasPackage) return undefined;

    mountRef.current = window.SketchRunner.mount(host, demoId, perfMode);
    const { iframe } = mountRef.current;
    if (!iframe) return undefined;

    const onPause = (paused) => {
      pausedRef.current = paused;
      window.SketchRunner.setPaused(iframe, demoId, paused);
    };

    let io;
    const startObserver = () => {
      if (perfMode !== 'gallery' || io) return;
      io = new IntersectionObserver(([entry]) => {
        onPause(!entry.isIntersecting);
      }, { rootMargin: '80px', threshold: 0.05 });
      io.observe(host);
    };
    iframe.addEventListener('load', startObserver);
    if (perfMode === 'focused') {
      iframe.addEventListener('load', () => onPause(false));
    }

    return () => {
      io?.disconnect();
      mountRef.current?.cleanup();
      mountRef.current = null;
    };
  }, [demoId, perfMode, hasPackage]);

  if (!hasPackage) {
    return (
      <div className="sketch-host sketch-pending">
        <Typography variant="body2" color="text.secondary">
          Sketch p5.js en preparación para esta demo.
        </Typography>
      </div>
    );
  }

  return <div ref={hostRef} className="sketch-host" title="Mueve el ratón sobre el sketch" />;
}

function isVideoResponse(res) {
  const type = (res.headers.get('content-type') || '').toLowerCase();
  return type.includes('video/') || type.includes('application/octet-stream');
}

function ManimPanel({ methodId }) {
  const entry = MANIM[methodId];
  const [available, setAvailable] = useState(null);

  useEffect(() => {
    if (!entry?.file || entry.status !== 'ready') {
      setAvailable(false);
      return undefined;
    }
    const url = `public/manim/${entry.file}`;
    let cancelled = false;
    fetch(url, { method: 'HEAD' })
      .then((r) => {
        if (cancelled) return;
        setAvailable(r.ok && isVideoResponse(r));
      })
      .catch(() => { if (!cancelled) setAvailable(false); });
    return () => { cancelled = true; };
  }, [entry?.file, entry?.status, methodId]);

  const onVideoError = useCallback(() => setAvailable(false), []);

  if (!entry) return null;

  if (!entry.file || entry.status !== 'ready' || available === false) {
    return (
      <div className="manim-panel manim-pending">
        <Typography className="panel-label">
          <iconify-icon icon="mdi:function-variant" width="18" /> Animación matemática (Manim)
        </Typography>
        <p className="manim-pending-text">
          {entry.status === 'pending' || !entry.file
            ? 'Clip Manim en preparación para este método.'
            : 'Render pendiente en disco — ejecuta tools/manim/render_all.ps1 y luego scripts/sync-manim-videos.ps1.'}
          {entry.source && <span className="manim-source"> Fuente: <code>{entry.source}</code></span>}
        </p>
      </div>
    );
  }

  if (available === null) {
    return (
      <div className="manim-panel manim-pending">
        <Typography className="panel-label">
          <iconify-icon icon="mdi:function-variant" width="18" /> Animación matemática (Manim)
        </Typography>
        <p className="manim-pending-text">Comprobando clip…</p>
      </div>
    );
  }

  return (
    <div className="manim-panel">
      <Typography className="panel-label">
        <iconify-icon icon="mdi:function-variant" width="18" /> Animación matemática (Manim)
      </Typography>
      <video
        className="manim-video"
        src={`public/manim/${entry.file}`}
        autoPlay
        loop
        muted
        playsInline
        preload="metadata"
        onError={onVideoError}
      />
    </div>
  );
}

function ViewCodeButton({ demoId, methodName }) {
  const open = useCallback(() => {
    if (window.openSketchCodeModal) {
      window.openSketchCodeModal(demoId, methodName);
    }
  }, [demoId, methodName]);

  if (!PACKAGES[demoId]) return null;

  return (
    <Button
      size="small"
      variant="outlined"
      onClick={open}
      className="link-btn view-code-btn"
      startIcon={<iconify-icon icon="mdi:code-braces" width="18" />}
      sx={{ textTransform: 'none', borderColor: 'rgba(56,189,248,0.35)', color: '#38bdf8' }}
    >
      Ver código completo
    </Button>
  );
}

function CopyLinkButton({ methodId }) {
  const [open, setOpen] = useState(false);
  const copy = useCallback(async () => {
    const url = directUrl(methodId);
    try {
      await navigator.clipboard.writeText(url);
      setOpen(true);
    } catch {
      window.prompt('Copia este enlace:', url);
    }
  }, [methodId]);

  return (
    <>
      <Button
        size="small"
        variant="outlined"
        onClick={copy}
        className="link-btn"
        startIcon={<iconify-icon icon="mdi:content-copy" width="18" />}
        sx={{ textTransform: 'none', borderColor: 'rgba(148,163,184,0.35)', color: '#e8eef7' }}
      >
        Copiar enlace
      </Button>
      <Snackbar open={open} autoHideDuration={2200} onClose={() => setOpen(false)} anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }}>
        <Alert severity="success" variant="filled" sx={{ bgcolor: '#4ade80', color: '#0a0e14' }}>
          Enlace copiado
        </Alert>
      </Snackbar>
    </>
  );
}

function MethodCard({ section, method, highlight }) {
  const perfMode = highlight ? 'focused' : 'gallery';

  return (
    <Card
      id={method.id}
      className={highlight ? 'method-card-highlight' : ''}
      sx={{ bgcolor: 'rgba(14,20,30,0.92)', border: '1px solid rgba(74,222,128,0.2)', borderRadius: 3 }}
    >
      <CardContent className="method-card-inner">
        <Chip
          label={<span className="chip-with-icon"><iconify-icon icon="mdi:shape-outline" width="14" /> {section.title}</span>}
          size="small"
          sx={{ mb: 1, color: '#38bdf8', borderColor: 'rgba(56,189,248,0.3)' }}
          variant="outlined"
        />
        <Typography variant="h6" sx={{ fontFamily: '"Space Grotesk", sans-serif', fontWeight: 700 }}>
          {method.name}
        </Typography>
        <Typography variant="body2" color="text.secondary" sx={{ mb: 2 }}>
          {method.desc}
        </Typography>
        <div className="math-block">{`\\(${method.latex}\\)`}</div>

        <ManimPanel methodId={method.id} />

        <div className="method-sketch-block">
          <Typography className="panel-label">
            <iconify-icon icon="simple-icons:p5dotjs" width="18" /> Sketch p5.js
            <span className="panel-hint">
              <iconify-icon icon="mdi:cursor-move" width="14" /> mueve el ratón
            </span>
          </Typography>
          <SketchCanvas demoId={method.demo} perfMode={perfMode} />
          <Stack direction="row" spacing={1} flexWrap="wrap" className="sketch-panel-actions">
            <ViewCodeButton demoId={method.demo} methodName={method.name} />
          </Stack>
        </div>

        <Stack direction="row" spacing={1.5} flexWrap="wrap" className="method-actions">
          {method.sketch && (
            <Button
              size="small"
              href={method.sketch}
              target="_blank"
              rel="noopener"
              className="link-btn"
              startIcon={<iconify-icon icon="simple-icons:p5dotjs" width="18" />}
              sx={{ textTransform: 'none', color: '#38bdf8' }}
            >
              Abrir en editor p5.js ↗
            </Button>
          )}
          <CopyLinkButton methodId={method.id} />
        </Stack>
      </CardContent>
    </Card>
  );
}

function App() {
  const params = new URLSearchParams(location.search);
  const s = params.get('s');
  const view = useMemo(() => parseState(s), [s]);
  const mainRef = useRef(null);

  useEffect(() => {
    if (!mainRef.current || !window.renderMathInElement) return;
    renderMathInElement(mainRef.current, {
      delimiters: [
        { left: '$$', right: '$$', display: true },
        { left: '\\(', right: '\\)', display: false },
      ],
    });
  });

  useEffect(() => {
    if (view.mode === 'demo') {
      const el = document.getElementById(view.demo);
      if (el) el.scrollIntoView({ behavior: 'smooth', block: 'start' });
    }
  }, [view]);

  const heroSub = view.mode === 'demo'
    ? `Demostración: ${view.demo}`
    : 'Vec2, Rectangle, Circle y Segment — librería JavaScript pura para hitboxes y colisiones 2D. Explora cada método con fórmula, demo interactiva y código listo para copiar.';

  const sections = CATALOG.sections.filter((sec) => {
    if (view.mode === 'lib') return sec.id === view.lib;
    if (view.mode === 'demo') return sec.methods.some((m) => m.id === view.demo);
    return true;
  });

  return (
    <Box sx={{ minHeight: '100vh', bgcolor: '#0a0e14' }}>
      <AppBar position="sticky" elevation={0} sx={{ bgcolor: 'rgba(10,14,20,0.9)', backdropFilter: 'blur(12px)', borderBottom: '1px solid rgba(255,255,255,0.06)' }}>
        <Toolbar className="app-toolbar">
          <Stack direction="row" spacing={1} flexWrap="wrap" className="nav-pills">
            {NAV.map((item) => (
              <Button
                key={item.s}
                href={stateHref(item.s)}
                className={((view.mode === 'home' && item.s === 'home') || (view.mode === 'lib' && view.lib === item.s)) ? 'nav-pill active' : 'nav-pill'}
                sx={{ borderRadius: 999, textTransform: 'none', color: '#94a3b8', border: '1px solid rgba(148,163,184,0.25)' }}
              >
                {item.label}
              </Button>
            ))}
          </Stack>
          <Stack direction="row" spacing={1} className="toolbar-links">
            <Button
              size="small"
              href={CATALOG.meta.repo}
              target="_blank"
              rel="noopener"
              startIcon={<iconify-icon icon="mdi:github" width="18" />}
              sx={{ textTransform: 'none', color: '#e8eef7', border: '1px solid rgba(148,163,184,0.25)', borderRadius: 999 }}
            >
              GitHub
            </Button>
            <Button
              size="small"
              href={CATALOG.meta.youtube}
              target="_blank"
              rel="noopener"
              startIcon={<iconify-icon icon="mdi:youtube" width="18" />}
              sx={{ textTransform: 'none', color: '#f87171', border: '1px solid rgba(248,113,113,0.35)', borderRadius: 999 }}
            >
              Tutorial
            </Button>
            <Button
              size="small"
              href={`${CATALOG.meta.repo}/releases`}
              target="_blank"
              rel="noopener"
              startIcon={<iconify-icon icon="mdi:package-variant" width="18" />}
              sx={{ textTransform: 'none', color: '#38bdf8', border: '1px solid rgba(56,189,248,0.3)', borderRadius: 999 }}
            >
              Releases
            </Button>
          </Stack>
        </Toolbar>
      </AppBar>

      <Box className="geom-hero">
        <Typography component="h1" sx={{ fontFamily: '"Space Grotesk", sans-serif', fontWeight: 700, fontSize: 'clamp(2rem, 5vw, 3.2rem)', mb: 1.5 }}>
          Jeff <span className="hero-accent">Geometry</span>
        </Typography>
        <Typography color="text.secondary" sx={{ maxWidth: 820, mx: 'auto', mb: 2, px: 2 }}>
          {heroSub}
        </Typography>
        <Stack direction="row" spacing={1.5} justifyContent="center" flexWrap="wrap" sx={{ mb: 2, px: 2 }}>
          <Button
            href={CATALOG.meta.youtube}
            target="_blank"
            rel="noopener"
            variant="contained"
            startIcon={<iconify-icon icon="mdi:youtube" width="20" />}
            sx={{ bgcolor: '#ef4444', color: '#fff', textTransform: 'none', '&:hover': { bgcolor: '#dc2626' } }}
          >
            Ver tutorial en YouTube
          </Button>
          <Button
            href={CATALOG.meta.repo}
            target="_blank"
            rel="noopener"
            variant="contained"
            startIcon={<iconify-icon icon="mdi:github" width="20" />}
            sx={{ bgcolor: '#4ade80', color: '#0a0e14', textTransform: 'none', '&:hover': { bgcolor: '#22c55e' } }}
          >
            Repositorio en GitHub
          </Button>
          <Button
            href={CATALOG.meta.flappy}
            target="_blank"
            rel="noopener"
            variant="outlined"
            startIcon={<iconify-icon icon="mdi:gamepad-variant" width="20" />}
            sx={{ borderColor: 'rgba(74,222,128,0.4)', color: '#4ade80', textTransform: 'none' }}
          >
            Flappy Bird (usa esta lib)
          </Button>
        </Stack>
        <Stack spacing={1} className="cdn-box" sx={{ alignItems: 'center' }}>
          <Box component="code" sx={{ fontFamily: 'JetBrains Mono, monospace', fontSize: 15, color: '#94a3b8' }}>
            npm i {CATALOG.meta.npm}
          </Box>
          <Box component="code" sx={{ fontFamily: 'JetBrains Mono, monospace', fontSize: 13, color: '#64748b', wordBreak: 'break-all', textAlign: 'center' }}>
            {CATALOG.meta.cdn}
          </Box>
        </Stack>
      </Box>

      <Container maxWidth={false} className="main-container" ref={mainRef}>
        {sections.length === 0 && (
          <Typography color="text.secondary" textAlign="center" sx={{ py: 8 }}>
            Sin resultados para <code>?s={s}</code>. <Link href="?">Ver todo</Link>
          </Typography>
        )}
        {sections.map((section) => {
          const methods = section.methods.filter((m) => view.mode !== 'demo' || m.id === view.demo);
          return (
            <Box key={section.id} sx={{ mb: 6 }}>
              {view.mode !== 'demo' && (
                <>
                  <Typography variant="h4" sx={{ fontFamily: '"Space Grotesk", sans-serif', color: '#4ade80', mb: 1 }}>
                    {section.title}
                  </Typography>
                  <Typography color="text.secondary" sx={{ mb: 3 }}>{section.intro}</Typography>
                </>
              )}
              <Stack spacing={3}>
                {methods.map((method) => (
                  <MethodCard
                    key={method.id}
                    section={section}
                    method={method}
                    highlight={view.mode === 'demo' && view.demo === method.id}
                  />
                ))}
              </Stack>
            </Box>
          );
        })}
      </Container>

      <footer className="site-foot">
        <Stack spacing={1.5} alignItems="center">
          <Stack direction="row" spacing={2} justifyContent="center" flexWrap="wrap" alignItems="center">
            <a href={CATALOG.meta.repo} target="_blank" rel="noopener">
              <iconify-icon icon="mdi:github" width="16" /> GitHub
            </a>
            <span>·</span>
            <a href={CATALOG.meta.youtube} target="_blank" rel="noopener">
              <iconify-icon icon="mdi:youtube" width="16" /> Tutorial
            </a>
            <span>·</span>
            <a href={CATALOG.meta.flappy} target="_blank" rel="noopener">Flappy Bird</a>
            <span>·</span>
            <a href={CATALOG.meta.channel} target="_blank" rel="noopener">Canal YouTube</a>
          </Stack>
          <Stack direction="row" spacing={2} justifyContent="center" flexWrap="wrap" alignItems="center" sx={{ opacity: 0.85 }}>
            <a href={CATALOG.meta.whatsapp} target="_blank" rel="noopener">
              <iconify-icon icon="mdi:whatsapp" width="16" /> WhatsApp
            </a>
            <span>·</span>
            <a href={CATALOG.meta.telegram} target="_blank" rel="noopener">
              <iconify-icon icon="mdi:telegram" width="16" /> Telegram
            </a>
            <span>·</span>
            <span>Jeff Aporta Programación</span>
          </Stack>
        </Stack>
      </footer>
    </Box>
  );
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <MaterialUI.ThemeProvider theme={MaterialUI.createTheme({
    palette: {
      mode: 'dark',
      primary: { main: '#4ade80' },
      background: { default: '#0a0e14', paper: '#0e141e' },
    },
    typography: { fontFamily: 'Inter, system-ui, sans-serif' },
  })}>
    <App />
  </MaterialUI.ThemeProvider>
);
