import { createApi } from './router.js';
import { scenarios, requestCode } from './scenarios.js';
const $=id=>document.getElementById(id);let selected=0,busy=false,reader=null,controller=null,result=null,lastCode='',generation=0,cancelled=false;
let app;
function fresh(){const instance=createApi({onEvent:e=>{if(app!==instance)return;const li=document.createElement('li');li.textContent=e.stage;$('events').append(li);}});app=instance;}fresh();
const state=()=>({method:$('method').value,path:$('path').value,body:$('body').value,token:$('token').value.trim()});
function update(){const s=state();$('body-wrap').hidden=s.method!=='POST';$('bytes').textContent=`${new TextEncoder().encode(s.body).length} байт UTF-8 · лимит API 1024 байта`;$('code').textContent=lastCode=requestCode(s);}
function chooseVariant(v){if(busy)return;$('method').value=v[1];$('path').value=v[2];$('body').value=v[3]??'';$('token').value=v[4]??'';update();}
function choose(index){if(busy)return;selected=index;const s=scenarios[index];$('scenario').value=String(index);$('scenario-title').textContent=s.title;$('goal').textContent=s.goal;$('tip').textContent=s.tip;$('variants').replaceChildren();s.variants.forEach(v=>{const b=document.createElement('button');b.type='button';b.className='btn btn-outline-success';b.textContent=v[0];b.addEventListener('click',()=>chooseVariant(v));$('variants').append(b);});document.querySelectorAll('#scenario-nav button').forEach((b,i)=>b.setAttribute('aria-current',String(index===i)));chooseVariant(s.variants[0]);}
scenarios.forEach((s,i)=>{const option=document.createElement('option');option.value=String(i);option.textContent=s.title;$('scenario').append(option);const b=document.createElement('button');b.textContent=s.title;b.type='button';b.addEventListener('click',()=>choose(i));$('scenario-nav').append(b);});
$('scenario').addEventListener('change',e=>choose(Number(e.target.value)));['method','path','body','token'].forEach(id=>$(id).addEventListener('input',update));
function lock(value){busy=value;['run','scenario','method','path','token','body'].forEach(id=>$(id).disabled=value);document.querySelectorAll('#scenario-nav button,#variants button').forEach(b=>b.disabled=value);$('cancel').disabled=!value;$('download-json').disabled=value||!result;}
function stop(){cancelled=true;controller?.abort();reader?.cancel().catch(()=>{});}
$('cancel').addEventListener('click',stop);
$('reset').addEventListener('click',()=>{generation++;stop();reader=null;controller=null;fresh();lock(false);result=null;$('download-json').disabled=true;$('events').replaceChildren();$('headers').textContent='—';$('response').textContent='Нажмите «Выполнить запрос».';$('status').textContent='Мастерская сброшена. Восстановлено 18 заявок.';$('status').classList.remove('error');$('progress-wrap').hidden=true;choose(0);});
function save(name,text,type){const url=URL.createObjectURL(new Blob([text],{type}));const a=document.createElement('a');a.href=url;a.download=name;a.click();setTimeout(()=>URL.revokeObjectURL(url),1000);}
$('download-json').addEventListener('click',()=>{if(result)save('hono-response.json',JSON.stringify(result,null,2),'application/json');});$('download-code').addEventListener('click',()=>save('request-example.mjs',lastCode,'text/javascript'));
$('request-form').addEventListener('submit',async e=>{
 e.preventDefault();if(busy)return;const s=state();
 if(!/^\/api\/[a-zA-Z0-9_/?=&%+.,\-\u0400-\u04ff]*$/.test(s.path)||s.path.length>300){$('status').textContent='Укажите локальный путь /api/… длиной до 300 символов.';$('status').classList.add('error');return;}
 const my=++generation;cancelled=false;result=null;$('events').replaceChildren();$('response').textContent='Выполняется…';$('headers').textContent='—';$('status').textContent='Hono обрабатывает запрос в браузере…';$('status').classList.remove('error');$('progress').value=0;$('progress-label').textContent='0%';$('progress-wrap').hidden=true;lock(true);controller=new AbortController();const begin=performance.now();
 try{
  const headers={'Content-Type':'application/json'};if(s.token)headers.Authorization=`Bearer ${s.token}`;if(s.method==='OPTIONS'){headers.Origin='https://demo.example';headers['Access-Control-Request-Method']='POST';headers['Access-Control-Request-Headers']='content-type';}
  const response=await app.request(s.path,{method:s.method,headers,signal:controller.signal,...(s.method==='POST'?{body:s.body}:{})});
  if(my!==generation)return;const head=Object.fromEntries(response.headers);$('headers').textContent=JSON.stringify(head,null,2);let body;
  if((response.headers.get('content-type')||'').includes('text/event-stream')){
    $('progress-wrap').hidden=false;const activeReader=response.body.getReader();reader=activeReader;const decoder=new TextDecoder();let text='',pending='';const events=[];$('response').textContent='';
    while(!cancelled&&my===generation){const chunk=await activeReader.read();if(chunk.done||my!==generation)break;const decoded=decoder.decode(chunk.value,{stream:true});text+=decoded;pending+=decoded;$('response').textContent=text;const blocks=pending.split('\n\n');pending=blocks.pop();for(const block of blocks){const line=block.split('\n').find(x=>x.startsWith('data:'));if(line){const data=JSON.parse(line.slice(5));events.push(data);if(data.percent!==undefined){$('progress').value=data.percent;$('progress-label').textContent=data.percent+'%';}}}}
    body={events,raw:text,cancelled};activeReader.releaseLock();if(reader===activeReader)reader=null;
  }else{const text=await response.text();try{body=JSON.parse(text);}catch{body=text||'(пустое тело)';}$('response').textContent=typeof body==='string'?body:JSON.stringify(body,null,2);}
  if(my!==generation)return;const elapsed=Math.round((performance.now()-begin)*100)/100;result={runtime:'Hono app.request in browser; no network request',request:s,status:response.status,headers:head,elapsedMs:elapsed,body};$('status').textContent=`${cancelled?'Чтение остановлено · ':''}HTTP ${response.status} · ${elapsed} мс на этом устройстве`;$('status').classList.toggle('error',response.status>=400);
 }catch(err){if(my!==generation)return;$('status').textContent=cancelled?'Чтение остановлено.':`Ошибка выполнения: ${err.message}`;$('status').classList.add('error');$('response').textContent=cancelled?'Поток закрыт. Можно запустить новый запрос.':String(err.message);}
 finally{if(my===generation){reader=null;controller=null;lock(false);}}
});choose(0);
