import json
import subprocess
from pathlib import Path


ROOT = Path(__file__).parents[1]
PROTECT_TODAY = ROOT / "frontend" / "protect-today.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_protect_today_prioritizes_and_deduplicates_urgent_deadlines_before_existing_plan():
    script = f"""
const protectToday = require({json.dumps(str(PROTECT_TODAY))});
const issue = (number, group, due) => ({{
  kind:'issue', repository:'stackchain/dashboard', number, title:'Issue ' + number,
  is_assigned:true, state:'open', agenda_group:group, due_date:due,
}});
const urgentLater = issue(3, 'Today', '2026-08-13');
const urgentFirst = issue(2, 'Overdue', '2026-08-12');
const duplicate = issue(2, 'Overdue', '2026-08-12');
const existingUrgent = issue(1, 'Today', '2026-08-13');
const existingNormal = issue(8, null, null);
const result = protectToday.propose({{
  agenda:[urgentLater, duplicate, urgentFirst, issue(4, 'Tomorrow', '2026-08-14')],
  today:[existingNormal, existingUrgent],
  identity:item => item.repository + '#' + item.number,
  limit:5,
}});
process.stdout.write(JSON.stringify({{
  selected:result.selected.map(item => item.number),
  protected:result.protected.map(item => item.number),
  displaced:result.displaced.map(item => item.number),
  summary:result.summary,
}}));
"""
    assert run_node(script) == {
        "selected": [2, 1, 3, 8],
        "protected": [2, 1, 3],
        "displaced": [],
        "summary": "3 urgent items protected · 0 displaced",
    }


def test_protect_today_reports_existing_work_displaced_by_five_item_limit():
    script = f"""
const protectToday = require({json.dumps(str(PROTECT_TODAY))});
const issue = (number, group = null) => ({{
  kind:'issue', repository:'stackchain/dashboard', number, title:'Issue ' + number,
  is_assigned:true, state:'open', agenda_group:group,
  due_date:group === 'Overdue' ? '2026-08-12' : group === 'Today' ? '2026-08-13' : null,
}});
const result = protectToday.propose({{
  agenda:[issue(10, 'Overdue'), issue(11, 'Today'), issue(12, 'Today')],
  today:[issue(1), issue(2), issue(3), issue(4), issue(5)],
  identity:item => item.repository + '#' + item.number,
  limit:5,
}});
process.stdout.write(JSON.stringify({{
  selected:result.selected.map(item => item.number),
  displaced:result.displaced.map(item => item.number),
  summary:result.summary,
}}));
"""
    assert run_node(script) == {
        "selected": [10, 11, 12, 1, 2],
        "displaced": [3, 4, 5],
        "summary": "3 urgent items protected · 3 displaced for review",
    }


def test_protect_today_excludes_closed_unassigned_and_nonurgent_items():
    script = f"""
const protectToday = require({json.dumps(str(PROTECT_TODAY))});
const items = [
  {{kind:'issue',repository:'r',number:1,is_assigned:true,state:'closed',agenda_group:'Overdue',due_date:'2026-08-01'}},
  {{kind:'issue',repository:'r',number:2,is_assigned:false,state:'open',agenda_group:'Today',due_date:'2026-08-13'}},
  {{kind:'issue',repository:'r',number:3,is_assigned:true,state:'open',agenda_group:'Tomorrow',due_date:'2026-08-14'}},
  {{kind:'pull',repository:'r',number:4,is_assigned:true,state:'open',agenda_group:'Overdue',due_date:'2026-08-01'}},
];
const result = protectToday.propose({{agenda:items,today:[],identity:item => item.repository + '#' + item.number}});
process.stdout.write(JSON.stringify(result));
"""
    assert run_node(script) == {
        "selected": [], "protected": [], "displaced": [],
        "summary": "No overdue or due-today work needs protection.",
    }


def test_dashboard_renders_mobile_protect_today_entrypoint_and_preview_context():
    html = (ROOT / "frontend" / "index.html").read_text()
    dashboard = (ROOT / "frontend" / "dashboard.js").read_text()
    css = (ROOT / "frontend" / "dashboard.css").read_text()
    bundle = (ROOT / "src" / "frontend_bundle.py").read_text()

    assert 'id="protect-today"' in html
    assert 'id="protect-today-status"' in html
    assert "protectToday.propose" in dashboard
    assert "pendingProtectToday" in dashboard
    assert "Protect Today" in dashboard
    assert ".protect-today" in css
    assert "min-height:44px" in css.replace(" ", "")
    assert '"static/protect-today.js"' in bundle
