from __future__ import annotations

import json
import subprocess
from pathlib import Path


MODULE = Path(__file__).parents[1] / "frontend" / "create-issue-sheet.js"


def run_node(script: str) -> dict:
    result = subprocess.run(
        ["node", "-e", script],
        check=True,
        capture_output=True,
        text=True,
    )
    return json.loads(result.stdout)


def test_issue_capture_modal_inerts_background_focuses_cancel_and_restores_exact_launcher():
    result = run_node(
        f"""
const createIssueCapture = require({json.dumps(str(MODULE))});
function element(id) {{
  return {{id, inert:false, hidden:false, disabled:false, isConnected:true,
    focus() {{ document.activeElement = this; }},
    getClientRects() {{ return [{{}}]; }} }};
}}
const launcher = element('mobile-new');
const cancel = element('cancel-new-issue');
const title = element('create-issue-title');
const panel = {{...element('create-issue-panel'), scrollTop:420}};
const background = [element('header'), element('main'), element('mobile-task-dock')];
const root = {{
  querySelector: selector => selector === '#cancel-new-issue' ? cancel :
    (selector === '.create-issue-panel' ? panel : null),
  querySelectorAll: () => [cancel, title],
  addEventListener() {{}}, removeEventListener() {{}},
}};
const document = {{activeElement: launcher}};
const lifecycle = createIssueCapture.createModalLifecycle({{
  root, background, document, requestClose() {{}},
}});
lifecycle.open(launcher);
const opened = {{active:document.activeElement.id, inert:background.map(item => item.inert)}};
lifecycle.close();
process.stdout.write(JSON.stringify({{
  opened, closed:{{active:document.activeElement.id, inert:background.map(item => item.inert), scrollTop:panel.scrollTop}}
}}));
"""
    )

    assert result == {
        "opened": {"active": "cancel-new-issue", "inert": [True, True, True]},
        "closed": {"active": "mobile-new", "inert": [False, False, False], "scrollTop": 0},
    }


def test_issue_capture_modal_wraps_visible_focus_and_escape_uses_close_request():
    result = run_node(
        f"""
const createIssueCapture = require({json.dumps(str(MODULE))});
function element(id, visible=true) {{
  return {{id, inert:false, hidden:!visible, disabled:false, isConnected:true,
    focus() {{ document.activeElement = this; }},
    getClientRects() {{ return visible ? [{{}}] : []; }} }};
}}
const launcher = element('empty-work-create');
const cancel = element('cancel-new-issue');
const hidden = element('hidden-control', false);
const submit = element('submit-new-issue');
const listeners = {{}};
const root = {{
  querySelector: selector => selector === '#cancel-new-issue' ? cancel : null,
  querySelectorAll: () => [cancel, hidden, submit],
  addEventListener: (name, callback) => {{ listeners[name] = callback; }},
  removeEventListener() {{}},
}};
const document = {{activeElement: launcher}};
let closes = 0;
const lifecycle = createIssueCapture.createModalLifecycle({{
  root, background:[], document, requestClose() {{ closes += 1; }},
}});
lifecycle.open(launcher);
document.activeElement = submit;
let prevented = 0;
listeners.keydown({{key:'Tab', shiftKey:false, preventDefault() {{ prevented += 1; }}}});
const wrappedForward = document.activeElement.id;
document.activeElement = cancel;
listeners.keydown({{key:'Tab', shiftKey:true, preventDefault() {{ prevented += 1; }}}});
const wrappedBackward = document.activeElement.id;
listeners.keydown({{key:'Escape', shiftKey:false, preventDefault() {{ prevented += 1; }}}});
process.stdout.write(JSON.stringify({{wrappedForward, wrappedBackward, closes, prevented}}));
"""
    )

    assert result == {
        "wrappedForward": "cancel-new-issue",
        "wrappedBackward": "submit-new-issue",
        "closes": 1,
        "prevented": 3,
    }
