import {scenarios} from './scenarios.js';
import {boundedFetch,loadReference} from './scalar-config.js';
const $=id=>document.getElementById(id);
let controller=null,generation=0,lastResult=null;
function download(name,text,type='application/json'){
 const href=URL.createObjectURL(new Blob([text],{type}));const a=document.createElement('a');a.href=href;a.download=name;a.click();setTimeout(()=>URL.revokeObjectURL(href),1000);
}
function option(value,text){const o=document.createElement('option');o.value=value;o.textContent=text;return o;}
scenarios.forEach((s,i)=>$('scenario').append(option(String(i),s.title)));
function selected(){return scenarios[Number($('scenario').value)];}
function variant(){return selected().variants[Number($('variant').value)];}
function cancel(){generation++;controller?.abort();controller=null;$('send').disabled=false;$('cancel').disabled=true;}
function clearResult(){lastResult=null;$('download').disabled=true;$('status').textContent='Готово к отправке';$('status').dataset.state='';$('http').textContent='—';$('duration').textContent='—';$('response').textContent='Нет ответа';$('headers').textContent='—';$('result-help').textContent='Ответ появится после отправки. Здесь не показана заранее сохранённая запись.';}
function updateVariant(){
 cancel();clearResult();const v=variant();
 $('why').textContent=selected().why;$('learn').textContent=selected().learn;
 $('method').textContent=v.method;$('endpoint').textContent='api/'+v.path;
 $('query-panel').hidden=!v.query;$('query').value=JSON.stringify(v.query??{},null,2);
 $('body-panel').hidden=!['POST','PATCH'].includes(v.method);$('body').value=v.raw??JSON.stringify(v.body??{},null,2);
 $('token-panel').hidden=selected().id!=='auth';$('token').value=v.token??'';
 $('file-panel').hidden=selected().id!=='upload';$('file').value='';
 $('body-type').textContent='Content-Type: '+(v.contentType??'application/json');$('expected').textContent=String(v.expect);
 $('input-note').textContent='';updateCurl();
}
function updateScenario(){const s=selected();$('variant').replaceChildren(...s.variants.map((v,i)=>option(String(i),v.title)));updateVariant();}
function requestData(){
 const v=variant();const url=new URL('./api/'+v.path,location.href);
 if(v.query){let q;try{q=JSON.parse($('query').value);}catch{throw new Error('Параметры URL должны быть JSON-объектом.');}
  if(!q||Array.isArray(q)||typeof q!=='object')throw new Error('Параметры URL должны быть объектом.');
  for(const [key,value]of Object.entries(q)){if(!['string','number','boolean'].includes(typeof value))throw new Error('Значения параметров должны быть строками или числами.');url.searchParams.set(key,String(value));}}
 const headers={Accept:'application/json'};let body;
 if(['POST','PATCH'].includes(v.method)){body=$('body').value;headers['Content-Type']=v.contentType??'application/json';}
 if(selected().id==='auth'&&$('token').value)headers.Authorization='Bearer '+$('token').value;
 return {url:url.href,method:v.method,headers,body};
}
const shellQuote=value=>"'"+value.replaceAll("'","'\\''")+"'";
function curlOf(r){return ['curl -i -X '+r.method+' '+shellQuote(r.url),...Object.entries(r.headers).map(([k,v])=>'-H '+shellQuote(k+': '+v)),...(r.body!==undefined?['--data-binary '+shellQuote(r.body)]:[])].join(' \\\n  ');}
function updateCurl(){try{$('curl').textContent=curlOf(requestData());}catch(e){$('curl').textContent=e.message;}}
$('scenario').addEventListener('change',updateScenario);$('variant').addEventListener('change',updateVariant);$('reset').addEventListener('click',updateVariant);
for(const id of ['query','body','token'])$(id).addEventListener('input',updateCurl);
$('cancel').addEventListener('click',()=>{cancel();$('status').textContent='Запрос отменён';$('status').dataset.state='';$('result-help').textContent='Можно изменить данные и отправить снова.';});
$('send').addEventListener('click',async()=>{
 cancel();clearResult();let r;
 try{r=requestData();}catch(e){$('status').textContent=e.message;$('status').dataset.state='error';return;}
 const ticket=generation;controller=new AbortController();$('send').disabled=true;$('cancel').disabled=false;$('status').textContent='Отправляем запрос…';$('status').dataset.state='loading';
 const started=performance.now();const activeController=controller;const timeout=setTimeout(()=>activeController.abort(),10000);
 try{
  const response=await boundedFetch(r.url,{method:r.method,headers:r.headers,body:r.body,signal:controller.signal});
  const raw=await response.text();if(ticket!==generation)return;
  const ms=Math.round(performance.now()-started);let data;try{data=JSON.parse(raw);}catch{data={message:'Сервер вернул не JSON',preview:raw.slice(0,1000)};}
  const headers=Object.fromEntries(['content-type','x-request-id','x-aen-demo','retry-after','allow','www-authenticate'].filter(k=>response.headers.has(k)).map(k=>[k,response.headers.get(k)]));
  lastResult={scenario:selected().id,request:r,status:response.status,durationMs:ms,headers,response:data};
  $('status').textContent='HTTP '+response.status+' · ответ получен';$('status').dataset.state=response.ok?'success':'error';$('http').textContent=String(response.status);$('duration').textContent=ms+' мс';$('response').textContent=JSON.stringify(data,null,2);$('headers').textContent=JSON.stringify(headers,null,2);$('download').disabled=false;
  $('result-help').textContent=response.status===variant().expect?'Ответ совпал с исходным примером. После ваших изменений статус может быть другим.':'Статус отличается от исходного примера: изучите ответ и изменённые поля.';
 }catch(e){if(ticket!==generation)return;$('status').textContent=e.name==='AbortError'?'Превышено ожидание 10 секунд':'Запрос не завершён';$('status').dataset.state='error';$('response').textContent=e.message;$('result-help').textContent='Проверьте PHP-сервер и соединение. Затем можно повторить запрос.';
 }finally{clearTimeout(timeout);if(ticket===generation){controller=null;$('send').disabled=false;$('cancel').disabled=true;}}
});
$('file').addEventListener('change',async()=>{const f=$('file').files[0];if(!f)return;const ticket=generation;if(f.size>4096){$('input-note').textContent='Файл больше 4096 байт. Выберите небольшой учебный TXT.';$('file').value='';return;}const text=await f.text();if(ticket!==generation)return;$('body').value=text;updateCurl();$('input-note').textContent='Файл прочитан локально. Нажмите «Отправить запрос», чтобы передать текст.';});
$('download').addEventListener('click',()=>{if(lastResult)download('scalar-'+lastResult.scenario+'-result.json',JSON.stringify(lastResult,null,2));});
$('copy-curl').addEventListener('click',async()=>{try{await navigator.clipboard.writeText($('curl').textContent);$('input-note').textContent='Команда скопирована. Для PowerShell используйте curl.exe и проверьте кавычки; надёжнее передать тело через файл.';}catch{$('input-note').textContent='Копирование недоступно. Выделите команду в блоке выше.';}});
$('load-scalar').addEventListener('click',async()=>{const button=$('load-scalar');button.disabled=true;$('scalar-host').hidden=false;$('scalar-note').textContent='Загружаем локальную библиотеку и контракт…';try{await loadReference('#scalar');$('scalar-note').textContent='Scalar загружен. Откройте операцию и нажмите Test Request для настоящего запроса.';button.textContent='Scalar открыт';}catch(e){$('scalar-note').textContent=e.message;button.disabled=false;}});
updateScenario();
