// cache-bust: 1779480397114-signinbtn
// =========================================================
// ep1-guided.jsx -- GENERIC interactive guided session for any episode.
// (Filename retained for index.html compatibility.)
//
// - Reads window.BL_EP_ID (set by ep-route.jsx before mount)
// - Looks up beats in EP_RICH[id] (rich format with pinned prompts) OR
//   falls back to window.BL_SCRIPTS[id].beats (simple time/text from
//   scripts-data.js).
// - Ep 1.0's rich BEATS live in EP_RICH below. Other episodes render
//   with time + narration only until upgraded.
// =========================================================

const { useState, useRef, useEffect } = React;

const T = {
  paper:"#f5f1ea",paper2:"#ebe5da",paper3:"#ddd5c6",
  ink:"#1a1612",ink2:"#3a322a",inkDim:"#5b5247",inkMute:"#8a8073",
  line:"#d9d1c5",dark:"#16110d",dark2:"#1f1812",dark3:"#29211a",
  lineDark:"#2e261f",bone:"#f4eee3",boneDim:"#c9c0b1",
  accent:"#d96846",accentDeep:"#b8451f",accentSoft:"#f3c3ab",accentTint:"#fae5d8",
  sage:"#6b9a5f",amber:"#e3a44e",
  serif:"'Georgia', ui-serif, serif",
  mono:"'Menlo', 'Courier New', monospace",
  sans:"system-ui, -apple-system, sans-serif",
};

// --------------------------------------------------------------------
// RICH BEAT OVERRIDES -- richer than scripts-data.js (adds label, action,
// pinned prompts). Only Ep 1.0 has this today; add more here as you polish.
// --------------------------------------------------------------------
const EP_RICH = {
  "1.0": [
    { id:0, time:"0:00 - 0:08", label:"Hook",
      narration:"Most people open VS Code first. Bad move -- you don't know what you're building yet. I designed reloadin5.com before I wrote a single line of code. In Claude. Here's how -- and why it changes the whole project.",
      action:null, pinned:null },
    { id:1, time:"0:08 - 1:00", label:"Open Claude Design",
      narration:"Open Claude Design and start a fresh project. Attach two screenshots: your live site and a Stripe pricing page you like. Then paste the prompt below directly into Claude.",
      action:"Open Claude Design -> New Project -> attach 2 screenshots",
      pinned:{ label:"Paste this into Claude:",
        code:`Design a premium content-locked landing page for reloadin5.com/build --
a video curriculum site that teaches engineers how I built reloadin5 with you.

Tone: engineer-built, not marketing. Terminal aesthetic with
warm coral accents. Premium SaaS, never "agency."

Use the design_canvas component. Lay out:
  - desktop landing (1440 wide)
  - mobile landing (390 wide)
  - members-area dashboard (1440x900)

Expose tweaks for: accent color, density, lock-state aggressiveness.
No filler content. No emoji. No fake testimonials.` } },
    { id:2, time:"1:00 - 2:30", label:"Watch it scaffold",
      narration:"Claude generates a full landing page -- hero, story, module list, architecture diagram, pricing -- all on one design canvas. You haven't written a single component yet. Drag the artboards around. Open one fullscreen. This is your blueprint, not your final product.",
      action:"Let Claude finish. Drag artboards. Open desktop view fullscreen.",
      pinned:null },
    { id:3, time:"2:30 - 4:00", label:"Iterate with Tweaks",
      narration:"See the Tweaks panel in the corner? This is where you make design decisions without re-prompting. Switch the accent, tighten the density, flip the lock-state. No re-prompting needed.",
      action:"Use the Tweaks panel -- try accent colors, density settings, lock-state modes.",
      pinned:{ label:"Try each Tweak in order:",
        code:`1. Accent color -> amber -> sage -> back to coral
2. Density -> compact -> comfortable -> spacious
3. Lock-state -> subtle -> soft-blur -> tiered
4. Motion -> on / off` } },
    { id:4, time:"4:00 - 5:30", label:"Add artboard variants",
      narration:"Ask Claude to add more artboards directly on the canvas -- mobile and TikTok short dimensions. These are real surfaces this site will live on.",
      action:"Paste this next prompt into Claude:",
      pinned:{ label:"Paste this into Claude:",
        code:`Add two more artboards to the canvas:
- Mobile landing at 390px wide
- TikTok short at 400 x 711px (portrait)

Keep the same design system. Show them side-by-side with the desktop.` } },
    { id:5, time:"5:30 - 6:45", label:"Comment and patch",
      narration:"Pick one thing that looks off. Type a comment about that specific element. Claude fixes only that, leaving everything else alone -- same discipline you'll use in real code.",
      action:"Comment on one specific element in the preview.",
      pinned:{ label:"Example -- paste this into Claude:",
        code:`The hero H1 is too tight against the paragraph below it.
Add 12px more breathing room between them.
Only this change. Do not touch other spacing.` } },
    { id:6, time:"6:45 - 8:00", label:"Export the blueprint",
      narration:"Once the design is locked, export the HTML. This becomes your blueprint for the real Vite build. You're translating from a working prototype -- not starting from scratch.",
      action:"Export or copy the HTML output from Claude.",
      pinned:{ label:"Paste this into Claude:",
        code:`Export the final design as a single self-contained HTML file.
Include all CSS inline. No external dependencies.` } },
    { id:7, time:"8:00 - 8:24", label:"What's next",
      narration:"You just designed your entire product before writing a single line of production code. Episode 1.1 covers the patch-script workflow -- the loop that gets this design into a real Vite + Cloudflare app.",
      action:null, pinned:null },
  ],
};

