import json
import subprocess
from pathlib import Path


RECEIPT = Path(__file__).parents[1] / "frontend" / "issue-filing-receipt.js"
INDEX = Path(__file__).parents[1] / "frontend" / "index.html"
CSS = Path(__file__).parents[1] / "frontend" / "dashboard.css"
DASHBOARD = Path(__file__).parents[1] / "frontend" / "dashboard.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_confirmed_delegated_issue_opens_an_accessible_shareable_receipt():
    script = f"""
const createReceipt = require({json.dumps(str(RECEIPT))});
const element = () => ({{hidden:true,textContent:'',href:'',focused:false,focus(){{this.focused=true;}},addEventListener(name, fn){{this[name]=fn;}}}});
const elements = {{root:element(),heading:element(),key:element(),title:element(),ownership:element(),openLink:element(),shareButton:element(),fileAnotherButton:element(),doneButton:element(),status:element()}};
const controller = createReceipt({{...elements,navigator:{{share:async payload=>{{elements.shared=payload;}}}}}});
controller.show({{repository:'stackchain/dashboard',number:866,title:'Finish the filing journey',assignees:['alex'],url:'https://forge.example/git/stackchain/dashboard/issues/866'}}, elements.doneButton);
(async()=>{{await elements.shareButton.click();process.stdout.write(JSON.stringify({{
  hidden:elements.root.hidden,key:elements.key.textContent,title:elements.title.textContent,
  ownership:elements.ownership.textContent,href:elements.openLink.href,focused:elements.heading.focused,
  shared:elements.shared,
}}));}})();
"""
    output = run_node(script)

    assert output == {
        "hidden": False,
        "key": "stackchain/dashboard#866",
        "title": "Finish the filing journey",
        "ownership": "Assigned to @alex.",
        "href": "https://forge.example/git/stackchain/dashboard/issues/866",
        "focused": True,
        "shared": {
            "title": "stackchain/dashboard#866 · Finish the filing journey",
            "text": "Finish the filing journey",
            "url": "https://forge.example/git/stackchain/dashboard/issues/866",
        },
    }


def test_unassigned_receipt_copies_link_and_escape_restores_launch_focus():
    script = f"""
const createReceipt = require({json.dumps(str(RECEIPT))});
const element = () => ({{hidden:true,textContent:'',href:'',focusCount:0,focus(){{this.focusCount++;}},addEventListener(name, fn){{this[name]=fn;}}}});
const elements = {{root:element(),heading:element(),key:element(),title:element(),ownership:element(),openLink:element(),shareButton:element(),fileAnotherButton:element(),doneButton:element(),status:element()}};
const copied=[];const launcher=element();
const controller=createReceipt({{...elements,navigator:{{}},clipboard:{{writeText:async value=>copied.push(value)}}}});
controller.show({{repository:'stackchain/dashboard',number:867,title:'Unowned follow-up',assignees:[],url:'https://forge.example/git/stackchain/dashboard/issues/867'}},launcher);
(async()=>{{await elements.shareButton.click();elements.root.keydown({{key:'Escape',preventDefault(){{elements.prevented=true;}}}});process.stdout.write(JSON.stringify({{
  ownership:elements.ownership.textContent,copied,status:elements.status.textContent,hidden:elements.root.hidden,
  restored:launcher.focusCount,prevented:elements.prevented,
}}));}})();
"""
    output = run_node(script)

    assert output == {
        "ownership": "Created with no owner.",
        "copied": ["https://forge.example/git/stackchain/dashboard/issues/867"],
        "status": "Issue link copied.",
        "hidden": True,
        "restored": 1,
        "prevented": True,
    }


