import * as DateTime from 'effect/DateTime';
import * as Option from 'effect/Option';
import { AtomRegistry } from 'effect/reactivity';
import { startThreadNotifications } from 'f4-coordinator';
import { shellAtom } from 'f4-state';

declare const __SIDE__: 'before'|'after';
declare const __SHA__: string;
const element = (id: string) => document.getElementById(id)!;
const notes: {t:string;body:string|undefined;at:string;elapsed:number}[] = [];
const events: {elapsed:number;at:string;message:string}[] = [];
Object.assign(window, {__notes:notes,__events:events});
let epoch = 0;
function log(message: string, kind = '') {
  const elapsed = (performance.now()-epoch)/1000;
  const at = new Date().toISOString();
  events.push({elapsed,at,message});
  const line = document.createElement('div'); line.className=kind;
  line.textContent=`t=${elapsed.toFixed(3).padStart(6)}s  ${at.slice(11,23)}Z  ${message}`;
  element('log').append(line);
}
// Recorder from the PR body, extended only with visible log output and the tag read by the coordinator.
class RecordingNotification {
  static permission = 'granted';
  static requestPermission = async () => 'granted';
  tag: string;
  constructor(title: string, options?: NotificationOptions) {
    notes.push({t:title,body:options?.body,at:new Date().toISOString(),elapsed:(performance.now()-epoch)/1000});
    this.tag=options?.tag??'';
    element('count').textContent=String(notes.length);
    log(`Notification(${JSON.stringify(title)}) #${notes.length}`, 'alert');
  }
  close() {}
  addEventListener() {}
}
Object.assign(window,{Notification:RecordingNotification});
Document.prototype.hasFocus = () => false;
const now = DateTime.makeUnsafe('2026-11-10T12:00:00.000Z');
const monitor = {id:'synthetic-monitor',kind:'monitor',title:'Synthetic pending Monitor',status:'running'};
function thread(run: 'user'|'wake', status:'running'|'completed', pending:boolean) {
  return {
    id:'synthetic-thread',projectId:'synthetic-project',title:'F4 synthetic Monitor thread',
    providerInstanceId:'claude',modelSelection:{instanceId:'claude',model:'synthetic'},runtimeMode:'full-access',interactionMode:'default',
    branch:null,worktreePath:null,activeProviderThreadId:null,
    lineage:{rootThreadId:'synthetic-thread',parentThreadId:null,relationshipToParent:null},forkedFrom:null,createdBy:'user',creationSource:'web',
    latestRunId:`${run}-run`,activeRunId:status==='running'?`${run}-run`:null,status,
    latestRunBackgroundWake:run==='wake',pendingBackgroundTasks:pending?[monitor]:[],pendingRuntimeRequest:null,
    latestVisibleMessage:null,latestUserMessageAt:null,hasActionableProposedPlan:false,itemCount:0,visibleItemCount:0,
    createdAt:now,updatedAt:now,latestRunRequestedAt:now,latestRunStartedAt:now,
    latestRunCompletedAt:status==='completed'?DateTime.makeUnsafe(run==='user'?'2026-11-10T12:00:01.000Z':'2026-11-10T12:00:05.000Z'):null,
    archivedAt:null,settledOverride:null,settledAt:null,lastVisitedAt:null,deletedAt:null,
  };
}
function setShell(registry: ReturnType<typeof AtomRegistry.make>,value: ReturnType<typeof thread>) {
  registry.set(shellAtom,{status:'live',snapshot:Option.some({threads:[value]})});
}
const start = element('start') as HTMLButtonElement;
start.disabled=false; start.textContent='Start 25-second sequence';
element('environment').textContent=`${navigator.userAgent} | no device emulation | DPR ${devicePixelRatio} | viewport ${innerWidth}×${innerHeight} CSS px | notifications only | focus=false`;
start.onclick = () => {
  start.disabled=true; start.textContent='Sequence running';
  epoch=performance.now();
  const registry=AtomRegistry.make();
  setShell(registry,thread('user','running',false));
  log('SHELL user run RUNNING; Monitor absent');
  const stop=startThreadNotifications(registry,{state:{matches:[{params:{}}]},navigate:async()=>{}} as never);
  const clock=setInterval(()=>element('clock').textContent=`${((performance.now()-epoch)/1000).toFixed(1)} s`,100);
  const feed=(at:number,message:string,run:'user'|'wake',status:'running'|'completed',pending:boolean)=>setTimeout(()=>{
    log(message);element('status').textContent=`${run} ${status} / ${pending?'1 Monitor':'0 Monitors'}`;
    setShell(registry,thread(run,status,pending));
  },at);
  element('status').textContent='user running / 0 Monitors';
  feed(1000,'SHELL user run COMPLETED; expect one alert on both','user','completed',false);
  feed(3000,'SHELL wake run RUNNING; Monitor pending','wake','running',true);
  feed(5000,'SHELL wake run COMPLETED; Monitor still pending','wake','completed',true);
  feed(10000,'SHELL Monitor REMOVED; no following run; AFTER grace begins','wake','completed',false);
  feed(12000,'SHELL unchanged re-emit; same run and completion; deadline stays 15s','wake','completed',false);
  setTimeout(()=>{
    const times=notes.map(n=>n.elapsed);
    const expected=__SIDE__==='before'?[1,5]:[1,15];
    const pass=times.length===2&&times.every((t,i)=>Math.abs(t-expected[i]!)<0.75);
    log(`OBSERVATION END: ${notes.length} alerts; times ${times.map(t=>t.toFixed(3)+'s').join(', ')}; ${pass?'PASS':'FAIL'}`,pass?'pass':'alert');
    element('result').textContent=pass?'PASS — expected timings and exactly two total alerts':'FAIL — inspect recorded timestamps';
    element('result').className=pass?'pass':'alert';
    start.textContent='Observation complete';clearInterval(clock);element('clock').textContent='25.0 s';stop();registry.dispose();
    Object.assign(window,{__done:true,__pass:pass,__result:{side:__SIDE__,sha:__SHA__,notes,events,viewport:{width:innerWidth,height:innerHeight,dpr:devicePixelRatio},userAgent:navigator.userAgent}});
  },25000);
};
