"""
First-login guided tour — a lightweight spotlight walkthrough.

`tour(page_key, steps)` returns an HTML snippet (style + overlay + script) to drop
before </body>. On first visit it dims the screen, highlights each target element,
and shows a titled tip with Next/Back/Skip. It runs once (remembered in
localStorage); a "?" help button (`help_button()`) replays it.

steps = [{"sel": "#id-or-.class", "title": "...", "body": "..."}, ...]
A step with no/not-found selector is shown centered (good for intro/outro).
No dependencies; safe to inject on any themed page.

Robustness: the target is scrolled into view FIRST, then measured on the next
frame, so the spotlight always lands on the right element; ending the tour fully
removes the overlay so the app is usable again.
"""

from __future__ import annotations

import json


def help_button() -> str:
    """A small round '?' button (put in a topbar) that replays the tour."""
    return ('<button class="iconbtn" onclick="biosyncTour&&biosyncTour(true)" '
            'title="Show the guided tour" style="width:34px;padding:0">?</button>')


def tour(page_key: str, steps: list[dict]) -> str:
    data = json.dumps(steps)
    return r"""
<style>
 #tourBlock{position:fixed;inset:0;z-index:9000;background:transparent;display:none}
 #tourHi{position:fixed;z-index:9001;border-radius:10px;border:2px solid var(--accent);
   box-shadow:0 0 0 9999px rgba(10,20,24,.60);transition:all .18s ease;pointer-events:none;display:none}
 #tourPop{position:fixed;z-index:9002;max-width:330px;width:min(330px,calc(100vw - 28px));
   background:var(--surface);color:var(--ink);border-radius:12px;
   box-shadow:0 12px 34px rgba(0,0,0,.30);padding:16px 18px;display:none}
 #tourPop h3{margin:0 0 6px;font-size:15px;color:var(--primary)}
 #tourPop p{margin:0 0 12px;font-size:14px;line-height:1.45}
 #tourPop .row{display:flex;gap:8px;align-items:center}
 #tourPop .prog{flex:1;font-size:12px;color:var(--muted)}
 #tourPop button{border:0;border-radius:8px;padding:7px 14px;font-size:13px;cursor:pointer;font-weight:600}
 #tourPop .skip{background:transparent;color:var(--muted)}
 #tourPop .next{background:var(--primary);color:#fff}
</style>
<div id="tourBlock"></div><div id="tourHi"></div>
<div id="tourPop"><h3 id="tourTitle"></h3><p id="tourBody"></p>
  <div class="row"><span class="prog" id="tourProg"></span>
    <button class="skip" id="tourSkip">Skip</button>
    <button class="next" id="tourNext">Next</button></div></div>
<script>
(function(){
 var KEY="biosync_tour___PAGEKEY__", STEPS=__STEPS__, i=0;
 var blk=document.getElementById("tourBlock"), hi=document.getElementById("tourHi"),
     pop=document.getElementById("tourPop");

 function place(el){
   var r=el.getBoundingClientRect();
   hi.style.display="block";
   hi.style.left=(r.left-6)+"px"; hi.style.top=(r.top-6)+"px";
   hi.style.width=(r.width+12)+"px"; hi.style.height=(r.height+12)+"px";
   // popover below the target, or above if it would overflow
   var pw=pop.offsetWidth||320, ph=pop.offsetHeight||160;
   var left=Math.min(Math.max(12, r.left), window.innerWidth-pw-12);
   var top=r.bottom+12;
   if(top+ph > window.innerHeight-12) top=Math.max(12, r.top-ph-12);
   pop.style.left=left+"px"; pop.style.top=top+"px";
 }
 function center(){
   hi.style.display="none";
   var pw=pop.offsetWidth||320, ph=pop.offsetHeight||160;
   pop.style.left=Math.round((window.innerWidth-pw)/2)+"px";
   pop.style.top=Math.round((window.innerHeight-ph)/2)+"px";
 }
 function show(n){
   i=n; var s=STEPS[n];
   document.getElementById("tourTitle").textContent=s.title;
   document.getElementById("tourBody").textContent=s.body;
   document.getElementById("tourProg").textContent=(n+1)+" / "+STEPS.length;
   document.getElementById("tourNext").textContent=(n===STEPS.length-1)?"Done":"Next";
   blk.style.display="block"; pop.style.display="block";
   var el=s.sel && document.querySelector(s.sel);
   if(el){
     el.scrollIntoView({block:"center",inline:"nearest"});   // scroll FIRST
     // measure AFTER the scroll/layout settles, so the spotlight is correct
     requestAnimationFrame(function(){ setTimeout(function(){ place(el); }, 60); });
   } else {
     center();
   }
 }
 function end(){
   blk.style.display="none"; hi.style.display="none"; pop.style.display="none";
   try{ localStorage.setItem(KEY,"1"); }catch(e){}
   document.removeEventListener("keydown", onKey);
 }
 function onKey(e){ if(e.key==="Escape") end(); }

 document.getElementById("tourNext").addEventListener("click", function(){
   (i+1<STEPS.length)?show(i+1):end(); });
 document.getElementById("tourSkip").addEventListener("click", end);
 document.addEventListener("keydown", onKey);
 window.addEventListener("resize", function(){
   var s=STEPS[i], el=s&&s.sel&&document.querySelector(s.sel);
   if(pop.style.display!=="none"){ el?place(el):center(); } });

 window.biosyncTour=function(force){
   if(force){ try{ localStorage.removeItem(KEY); }catch(e){} }
   document.addEventListener("keydown", onKey); show(0); };
 try{ if(!localStorage.getItem(KEY)) setTimeout(function(){ show(0); }, 500); }catch(e){}
})();
</script>
""".replace("__PAGEKEY__", page_key).replace("__STEPS__", data)
