(()=>{
  if(window.__kir0SignalLoaded)return;
  window.__kir0SignalLoaded=true;

  let box=null;
  let video=null;
  let enabled=true;
  let minimized=false;
  let generation=0;
  let rvfcId=null;
  let frameTimes=[];
  let mediaSamples=[];
  let smoothFps=0;
  let lastQuality=null;
  let qualityBase=null;
  let lastVideoCheck=0;
  let drag=null;

  const $=id=>box?.querySelector('#'+id);
  const fmt=(n,d=1)=>Number.isFinite(n)?n.toFixed(d):'Unknown';

  function visibleArea(el){
    const r=el.getBoundingClientRect();
    const w=Math.max(0,Math.min(innerWidth,r.right)-Math.max(0,r.left));
    const h=Math.max(0,Math.min(innerHeight,r.bottom)-Math.max(0,r.top));
    return w*h;
  }

  function getVideo(){
    const videos=[...document.querySelectorAll('video')].filter(v=>v.readyState>0&&visibleArea(v)>8000);
    let best=null,bestScore=-Infinity;
    for(const v of videos){
      const r=v.getBoundingClientRect();
      const area=visibleArea(v);
      const cy=(r.top+r.bottom)/2;
      const centerPenalty=Math.abs(cy-innerHeight/2);
      const score=(v.paused?0:1e9)+(v.ended?-2e9:0)+(v.readyState>=3?1e7:0)+area-centerPenalty*1000;
      if(score>bestScore){bestScore=score;best=v;}
    }
    return best;
  }

  function resetMeasurement(next){
    generation++;
    if(video&&rvfcId!=null&&video.cancelVideoFrameCallback){
      try{video.cancelVideoFrameCallback(rvfcId)}catch{}
    }
    rvfcId=null;
    video=next;
    frameTimes=[];
    mediaSamples=[];
    smoothFps=0;
    lastQuality=null;
    qualityBase=null;
    if(video){
      const q=video.getVideoPlaybackQuality?.();
      if(q){
        qualityBase={total:q.totalVideoFrames||0,dropped:q.droppedVideoFrames||0};
        lastQuality=q;
      }
      startFrameClock(video,generation);
    }
  }

  function startFrameClock(v,token){
    if(!v?.requestVideoFrameCallback)return;
    const tick=(now,meta)=>{
      if(token!==generation||v!==video)return;
      frameTimes.push(now);
      if(Number.isFinite(meta?.mediaTime))mediaSamples.push({t:now,m:meta.mediaTime});
      const cutoff=now-1800;
      while(frameTimes.length&&frameTimes[0]<cutoff)frameTimes.shift();
      while(mediaSamples.length&&mediaSamples[0].t<cutoff)mediaSamples.shift();

      if(frameTimes.length>=3){
        const span=(frameTimes[frameTimes.length-1]-frameTimes[0])/1000;
        const raw=span>0?(frameTimes.length-1)/span:0;
        if(raw>=0&&raw<300)smoothFps=smoothFps?((smoothFps*0.72)+(raw*0.28)):raw;
      }
      rvfcId=v.requestVideoFrameCallback(tick);
    };
    rvfcId=v.requestVideoFrameCallback(tick);
  }

  function sourceFps(){
    if(mediaSamples.length<4)return 0;
    const deltas=[];
    for(let i=1;i<mediaSamples.length;i++){
      const d=mediaSamples[i].m-mediaSamples[i-1].m;
      if(d>0.001&&d<0.2)deltas.push(d);
    }
    if(!deltas.length)return 0;
    deltas.sort((a,b)=>a-b);
    const median=deltas[Math.floor(deltas.length/2)];
    const f=1/median;
    if(f>23&&f<25)return 24;
    if(f>28&&f<32)return 30;
    if(f>47&&f<50)return 48;
    if(f>57&&f<63)return 60;
    if(f>118&&f<122)return 120;
    return f;
  }

  function setPos(x,y){
    if(!box)return;
    const margin=8;
    const maxX=Math.max(margin,innerWidth-box.offsetWidth-margin);
    const maxY=Math.max(margin,innerHeight-box.offsetHeight-margin);
    x=Math.max(margin,Math.min(maxX,x));
    y=Math.max(margin,Math.min(maxY,y));
    box.style.left=x+'px';box.style.top=y+'px';box.style.right='auto';
    return {x,y};
  }

  function applySavedPosition(){
    chrome.storage.local.get({kir0SignalPosition:null},r=>{
      const p=r.kir0SignalPosition;
      if(p&&Number.isFinite(p.x)&&Number.isFinite(p.y))setPos(p.x,p.y);
    });
  }

  function installDrag(){
    const head=box.querySelector('.kqHead');
    head.addEventListener('pointerdown',e=>{
      if(e.button!==0||e.target.closest('button'))return;
      const r=box.getBoundingClientRect();
      drag={dx:e.clientX-r.left,dy:e.clientY-r.top};
      head.setPointerCapture?.(e.pointerId);
      box.classList.add('kqDragging');
      e.preventDefault();
    });
    head.addEventListener('pointermove',e=>{
      if(!drag)return;
      setPos(e.clientX-drag.dx,e.clientY-drag.dy);
    });
    const stop=e=>{
      if(!drag)return;
      drag=null;box.classList.remove('kqDragging');
      const r=box.getBoundingClientRect();
      chrome.storage.local.set({kir0SignalPosition:{x:r.left,y:r.top}});
      try{head.releasePointerCapture?.(e.pointerId)}catch{}
    };
    head.addEventListener('pointerup',stop);
    head.addEventListener('pointercancel',stop);
  }

  function setMinimized(value,save=true){
    minimized=!!value;
    if(!box)return;
    box.classList.toggle('kqMin',minimized);
    const btn=box.querySelector('.kqMinBtn');
    if(btn){btn.textContent=minimized?'+':'−';btn.title=minimized?'Expand':'Minimize';}
    if(save)chrome.storage.local.set({kir0SignalMinimized:minimized});
    requestAnimationFrame(()=>{
      const r=box.getBoundingClientRect();
      setPos(r.left,r.top);
    });
  }

  function build(){
    if(box)return;
    box=document.createElement('div');
    box.id='kir0-signal';
    box.innerHTML=`
      <div class="kqHead">
        <div class="kqCompact"><b id="kqCompactFps">— FPS</b><span id="kqCompactTag">NO VIDEO</span><i>● LIVE</i></div>
        <span class="kqBrand">KIR0 SIGNAL</span><span class="kqLive">● LIVE</span>
        <button class="kqMinBtn" title="Minimize">−</button>
      </div>
      <div class="kqBody">
        <div class="kqFps"><span id="kqFps">—</span><small>FPS</small></div>
        <div class="kqSub"><span>SOURCE <b id="kqSource">—</b></span><span>DROPPED <b id="kqDrop">—</b></span></div>
        <div class="kqLine"></div>
        <div class="kqTags"><span class="kqTag" id="kqResTag">NO VIDEO</span></div>
        <div class="kqGrid">
          <div class="kqCell"><span>RESOLUTION</span><b id="kqRes">—</b></div>
          <div class="kqCell"><span>ON SCREEN</span><b id="kqScreen">—</b></div>
          <div class="kqCell"><span>BUFFER</span><b id="kqBuffer">—</b></div>
          <div class="kqCell"><span>STATE</span><b id="kqState">Waiting</b></div>
          <div class="kqCell"><span>TIME</span><b id="kqTime">—</b></div>
          <div class="kqCell"><span>BITRATE</span><b>Unknown</b></div>
        </div>
        <div class="kqFoot"><span>LOCAL MEASUREMENTS</span><span>kir0Signal V1.1</span></div>
      </div>`;
    document.documentElement.appendChild(box);
    box.querySelector('.kqMinBtn').onclick=()=>setMinimized(!minimized);
    installDrag();
    chrome.storage.local.get({kir0SignalMinimized:false},r=>setMinimized(!!r.kir0SignalMinimized,false));
    applySavedPosition();
  }

  function update(){
    if(!enabled)return;
    build();
    const now=performance.now();
    if(now-lastVideoCheck>180){
      lastVideoCheck=now;
      const next=getVideo();
      if(next!==video)resetMeasurement(next);
    }

    if(!video){
      $('kqState').textContent='Waiting';
      $('kqFps').textContent='—';
      $('kqSource').textContent='—';
      $('kqCompactFps').textContent='— FPS';
      $('kqCompactTag').textContent='NO VIDEO';
      return;
    }

    const q=video.getVideoPlaybackQuality?.();
    let drop=0;
    if(q){
      if(!qualityBase)qualityBase={total:q.totalVideoFrames||0,dropped:q.droppedVideoFrames||0};
      const total=Math.max(0,(q.totalVideoFrames||0)-qualityBase.total);
      const dropped=Math.max(0,(q.droppedVideoFrames||0)-qualityBase.dropped);
      drop=total?100*dropped/total:0;
      lastQuality=q;
    }

    const measured=video.paused||video.readyState<2?0:smoothFps;
    const shown=measured>0?Math.max(0,Math.round(measured)):0;
    const src=sourceFps();
    $('kqFps').textContent=shown||'—';
    $('kqSource').textContent=src?fmt(src,2):'—';
    $('kqDrop').textContent=fmt(drop,1)+'%';

    const w=video.videoWidth||0,h=video.videoHeight||0;
    const res=w&&h?`${w}×${h}`:'—';
    const tag=h?`${h}p`:'NO VIDEO';
    $('kqRes').textContent=res;
    $('kqScreen').textContent=`${Math.round(video.clientWidth)}×${Math.round(video.clientHeight)}`;
    $('kqResTag').textContent=tag;
    $('kqCompactFps').textContent=(shown||'—')+' FPS';
    $('kqCompactTag').textContent=tag;

    let ahead=0;
    try{
      for(let i=0;i<video.buffered.length;i++){
        if(video.currentTime>=video.buffered.start(i)&&video.currentTime<=video.buffered.end(i)){
          ahead=Math.max(0,video.buffered.end(i)-video.currentTime);break;
        }
      }
    }catch{}
    $('kqBuffer').textContent=fmt(ahead,1)+'s';
    $('kqState').textContent=video.error?'Error':video.seeking?'Seeking':video.readyState<3?'Buffering':video.paused?'Paused':'Playing';
    $('kqTime').textContent=`${fmt(video.currentTime,0)}s / ${Number.isFinite(video.duration)?fmt(video.duration,0)+'s':'—'}`;
  }

  window.addEventListener('resize',()=>{
    if(!box)return;
    const r=box.getBoundingClientRect();
    const p=setPos(r.left,r.top);
    if(p)chrome.storage.local.set({kir0SignalPosition:p});
  },{passive:true});

  chrome.storage.local.get({kir0SignalEnabled:true},r=>{
    enabled=!!r.kir0SignalEnabled;
    if(enabled){build();update();setInterval(update,250);}
  });

  chrome.storage.onChanged.addListener(c=>{
    if(c.kir0SignalEnabled){
      enabled=!!c.kir0SignalEnabled.newValue;
      if(enabled){build();update();}
      else if(box){box.remove();box=null;resetMeasurement(null);}
    }
  });
})();