def test_related_action_returns_only_the_confirmed_reusable_plan():
    script = f"""
const createReceipt = require({json.dumps(str(RECEIPT))});
const element = () => ({{hidden:true,focusCount:0,focus(){{this.focusCount++;}},addEventListener(name, fn){{this[name]=fn;}}}});
const elements = {{root:element(),heading:element(),key:element(),title:element(),ownership:element(),openLink:element(),shareButton:element(),relatedButton:element(),fileAnotherButton:element(),doneButton:element(),status:element()}};
const plans=[];
const controller=createReceipt({{...elements,onFileRelated:plan=>plans.push(plan)}});
const plan={{repository:'stackchain/dashboard',title:'',body:'## Bug',labelIds:[7],templateId:'bug.yml'}};
controller.show({{repository:'stackchain/dashboard',number:868,title:'Filed',assignees:[],url:'https://forge.example/issues/868'}},elements.doneButton,plan);
elements.relatedButton.click();
process.stdout.write(JSON.stringify({{plans,hidden:elements.root.hidden,restored:elements.doneButton.focusCount}}));
"""
    output = run_node(script)

    assert output == {"plans": [{
        "repository": "stackchain/dashboard", "title": "", "body": "## Bug",
        "labelIds": [7], "templateId": "bug.yml",
    }], "hidden": True, "restored": 1}


def test_view_in_filed_closes_receipt_and_routes_the_exact_confirmed_issue():
    script = f"""
const createReceipt = require({json.dumps(str(RECEIPT))});
const element = () => ({{hidden:true,focusCount:0,focus(){{this.focusCount++;}},addEventListener(name, fn){{this[name]=fn;}}}});
const elements = {{root:element(),heading:element(),key:element(),title:element(),ownership:element(),openLink:element(),shareButton:element(),filedButton:element(),fileAnotherButton:element(),doneButton:element(),status:element()}};
const filed=[];
const controller=createReceipt({{...elements,onViewFiled:issue=>filed.push(issue)}});
controller.show({{repository:'stackchain/dashboard',number:870,title:'Delegated',assignees:['alex'],url:'https://forge.example/issues/870'}},elements.doneButton);
elements.filedButton.click();
process.stdout.write(JSON.stringify({{filed,hidden:elements.root.hidden,restored:elements.doneButton.focusCount}}));
"""
    output = run_node(script)
    assert output == {
        "filed": [{"repository": "stackchain/dashboard", "number": 870, "title": "Delegated", "assignees": ["alex"], "url": "https://forge.example/issues/870"}],
        "hidden": True, "restored": 1,
    }


def test_mobile_shell_wires_confirmed_non_my_work_issues_to_the_receipt():
    index = INDEX.read_text()
    css = CSS.read_text()
    dashboard = DASHBOARD.read_text()

    assert 'id="issue-filing-receipt" role="dialog" aria-modal="true"' in index
    assert 'id="issue-filing-receipt-heading"' in index
    assert 'id="issue-filing-receipt-open"' in index
    assert 'id="issue-filing-receipt-filed"' in index
    assert 'id="issue-filing-receipt-share"' in index
    assert 'id="issue-filing-receipt-related"' in index
    assert 'id="issue-filing-receipt-another"' in index
    assert 'id="issue-filing-receipt-done"' in index
    assert '<script src="static/issue-filing-receipt.js"></script>' in index
    assert '.issue-filing-receipt-panel' in css
    assert 'padding-bottom:calc(18px + env(safe-area-inset-bottom))' in css
    assert '.issue-filing-receipt-actions' in css
    assert 'min-height:44px' in css
    assert 'createIssueFilingReceipt({' in dashboard
    assert "filedButton:qs('#issue-filing-receipt-filed')" in dashboard
    assert 'onViewFiled:issue =>' in dashboard
    assert "is_filed:true, is_assigned:(issue.assignees || []).includes(confirmedOwnerLogin)" in dashboard
    assert "confirmed.work_reasons = ['created_by_me']" in dashboard
    assert "relatedButton:qs('#issue-filing-receipt-related')" in dashboard
    assert 'relatedDraft:issueCapture.buildRelatedDraft(durableDraft)' in dashboard
    assert "issueCapture.saveDraft(plan)" in dashboard
    assert "issueFilingReceipt.show(confirmed, qs('#new-issue'), filing?.relatedDraft)" in dashboard