// --------------------------------------------------------------------
// Build BEATS array for a given episode id. Prefers EP_RICH, then falls
// back to window.BL_SCRIPTS[id].beats (simple time/text).
// --------------------------------------------------------------------
function buildBeats(id) {
  if (EP_RICH[id]) return EP_RICH[id];
  const scripts = window.BL_SCRIPTS || {};
  const ep = scripts[id];
  if (!ep || !Array.isArray(ep.beats) || ep.beats.length === 0) {
    return [{
      id: 0, time: "--", label: "Coming soon",
      narration: "This episode's beat sheet hasn't been written yet. Ask Claude on the right for help with anything from this module.",
      action: null, pinned: null,
    }];
  }
  return ep.beats.map((b, i) => ({
    id: i,
    time: b.time || "--",
    label: b.label || `Step ${i + 1}`,
    narration: b.text || b.narration || "",
    action: b.action || null,
    pinned: b.pinned || null,
  }));
}

// --------------------------------------------------------------------
// Look up episode title + free/pro flag from window.BL_DATA (data.js).
// --------------------------------------------------------------------
function epMeta(id) {
  const data = window.BL_DATA;
  const scripts = window.BL_SCRIPTS || {};
  const fallback = { title: `Episode ${id}`, free: false };
  if (!data || !Array.isArray(data.modules)) return fallback;
  for (const m of data.modules) {
    for (const e of (m.episodes || [])) {
      if (e.n === id) {
        return {
          title: e.title || scripts[id]?.title || fallback.title,
          free: !!e.free,
        };
      }
    }
  }
  return { ...fallback, title: scripts[id]?.title || fallback.title };
}

function CopyButton({ text }) {
  const [copied, setCopied] = useState(false);
  function handleCopy() {
    navigator.clipboard.writeText(text).then(() => {
      setCopied(true);
      setTimeout(() => setCopied(false), 2000);
    });
  }
  return (
    <button onClick={handleCopy} style={{
      background: copied ? T.sage : T.accent,
      border:"none", borderRadius:6, padding:"6px 14px",
      color:"#fff", fontSize:11, fontFamily:T.mono,
      cursor:"pointer", letterSpacing:".06em",
      transition:"background .2s", flexShrink:0,
    }}>
      {copied ? "COPIED" : "COPY PROMPT"}
    </button>
  );
}

function ChatMessage({ msg }) {
  const isUser = msg.role === "user";
  return (
    <div style={{ display:"flex", justifyContent: isUser ? "flex-end" : "flex-start", marginBottom:12 }}>
      <div style={{
        maxWidth:"82%", padding:"10px 14px",
        borderRadius: isUser ? "14px 14px 4px 14px" : "14px 14px 14px 4px",
        background: isUser ? T.accent : T.dark3,
        color: isUser ? "#fff" : T.bone,
        fontSize:13.5, lineHeight:1.55, fontFamily:T.sans,
        border: isUser ? "none" : `1px solid ${T.lineDark}`,
      }}>
        {msg.content}
      </div>
    </div>
  );
}

