// Shared portfolio components (used by all 3 directions)
// Exports to window.PFC

const { useState, useEffect, useRef, useCallback } = React;

/* ── ProjectMock ───────────────────────────────────────────────
   Placeholder visual for a project — colored background with
   project name + a tiny stylized "screenshot" element.
*/
function ProjectMock({ project, variant = "card", size = "md" }) {
  const { hue = "#0052FF", accent = "#FFFFFF", name, idx, slug, tags = [] } = project;
  const isMobile = (tags.includes("Mobile App") || tags.includes("Mobile")) && !tags.includes("Web");
  const isWeb = tags.includes("Web") || tags.includes("Enterprise") || tags.includes("Tooling");
  const isAI = tags.includes("AI");

  // Decide which mini mockup to draw inside the colored swatch
  const renderInner = () => {
    if (variant === "logo") {
      return (
        <div style={{
          fontFamily: "var(--font-title)", fontWeight: 800,
          fontSize: size === "lg" ? 80 : 48,
          letterSpacing: "-0.04em", color: accent
        }}>
          {name}
        </div>
      );
    }
    if (isMobile) return <MiniPhone hue={hue} accent={accent} project={project} />;
    if (isAI) return <MiniAI hue={hue} accent={accent} project={project} />;
    if (isWeb) return <MiniWeb hue={hue} accent={accent} project={project} />;
    return <MiniWeb hue={hue} accent={accent} project={project} />;
  };

  return (
    <div className={`pfm pfm--${size}`} style={{
      background: hue,
      width: "100%",
      height: "100%",
      position: "relative",
      overflow: "hidden",
      color: accent,
    }}>
      {/* tag chip top-left */}
      <div style={{
        position: "absolute", top: 14, left: 14,
        fontFamily: "var(--pf-mono)", fontSize: 10,
        textTransform: "uppercase", letterSpacing: "0.12em",
        color: accent, opacity: 0.78,
        display: "flex", gap: 6, alignItems: "center",
      }}>
        <span style={{ display: "inline-block", width: 4, height: 4, background: accent, borderRadius: 999 }}></span>
        {idx} / {tags[0] || "Product"}
      </div>
      {/* name top-right */}
      <div style={{
        position: "absolute", top: 14, right: 14,
        fontFamily: "var(--font-title)", fontWeight: 700, fontSize: 13,
        letterSpacing: "-0.01em",
        color: accent, opacity: 0.92,
      }}>{name}</div>

      {/* center visual */}
      <div style={{
        position: "absolute", inset: 0,
        display: "grid", placeItems: "center"
      }}>
        {renderInner()}
      </div>

      {/* bottom right year */}
      <div style={{
        position: "absolute", bottom: 14, right: 14,
        fontFamily: "var(--pf-mono)", fontSize: 11,
        color: accent, opacity: 0.72,
        letterSpacing: "0.04em",
      }}>{project.year_short}</div>
    </div>
  );
}

function MiniPhone({ hue, accent, project }) {
  return (
    <div style={{
      width: 96, height: 180,
      background: accent,
      borderRadius: 14,
      position: "relative",
      boxShadow: `0 12px 32px rgba(0,0,0,0.18), 0 0 0 2px ${accent}`,
      overflow: "hidden",
    }}>
      {/* status notch */}
      <div style={{ position: "absolute", top: 6, left: "50%", transform: "translateX(-50%)", width: 32, height: 5, borderRadius: 9999, background: hue, opacity: 0.4 }}></div>
      {/* faux content */}
      <div style={{ position: "absolute", top: 18, left: 8, right: 8, display: "flex", flexDirection: "column", gap: 6 }}>
        <div style={{ height: 12, background: hue, opacity: 0.18, borderRadius: 3 }}></div>
        <div style={{ height: 28, background: hue, opacity: 0.85, borderRadius: 6, display: "grid", placeItems: "center", fontFamily: "var(--font-title)", fontSize: 11, fontWeight: 700, color: accent, letterSpacing: "-0.02em" }}>{project.name}</div>
        <div style={{ height: 8, background: hue, opacity: 0.12, borderRadius: 3 }}></div>
        <div style={{ height: 8, background: hue, opacity: 0.12, borderRadius: 3, width: "70%" }}></div>
        <div style={{ marginTop: 4, display: "flex", gap: 3 }}>
          <div style={{ flex: 1, height: 20, background: hue, opacity: 0.16, borderRadius: 4 }}></div>
          <div style={{ flex: 1, height: 20, background: hue, opacity: 0.30, borderRadius: 4 }}></div>
        </div>
        <div style={{ height: 36, background: hue, opacity: 0.10, borderRadius: 4 }}></div>
        <div style={{ height: 6, background: hue, opacity: 0.12, borderRadius: 3 }}></div>
        <div style={{ height: 6, background: hue, opacity: 0.12, borderRadius: 3, width: "60%" }}></div>
      </div>
      {/* home indicator */}
      <div style={{ position: "absolute", bottom: 4, left: "50%", transform: "translateX(-50%)", width: 32, height: 3, borderRadius: 9999, background: hue, opacity: 0.3 }}></div>
    </div>
  );
}

