import json
import subprocess
from pathlib import Path


BOOTSTRAP = Path(__file__).parents[1] / "frontend" / "workspace-bootstrap.js"


def run_bootstrap(scenario: str) -> dict:
    harness = f"""
const loadWorkspace = require({json.dumps(str(BOOTSTRAP))});
(async()=>{{ {scenario} }})().catch(error=>{{console.error(error);process.exit(1);}});
"""
    completed = subprocess.run(
        ["node", "-e", harness], check=True, capture_output=True, text=True
    )
    return json.loads(completed.stdout)


def test_workspace_bootstrap_loads_content_addressed_feature_before_startup():
    result = run_bootstrap("""
const status={textContent:''};
const document={
  querySelector(selector) {
    if (selector === 'meta[name="stackchain-feature-today-timer"]') return {content:'feature-workspace-abc.js'};
    if (selector === '#my-work-action-status') return status;
    return null;
  }
};
let requested='';
const createLoader=options=>({load:async name=>{requested=name + ':' + options.urls[name];}});
await loadWorkspace({document,createLoader});
console.log(JSON.stringify({requested,status:status.textContent}));
""")
    assert result == {"requested": "today-timer:feature-workspace-abc.js", "status": ""}


def test_workspace_bootstrap_keeps_shell_and_announces_retry_when_feature_fails():
    result = run_bootstrap("""
const status={textContent:''};
const document={
  querySelector(selector) {
    if (selector === 'meta[name="stackchain-feature-today-timer"]') return {content:'feature-workspace-abc.js'};
    if (selector === '#my-work-action-status') return status;
    return null;
  }
};
const createLoader=()=>({load:async()=>{throw new Error('network failed');}});
let message='';
try { await loadWorkspace({document,createLoader}); } catch (error) { message=error.message; }
console.log(JSON.stringify({message,status:status.textContent}));
""")
    assert result == {
        "message": "network failed",
        "status": "Workspace could not load. Check your connection, then reload to retry.",
    }


def test_workspace_bootstrap_reloads_after_a_failed_offline_load_reconnects():
    result = run_bootstrap("""
const status={textContent:''}; const listeners={}; let reloads=0;
const document={querySelector(selector) {
  if (selector.startsWith('meta[')) return {content:'feature-workspace-abc.js'};
  if (selector === '#my-work-action-status') return status;
  return null;
}};
const window={
  location:{reload(){reloads++;}},
  addEventListener(name,callback) { listeners[name]=callback; },
  removeEventListener(name,callback) { if (listeners[name] === callback) delete listeners[name]; },
};
const createLoader=()=>({load:async()=>{throw new Error('offline');}});
try { await loadWorkspace({document,window,createLoader}); } catch (error) {}
const waiting=Boolean(listeners.online);
if (listeners.online) listeners.online();
console.log(JSON.stringify({waiting,reloads,status:status.textContent}));
""")
    assert result == {
        "waiting": True,
        "reloads": 1,
        "status": "Workspace could not load. Reconnect to retry automatically, or reload now.",
    }


def test_workspace_bootstrap_reloads_when_reconnect_arrives_before_load_failure():
    result = run_bootstrap("""
const status={textContent:''}; const listeners={}; let reloads=0;
const document={querySelector(selector) {
  if (selector.startsWith('meta[')) return {content:'feature-workspace-abc.js'};
  if (selector === '#my-work-action-status') return status;
  return null;
}};
const window={
  location:{reload(){reloads++;}},
  addEventListener(name,callback) { listeners[name]=callback; },
  removeEventListener(name,callback) { if (listeners[name] === callback) delete listeners[name]; },
};
const createLoader=()=>({load:async()=>{listeners.online(); throw new Error('offline request');}});
try { await loadWorkspace({document,window,createLoader}); } catch (error) {}
console.log(JSON.stringify({reloads,waiting:Boolean(listeners.online)}));
""")
    assert result == {"reloads": 1, "waiting": False}


def test_workspace_bootstrap_replays_online_event_after_dashboard_registers_handlers():
    result = run_bootstrap("""
const status={textContent:''}; const listeners={};
const document={querySelector(selector) {
  if (selector.startsWith('meta[')) return {content:'feature-workspace-abc.js'};
  if (selector === '#my-work-action-status') return status;
  return null;
}};
const window={
  addEventListener(name,callback) { listeners[name]=callback; },
  removeEventListener(name,callback) { if (listeners[name] === callback) delete listeners[name]; },
};
const createLoader=()=>({load:async()=>{listeners.online();}});
const lifecycle=await loadWorkspace({document,window,createLoader});
let reconnects=0;
lifecycle.replayOnline(()=>{reconnects++;});
lifecycle.replayOnline(()=>{reconnects++;});
console.log(JSON.stringify({reconnects,listening:Boolean(listeners.online)}));
""")
    assert result == {"reconnects": 1, "listening": False}