function EpisodeGuide() {
  // Subscribe to auth state so the top bar updates on sign-in/out.
  const auth = window.useBLAuth();
  // Episode id is set by the router right before mount.
  const ID = (typeof window !== "undefined" && window.BL_EP_ID) ? window.BL_EP_ID : "1.0";
  const META = epMeta(ID);
  const BEATS = buildBeats(ID);

  const [beat, setBeat] = useState(0);
  const [showHint, setShowHint] = useState(true);
  const [messages, setMessages] = useState([{
    role:"assistant",
    content: `You are now on \"${META.title}\". Ask me anything about this step -- including how to run commands on Mac or Windows.`,
  }]);
  const [input, setInput] = useState("");
  const [loading, setLoading] = useState(false);
  const chatEndRef = useRef(null);
  const current = BEATS[beat];
  const progress = (beat / Math.max(1, BEATS.length - 1)) * 100;

  useEffect(() => { chatEndRef.current?.scrollIntoView({ behavior:"smooth" }); }, [messages]);

  const [remaining, setRemaining] = useState(null);

  async function sendMessage() {
    if (!input.trim() || loading) return;
    const userMsg = { role:"user", content:input.trim() };
    setMessages(prev => [...prev, userMsg]);
    setInput("");
    setLoading(true);
    try {
      const token = (window.BL_AUTH && window.BL_AUTH.getToken && window.BL_AUTH.getToken()) || localStorage.getItem("bl_token");
      const res = await fetch("/api/build/ask", {
        method:"POST",
        headers:{
          "Content-Type":"application/json",
          ...(token ? { "Authorization": `Bearer ${token}` } : {}),
        },
        body: JSON.stringify({
          messages:[...messages, userMsg].map(m => ({ role:m.role, content:m.content })),
          beatLabel: current.label,
          beatNarration: current.narration,
          episodeTitle: `Ep ${ID} -- ${META.title}`,
        }),
      });
      const data = await res.json();
      if (res.status === 401) {
        setMessages(prev => [...prev, { role:"assistant", content:"Sign in to ask questions -- it takes 30 seconds and the first episode is free." }]);
      } else if (res.status === 429) {
        setMessages(prev => [...prev, { role:"assistant", content:`You have used your ${5} free questions for today. Upgrade to Pro for unlimited questions across all lessons.` }]);
      } else {
        setMessages(prev => [...prev, { role:"assistant", content: data.reply || "Sorry, could not get a response." }]);
        if (data.remaining !== undefined) setRemaining(data.remaining);
      }
    } catch {
      setMessages(prev => [...prev, { role:"assistant", content:"Connection error -- try again." }]);
    }
    setLoading(false);
  }

  function goTo(n) {
    setBeat(n);
    setMessages([{ role:"assistant", content:`You are now on \"${BEATS[n].label}.\" Ask me anything about this step -- including how to run commands on Mac or Windows.` }]);
  }

  return (
    <div style={{ minHeight:"100vh", background:T.paper, fontFamily:T.sans, color:T.ink, display:"flex", flexDirection:"column" }}>

      {/* Top bar */}
      <div style={{ background:T.dark, borderBottom:`1px solid ${T.lineDark}`, padding:"0 24px", height:52, display:"flex", alignItems:"center", justifyContent:"space-between", flexShrink:0 }}>
        <div style={{ display:"flex", alignItems:"center", gap:12 }}>
          <span style={{ fontFamily:T.mono, fontSize:11, color:T.accentSoft, letterSpacing:".1em" }}>THE BUILD LAB</span>
          <span style={{ color:T.lineDark }}>.</span>
          <span style={{ fontFamily:T.mono, fontSize:11, color:T.boneDim }}>EP {ID} . {META.free ? "FREE" : "PRO"}</span>
        </div>
        <div style={{ display:"flex", alignItems:"center", gap:8 }}>
          <span style={{ fontFamily:T.mono, fontSize:11, color:T.boneDim }}>{beat+1} / {BEATS.length}</span>
          <div style={{ width:80, height:3, background:T.dark3, borderRadius:2, overflow:"hidden" }}>
            <div style={{ width:`${progress}%`, height:"100%", background:T.accent, borderRadius:2, transition:"width .3s" }}/>
          </div>
          {!auth.isLoggedIn && (
            <button onClick={() => auth.openLogin()} style={{ marginLeft:14, background:T.accent, color:"#fff", border:"none", borderRadius:6, padding:"6px 12px", fontSize:11, fontFamily:T.mono, cursor:"pointer", letterSpacing:".04em" }}>
              sign in
            </button>
          )}
          <button onClick={() => { window.location.hash = ''; }} style={{ marginLeft:14, background:T.dark3, color:T.boneDim, border:"none", borderRadius:6, padding:"6px 12px", fontSize:11, fontFamily:T.mono, cursor:"pointer", letterSpacing:".04em" }}>
            back to landing
          </button>
        </div>
      </div>

      {/* Claude hint banner -- dismissable */}
      {showHint && (
        <div style={{ background:T.accentTint, borderBottom:`1px solid ${T.accentSoft}`, padding:"10px 24px", display:"flex", alignItems:"center", justifyContent:"space-between", gap:16, flexShrink:0 }}>
          <div style={{ display:"flex", alignItems:"center", gap:10 }}>
            <span style={{ width:7, height:7, borderRadius:"50%", background:T.accent, display:"inline-block", flexShrink:0 }}/>
            <span style={{ fontSize:13, color:T.accentDeep, fontFamily:T.sans }}>
              <strong>Claude is your instructor</strong> -- ask anything in the panel on the right. Stuck on a terminal command? Confused about a step? Just ask. It knows exactly where you are.
            </span>
          </div>
          <button onClick={() => setShowHint(false)} style={{ background:"none", border:"none", color:T.accentDeep, fontSize:16, cursor:"pointer", flexShrink:0, lineHeight:1 }}>x</button>
        </div>
      )}

      {/* Beat nav strip */}
      <div style={{ background:T.dark2, borderBottom:`1px solid ${T.lineDark}`, padding:"0 24px", display:"flex", gap:4, overflowX:"auto", flexShrink:0 }}>
        {BEATS.map((b,i) => (
          <button key={b.id} onClick={() => goTo(i)} style={{
            background: i===beat ? T.accent : "transparent",
            color: i===beat ? "#fff" : i<beat ? T.boneDim : T.inkMute,
            border:"none", borderBottom: i===beat ? `2px solid ${T.accent}` : "2px solid transparent",
            padding:"10px 12px", fontSize:11, fontFamily:T.mono, cursor:"pointer",
            whiteSpace:"nowrap", letterSpacing:".04em", transition:"all .15s", borderRadius:"4px 4px 0 0",
          }}>
            {i<beat ? "+ " : ""}{b.label}
          </button>
        ))}
      </div>

      {/* Main */}
      <div style={{ flex:1, display:"grid", gridTemplateColumns:"1fr 380px", minHeight:0 }}>

        {/* Left: beat content */}
        <div style={{ padding:"40px 48px", overflowY:"auto", borderRight:`1px solid ${T.line}` }}>
          <div style={{ display:"flex", alignItems:"center", gap:12, marginBottom:20 }}>
            <span style={{ fontFamily:T.mono, fontSize:11, color:T.inkMute, letterSpacing:".08em", background:T.paper2, padding:"3px 8px", borderRadius:4 }}>{current.time}</span>
            <span style={{ fontFamily:T.mono, fontSize:11, color:T.accent, letterSpacing:".06em" }}>{(current.label || "").toUpperCase()}</span>
          </div>

          <p style={{ fontFamily:T.serif, fontSize:20, lineHeight:1.65, color:T.ink2, margin:"0 0 32px", maxWidth:580 }}>{current.narration}</p>

          {current.action && (
            <div style={{ background:T.accentTint, border:`1px solid ${T.accentSoft}`, borderRadius:10, padding:"14px 18px", marginBottom:28, display:"flex", alignItems:"flex-start", gap:10 }}>
              <span style={{ fontSize:16, marginTop:1 }}>{"->"}</span>
              <span style={{ fontSize:14, color:T.accentDeep, fontWeight:500, lineHeight:1.5 }}>{current.action}</span>
            </div>
          )}

          {current.pinned && (
            <div style={{ background:T.dark, borderRadius:10, padding:"16px 18px", marginBottom:28 }}>
              <div style={{ display:"flex", alignItems:"center", justifyContent:"space-between", marginBottom:10, gap:14 }}>
                <span style={{ fontFamily:T.mono, fontSize:10.5, color:T.accentSoft, letterSpacing:".08em" }}>{current.pinned.label}</span>
                <CopyButton text={current.pinned.code}/>
              </div>
              <pre style={{ margin:0, fontFamily:T.mono, fontSize:12.5, lineHeight:1.65, color:T.bone, whiteSpace:"pre-wrap", overflowX:"auto" }}>{current.pinned.code}</pre>
            </div>
          )}

          <div style={{ marginTop:36, display:"flex", justifyContent:"space-between", gap:12, paddingTop:24, borderTop:`1px solid ${T.line}` }}>
            <button onClick={() => beat>0 && goTo(beat-1)} disabled={beat===0} style={{ background: beat===0 ? T.paper2 : T.paper3, color: beat===0 ? T.inkMute : T.ink, border:"none", borderRadius:8, padding:"10px 18px", fontSize:13, fontFamily:T.mono, cursor: beat===0 ? "default" : "pointer", letterSpacing:".04em" }}>
              {"<- prev"}
            </button>
            <button onClick={() => {
              if (beat < BEATS.length - 1) { goTo(beat + 1); return; }
              try { localStorage.setItem("bl_ep_complete_" + ID.replace(".", "_"), "1"); } catch (e) {}
              const li = window.BL_AUTH && window.BL_AUTH.isLoggedIn && window.BL_AUTH.isLoggedIn();
              window.location.hash = li ? "#dashboard" : "#pricing";
            }} style={{ background: T.accent, color: "#fff", border:"none", borderRadius:8, padding:"10px 18px", fontSize:13, fontFamily:T.mono, cursor: "pointer", letterSpacing:".04em" }}>
              {beat===BEATS.length-1 ? "complete" : "next ->"}
            </button>
          </div>
        </div>

        {/* Right: Claude Q&A */}
        <div style={{ display:"flex", flexDirection:"column", background:T.dark2, minHeight:0 }}>
          <div style={{ padding:"16px 20px", borderBottom:`1px solid ${T.lineDark}`, display:"flex", alignItems:"center", justifyContent:"space-between", flexShrink:0 }}>
            <span style={{ width:7, height:7, borderRadius:"50%", background:T.accent, display:"inline-block" }}/>
            <span style={{ fontFamily:T.mono, fontSize:11, color:T.boneDim, letterSpacing:".08em" }}>ASK CLAUDE . ABOUT THIS STEP</span>
          </div>

          <div style={{ flex:1, overflowY:"auto", padding:"20px 16px", display:"flex", flexDirection:"column" }}>
            {messages.map((m,i) => <ChatMessage key={i} msg={m}/>)}
            {loading && (
              <div style={{ display:"flex", justifyContent:"flex-start", marginBottom:12 }}>
                <div style={{ background:T.dark3, border:`1px solid ${T.lineDark}`, color:T.boneDim, padding:"10px 14px", borderRadius:"14px 14px 14px 4px", fontSize:13, fontFamily:T.mono }}>...</div>
              </div>
            )}
            <div ref={chatEndRef}/>
          </div>

          {/* Input */}
          <div style={{ padding:"12px 16px", borderTop:`1px solid ${T.lineDark}`, display:"flex", gap:8, flexShrink:0 }}>
            <input
              value={input}
              onChange={(e) => setInput(e.target.value)}
              onKeyDown={(e) => { if (e.key === "Enter") sendMessage(); }}
              placeholder="ask anything about this step..."
              style={{ flex:1, background:T.dark3, border:`1px solid ${T.lineDark}`, color:T.bone, padding:"9px 12px", borderRadius:8, fontSize:13, fontFamily:T.sans, outline:"none" }}
            />
            <button onClick={sendMessage} disabled={loading||!input.trim()} style={{ background:input.trim()?T.accent:T.dark3, border:"none", borderRadius:8, padding:"9px 14px", color:input.trim()?"#fff":T.boneDim, fontSize:13, cursor:input.trim()?"pointer":"default", fontFamily:T.mono, transition:"all .15s" }}>send</button>
          </div>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { EpisodeGuide });