function MiniWeb({ hue, accent, project }) {
  return (
    <div style={{
      width: 220, height: 140,
      background: accent,
      borderRadius: 8,
      position: "relative",
      overflow: "hidden",
      boxShadow: `0 12px 32px rgba(0,0,0,0.18)`,
    }}>
      {/* topbar */}
      <div style={{ height: 14, background: hue, opacity: 0.10, display: "flex", alignItems: "center", padding: "0 6px", gap: 3 }}>
        <span style={{ width: 5, height: 5, borderRadius: 9999, background: hue, opacity: 0.5 }}></span>
        <span style={{ width: 5, height: 5, borderRadius: 9999, background: hue, opacity: 0.3 }}></span>
        <span style={{ width: 5, height: 5, borderRadius: 9999, background: hue, opacity: 0.3 }}></span>
      </div>
      <div style={{ padding: "10px 12px", display: "flex", flexDirection: "column", gap: 5 }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
          <div style={{ fontFamily: "var(--font-title)", fontWeight: 800, fontSize: 11, color: hue, letterSpacing: "-0.02em" }}>{project.name}</div>
          <div style={{ display: "flex", gap: 4 }}>
            <span style={{ width: 14, height: 5, background: hue, opacity: 0.12, borderRadius: 2 }}></span>
            <span style={{ width: 14, height: 5, background: hue, opacity: 0.12, borderRadius: 2 }}></span>
            <span style={{ width: 14, height: 5, background: hue, opacity: 0.5, borderRadius: 2 }}></span>
          </div>
        </div>
        <div style={{ height: 16, background: hue, opacity: 0.85, borderRadius: 3, width: "75%", marginTop: 4 }}></div>
        <div style={{ height: 5, background: hue, opacity: 0.15, borderRadius: 2 }}></div>
        <div style={{ height: 5, background: hue, opacity: 0.15, borderRadius: 2, width: "85%" }}></div>
        <div style={{ height: 5, background: hue, opacity: 0.15, borderRadius: 2, width: "60%" }}></div>
        <div style={{ display: "flex", gap: 5, marginTop: 6 }}>
          <div style={{ flex: 1, height: 30, background: hue, opacity: 0.10, borderRadius: 3 }}></div>
          <div style={{ flex: 1, height: 30, background: hue, opacity: 0.10, borderRadius: 3 }}></div>
          <div style={{ flex: 1, height: 30, background: hue, opacity: 0.10, borderRadius: 3 }}></div>
        </div>
      </div>
    </div>
  );
}

function MiniAI({ hue, accent, project }) {
  return (
    <div style={{
      width: 220, height: 140,
      background: accent,
      borderRadius: 8,
      position: "relative",
      overflow: "hidden",
      boxShadow: `0 12px 32px rgba(0,0,0,0.18)`,
      padding: 12,
      display: "flex", flexDirection: "column", gap: 7,
    }}>
      <div style={{ display: "flex", alignItems: "center", gap: 6 }}>
        <span style={{ width: 16, height: 16, borderRadius: 6, background: hue, display: "grid", placeItems: "center", color: accent, fontFamily: "var(--font-title)", fontWeight: 800, fontSize: 9 }}>AI</span>
        <div style={{ fontFamily: "var(--font-title)", fontWeight: 700, fontSize: 11, color: hue, letterSpacing: "-0.02em" }}>{project.name}</div>
      </div>
      {/* chat bubbles */}
      <div style={{ alignSelf: "flex-start", maxWidth: "82%", background: hue, opacity: 0.10, borderRadius: 8, padding: "5px 8px", height: 18 }}></div>
      <div style={{ alignSelf: "flex-end", maxWidth: "70%", background: hue, opacity: 0.85, borderRadius: 8, padding: "5px 8px", height: 18, width: "60%" }}></div>
      <div style={{ alignSelf: "flex-start", maxWidth: "90%", background: hue, opacity: 0.10, borderRadius: 8, padding: "5px 8px", height: 32 }}></div>
      <div style={{ display: "flex", gap: 4, alignItems: "center", marginTop: "auto" }}>
        <div style={{ width: 4, height: 4, borderRadius: 9999, background: hue, opacity: 0.5, animation: "pf-bounce 1.4s ease-in-out infinite" }}></div>
        <div style={{ width: 4, height: 4, borderRadius: 9999, background: hue, opacity: 0.5 }}></div>
        <div style={{ width: 4, height: 4, borderRadius: 9999, background: hue, opacity: 0.5 }}></div>
      </div>
    </div>
  );
}

/* ── HoverPreview ──────────────────────────────────────────────
   Floating image preview that follows the cursor when hovering
   over a project list row.
*/
const DWELL_MS = 3000; // pointer must rest this long before the preview shows

function useHoverPreview(opts = {}) {
  const { rich = false, t = (v) => v } = opts;
  const [active, setActive] = useState(null);
  const [pos, setPos] = useState({ x: 0, y: 0 });
  const rowRef = useRef(null);
  const timerRef = useRef(0);
  const pendingRef = useRef(null);
  const activeRef = useRef(false);
  const lastRef = useRef({ x: 0, y: 0 });

  // Sit right next to the cursor (small offset), but never over the row's
  // title: if the cursor is on/near the title, the card is nudged just past
  // the title's right edge. Flips to the left of the cursor when out of room.
  const place = useCallback((clientX, clientY) => {
    const w = rich ? 360 : 340;
    const h = rich ? 430 : 255;
    const gap = 20;
    const vw = window.innerWidth, vh = window.innerHeight;
    const row = rowRef.current;
    const title = row && row.querySelector("h3");
    const tr = title ? title.getBoundingClientRect() : null;
    const overTitle = tr && clientY >= tr.top - 8 && clientY <= tr.bottom + 8;

    let x = clientX + gap;
    // only push past the title when the card would actually overlap the words
    if (overTitle && x < tr.right + gap) x = tr.right + gap;
    if (x + w > vw - 16) {
      const flipped = clientX - gap - w;
      x = flipped >= 16 && (!overTitle || flipped + w < tr.left - gap)
        ? flipped
        : Math.max(16, vw - w - 16);
    }

    let y = clientY - h / 2;
    y = Math.min(Math.max(16, y), Math.max(16, vh - h - 16));
    setPos({ x, y });
  }, [rich]);

  const onMove = useCallback((e) => {
    // remember where the cursor is, but only reveal once it has settled
    lastRef.current = { x: e.clientX, y: e.clientY };
    if (activeRef.current) { place(e.clientX, e.clientY); return; }
    arm(e.currentTarget);
  }, [place]);

  // Reveal only after the pointer rests on the row; any movement,
  // scroll or leave re-arms/cancels it so scrolling never pops the card.
  const arm = useCallback((row) => {
    clearTimeout(timerRef.current);
    timerRef.current = setTimeout(() => {
      const p = pendingRef.current;
      if (!p || !rowRef.current) return;
      setActive(p);
      activeRef.current = true;
      place(lastRef.current.x, lastRef.current.y);
    }, DWELL_MS);
  }, [place]);

  const cancel = useCallback(() => {
    clearTimeout(timerRef.current);
    pendingRef.current = null;
    rowRef.current = null;
    activeRef.current = false;
    setActive(null);
  }, []);

  useEffect(() => {
    const onScroll = () => cancel();
    window.addEventListener("scroll", onScroll, { passive: true });
    window.addEventListener("wheel", onScroll, { passive: true });
    return () => {
      window.removeEventListener("scroll", onScroll);
      window.removeEventListener("wheel", onScroll);
      clearTimeout(timerRef.current);
    };
  }, [cancel]);

  const bind = (project) => ({
    onMouseEnter: (e) => {
      rowRef.current = e.currentTarget;
      pendingRef.current = project;
      lastRef.current = { x: e.clientX, y: e.clientY };
      arm(e.currentTarget);
    },
    onMouseLeave: cancel,
    onMouseMove: onMove,
  });

  const Preview = active ? (
    rich ? (
      <div className="pf-preview pf-preview--rich visible" style={{ left: pos.x, top: pos.y, transform: "none" }}>
        <div style={{ width: "100%", aspectRatio: "4/3", overflow: "hidden", borderRadius: "12px 12px 0 0" }}>
          <ProjectMock project={active} variant="card" size="md" />
        </div>
        <div style={{ padding: "14px 16px 16px", background: "var(--pf-bg)" }}>
          <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline" }}>
            <div style={{ fontFamily: "var(--font-title)", fontSize: 22, fontWeight: 700, letterSpacing: "-0.02em" }}>{active.name}</div>
            <div className="pf-mono" style={{ fontSize: 10, color: "var(--pf-text-2)" }}>{active.idx} / {active.year_short}</div>
          </div>
          <div style={{ fontSize: 12, color: "var(--pf-text-2)", marginTop: 6, lineHeight: 1.45 }}>{t(active.summary)}</div>
          <div style={{ marginTop: 10, display: "flex", justifyContent: "space-between", alignItems: "center" }}>
            <div style={{ display: "flex", gap: 4, flexWrap: "wrap" }}>
              {active.tags.slice(0,2).map(tag => (
                <span key={tag} className="pf-mono" style={{ fontSize: 9, padding: "2px 6px", border: "1px solid var(--pf-line)", borderRadius: 9999, letterSpacing: "0.08em", textTransform: "uppercase", color: "var(--pf-text-2)" }}>{tag}</span>
              ))}
            </div>
            <span className="pf-mono" style={{ fontSize: 10, color: "var(--pf-accent)", letterSpacing: "0.08em", textTransform: "uppercase" }}>Read case <i className="ph ph-arrow-up-right"></i></span>
          </div>
        </div>
      </div>
    ) : (
      <div className="pf-preview visible" style={{ left: pos.x, top: pos.y, transform: "none" }}>
        <ProjectMock project={active} variant="card" size="md" />
      </div>
    )
  ) : null;

  return { bind, Preview };
}

/* ── BrandMark ─ small "HV" mark ─────────────────────────────── */
function BrandMark({ size = 28 }) {
  return (
    <div style={{
      width: size, height: size,
      borderRadius: Math.round(size * 0.28),
      background: "var(--pf-text)",
      color: "var(--pf-bg)",
      display: "grid", placeItems: "center",
      fontFamily: "var(--font-title)", fontWeight: 800,
      fontSize: Math.round(size * 0.5),
      letterSpacing: "-0.04em",
    }}>HV</div>
  );
}

/* ── LangSwitch ─ VI/EN inline toggle ────────────────────────── */
function LangSwitch({ lang, setLang }) {
  return (
    <div style={{
      display: "inline-flex", alignItems: "center",
      border: "1px solid var(--pf-line)", borderRadius: 9999,
      fontFamily: "var(--pf-mono)", fontSize: 11, fontWeight: 500,
      letterSpacing: "0.04em",
      overflow: "hidden",
    }}>
      {["vi","en"].map(l => (
        <button key={l} onClick={() => setLang(l)} style={{
          padding: "5px 10px",
          background: lang === l ? "var(--pf-text)" : "transparent",
          color: lang === l ? "var(--pf-bg)" : "var(--pf-text-2)",
          border: 0, cursor: "pointer", fontFamily: "inherit",
          textTransform: "uppercase",
        }}>{l}</button>
      ))}
    </div>
  );
}

/* ── ThemeSwitch ─ light/dark toggle ─────────────────────────── */
function ThemeSwitch({ theme, setTheme }) {
  return (
    <button
      onClick={() => setTheme(theme === "dark" ? "light" : "dark")}
      className="pf-iconbtn"
      aria-label="Toggle theme"
    >
      <i className={`ph ${theme === "dark" ? "ph-sun" : "ph-moon"}`}></i>
    </button>
  );
}

/* ── Local theme/lang state hook for one direction artboard ── */
function usePortfolioState() {
  const [lang, setLang] = useState("vi");
  const [theme, setTheme] = useState("light");
  return { lang, setLang, theme, setTheme };
}

window.PFC = {
  ProjectMock, BrandMark, LangSwitch, ThemeSwitch,
  useHoverPreview, usePortfolioState,
};
