import {advertisingQaConfiguration} from './qa.mjs';
import {createAdvertisingAge} from './age.mjs';
import {withAccountOperation} from '../account-operation.mjs';
import {AdvertisingError} from './reward-ledger.mjs';
import {validateDeviceSave} from '../../dist/js/offline/device-schema.mjs';
import {deviceAdvertisingContext} from '../../dist/js/advertising/device-context.mjs';
import {canRetryDaily,dexQuestionPool,selectRetryQuestions,selectRetryReward} from '../../dist/js/pixelpotes/daily-review.mjs';
import {act,normalizeState} from '../../dist/js/pixelpotes/model.mjs';
import ja from '../../dist/assets/lexicon/ja.json' with {type:'json'};
const fail=(message,status=409)=>{throw Object.assign(new AdvertisingError('ad_game_qa',status),{message});};
// Separate test ledger. Client-reported demo events are NOT SSV evidence. This
// service never touches production intents, backups, wallets or real grants.
export function createAdvertisingGameQa(env,{now=Date.now,random=Math.random}={}){
 const db=env.DB,age=createAdvertisingAge({db,now});
 async function run(user,body){
  if(env.PIXELINGO_AD_QA_GAME_ENABLED!=='true'||!advertisingQaConfiguration(env,user))fail('Test indisponible.',404);
  if(!body||body.testOnly!==true)fail('Parcours réservé aux essais.',400);
  return withAccountOperation(db,user.id,async lease=>{
   const declared=await age.requireEligible(user);
   if(body.action==='prepare'){
    const save=validateDeviceSave(body.save),c=await deviceAdvertisingContext(save);
    if(save.flow?.status!=='completed'||!canRetryDaily(c.daily,c.day))fail('Termine le défi de test avant la relance.');
    if(body.network==='unity'&&declared.band!=='18-plus')fail('Le diagnostic Unity est réservé aux testeurs majeurs.');
    if(!['google','unity'].includes(body.network))fail('Source de test inconnue.',400);
    const bytes=crypto.getRandomValues(new Uint8Array(32)),id=btoa(String.fromCharCode(...bytes)).replaceAll('+','-').replaceAll('/','_').replace(/=+$/,'');
    const intent={id,accountId:user.id,profileId:save.id,contextKey:c.contextKey,ageRevision:declared.revision,ageBand:declared.band,expiresAt:now()+1800000,network:body.network,testOnly:true};
    await lease.finalize([db.prepare('DELETE FROM advertising_game_qa WHERE user_id=? AND expires_at<?').bind(user.id,now()),db.prepare('INSERT INTO advertising_game_qa(id,user_id,profile_id,context_key,age_revision,expires_at,payload,completed) VALUES(?,?,?,?,?,?,?,0)').bind(id,user.id,save.id,c.contextKey,declared.revision,intent.expiresAt,JSON.stringify({save,intent}))]);return intent;
   }
   if(typeof body.id!=='string'||!/^[A-Za-z0-9_-]{43}$/.test(body.id))fail('Essai invalide.',400);
   const row=await db.prepare('SELECT * FROM advertising_game_qa WHERE id=? AND user_id=?').bind(body.id,user.id).first();
   if(!row||row.expires_at<=now()||row.age_revision!==declared.revision)fail('Cet essai a expiré ou la déclaration d’âge a changé.');
   const {save,intent}=JSON.parse(row.payload);
   if(body.action==='status')return {testOnly:true,completed:!!row.completed,grant:row.grant?JSON.parse(row.grant):null};
   if(body.action==='complete'){
    if(body.sdkReportedCompletion!==true||body.network!==intent.network)fail('La vidéo de démonstration n’est pas terminée.');
    await lease.finalize([db.prepare('UPDATE advertising_game_qa SET completed=1 WHERE id=? AND user_id=?').bind(body.id,user.id)]);return {testOnly:true,completed:true};
   }
   if(body.action!=='consume')fail('Action de test inconnue.',400);
   if(row.grant)return {...JSON.parse(row.grant),replayed:true};
   if(!row.completed||body.contextKey!==row.context_key)fail('Relance de test non confirmée.');
   const c=await deviceAdvertisingContext(save),entries=[...Object.values(save.pot.dexRewards||{}),...Object.values(save.promenadeGift||{})].filter(e=>e?.language==='ja');
   const questions=selectRetryQuestions(dexQuestionPool({entries,catalogue:ja},'ja'),c.daily,random),seen=new Set(entries.map(e=>e.id));
   const rewardCandidate=selectRetryReward(ja.entries.filter(e=>!seen.has(e.id)).map(e=>({id:e.id,language:'ja',source:e.displayWord,meanings:e.meanings,readings:e.readings})),c.daily,save.pot,random),receiptId='qa:'+intent.id;
   const applied=act(normalizeState(save.pot,now()),{type:'daily-retry',day:c.day,language:c.language,attempt:c.attempt,receiptId},now(),{dailyDay:c.day,dailyRetryGrant:{...c,source:'ad',receiptId,questions,rewardCandidate}});
   if(!applied.ok)fail(applied.message);
   const grant={ok:true,testOnly:true,authority:'solo-daily-retry',accountId:user.id,profileId:save.id,contextKey:c.contextKey,intentId:intent.id,receiptId,day:c.day,language:c.language,attempt:c.attempt,daily:applied.state.dailyReview};
   await lease.finalize([db.prepare('UPDATE advertising_game_qa SET grant=? WHERE id=? AND user_id=? AND grant IS NULL').bind(JSON.stringify(grant),intent.id,user.id)]);return grant;
  },now);
 }
 return {run};
}
