import Ajv2020 from 'ajv/dist/2020.js';
import addFormats from 'ajv-formats';
import{lessons,byKey}from'./schemas.mjs';
export const LIMITS={bytes:65536,depth:24,nodes:4000,lines:200};
const ajv=new Ajv2020({allErrors:true,strict:true});addFormats(ajv);
const validators=new Map(lessons.map(l=>[l.key,ajv.compile(l.schema)]));
const normalizer=new Ajv2020({allErrors:true,strict:true,coerceTypes:true,useDefaults:true,removeAdditional:true});addFormats(normalizer);
const normalize=normalizer.compile(byKey.normalize.schema);
export function guardData(data){
 let count=0;const stack=[[data,0]];
 while(stack.length){const[v,depth]=stack.pop();if(++count>LIMITS.nodes||depth>LIMITS.depth)throw new Error('Данные слишком сложные: не более 4000 узлов и глубины 24.');if(v&&typeof v==='object')for(const[k,x]of Object.entries(v)){if(['__proto__','prototype','constructor'].includes(k))throw new Error('Служебные ключи объектов в учебном импорте запрещены.');stack.push([x,depth+1]);}}
}
export function parseInput(text){if(new TextEncoder().encode(text).length>LIMITS.bytes)throw new Error('Максимальный размер JSON — 64 КиБ.');let data;try{data=JSON.parse(text);}catch{throw new Error('JSON не разобран: проверьте кавычки, запятые и скобки.');}guardData(data);return data;}
export function errorPath(error){const escape=k=>String(k).replaceAll('~','~0').replaceAll('/','~1');return error.instancePath+(error.keyword==='required'?'/'+escape(error.params.missingProperty):error.keyword==='additionalProperties'?'/'+escape(error.params.additionalProperty):'');}
export function validateData(key,data,{mutate=false}={}){
 if(!validators.has(key))throw new Error('Неизвестная схема.');guardData(data);
 const output=structuredClone(data),validate=key==='normalize'&&mutate?normalize:validators.get(key),valid=validate(output);
 const errors=structuredClone(validate.errors??[]).map(e=>({...e,path:errorPath(e)}));
 return{key,valid,errors,input:structuredClone(data),output,changed:JSON.stringify(data)!==JSON.stringify(output),mode:key==='normalize'&&mutate?'normalize-copy':'validate-only'};
}
export function validateText(key,text,options){return validateData(key,parseInput(text),options);}
export function importLines(text){
 if(new TextEncoder().encode(text).length>LIMITS.bytes)throw new Error('Максимальный размер импорта — 64 КиБ.');const lines=text.split(/\r?\n/);if(lines.length>LIMITS.lines)throw new Error('Не более 200 строк за одну проверку.');
 const rows=[];for(let i=0;i<lines.length;i++){if(!lines[i].trim())continue;try{const result=validateText('import',lines[i]);rows.push({line:i+1,...result});}catch(e){rows.push({line:i+1,valid:false,parseError:e.message,errors:[]});}}
 return{mode:'ndjson',rows,total:rows.length,accepted:rows.filter(r=>r.valid).length,rejected:rows.filter(r=>!r.valid).length};
}
export function recipe(key,{mutate=false}={}){if(!byKey[key])throw new Error('Неизвестная схема.');const options=key==='normalize'&&mutate?{allErrors:true,strict:true,coerceTypes:true,useDefaults:true,removeAdditional:true}:{allErrors:true,strict:true};return`// npm install ajv@8.20.0 ajv-formats@3.0.1\nimport Ajv2020 from 'ajv/dist/2020.js';\nimport addFormats from 'ajv-formats';\nconst ajv = new Ajv2020(${JSON.stringify(options)});\naddFormats(ajv);\nconst schema = ${JSON.stringify(byKey[key].schema,null,2)};\nconst validate = ajv.compile(schema); // один раз при старте\nconst input = ${JSON.stringify(byKey[key].good,null,2)};\nconst output = structuredClone(input);\nconst valid = validate(output);\nconst errors = structuredClone(validate.errors ?? []);\nconsole.log({ valid, errors, input, output });\n`;}
