"""Tests for issue #1140 — Cron completion badge per-job indicator.

Verifies that:
1. _cronNewJobIds tracks job IDs with new completions
2. loadCrons() renders a dot indicator for new-run jobs
3. openCronDetail() clears the unread state for the viewed job
4. Badge only clears when all unread jobs are viewed (not on panel open)
5. _renderCronDetail() adds has-new-run class to Last Output card
"""

import pytest

# ── Static file tests (no server needed) ──

def test_cron_new_job_ids_tracking_in_panels_js():
    """panels.js should declare _cronNewJobIds Set and populate it in startCronPolling."""
    with open('static/panels.js') as f:
        src = f.read()

    # _cronNewJobIds declared as Set
    assert '_cronNewJobIds' in src, '_cronNewJobIds not found in panels.js'
    assert 'new Set()' in src, '_cronNewJobIds should be initialized as Set()'

    # In startCronPolling, job IDs are added to the set
    assert '_cronNewJobIds.add(String(c.job_id))' in src, \
        'startCronPolling should add job_id to _cronNewJobIds'


def test_cron_dot_indicator_rendered_in_load_crons():
    """loadCrons() should render a .cron-new-dot for jobs in _cronNewJobIds."""
    with open('static/panels.js') as f:
        src = f.read()

    # Dot indicator in cron-item rendering
    assert 'cron-new-dot' in src, 'cron-new-dot class not found'
    assert "_cronNewJobIds.has(String(job.id))" in src, \
        'loadCrons should check _cronNewJobIds for each job'


def test_open_cron_detail_clears_unread():
    """openCronDetail() should mark job as read and remove the dot."""
    with open('static/panels.js') as f:
        src = f.read()

    # _clearCronUnreadForJob called in openCronDetail
    assert '_clearCronUnreadForJob' in src, \
        '_clearCronUnreadForJob function not found'
    # Dot removal in openCronDetail
    assert "target.querySelector('.cron-new-dot')" in src, \
        'openCronDetail should remove the dot element'


def test_clear_cron_unread_for_job_function():
    """_clearCronUnreadForJob should delete from set and refresh badge.

    _cronUnreadCount is derived from _cronNewJobIds.size in updateCronBadge,
    so the function only needs to delete from the set and trigger a badge sync.
    """
    with open('static/panels.js') as f:
        src = f.read()

    # Locate the function body to make assertions order-dependent
    start = src.find('function _clearCronUnreadForJob(')
    assert start != -1, '_clearCronUnreadForJob should be defined'
    body = src[start:start + 400]
    assert '_cronNewJobIds.delete(id)' in body, \
        '_clearCronUnreadForJob should delete from _cronNewJobIds'
    assert 'updateCronBadge()' in body, \
        '_clearCronUnreadForJob should call updateCronBadge to re-sync count'


def test_switch_panel_no_longer_clears_badge():
    """switchPanel override should NOT clear badge on tasks panel open."""
    with open('static/panels.js') as f:
        src = f.read()

    # The old pattern "if(name==='tasks'){_cronUnreadCount=0" should NOT exist
    assert "if(name==='tasks'){_cronUnreadCount=0" not in src, \
        'switchPanel should NOT clear _cronUnreadCount on tasks open'


def test_has_new_run_class_in_render_detail():
    """_renderCronDetail() should add has-new-run class to Last Output card."""
    with open('static/panels.js') as f:
        src = f.read()

    # Check has-new-run class in the cronDetailRuns div
    assert 'has-new-run' in src, 'has-new-run class not found'


def test_cron_css_classes_exist():
    """style.css should contain .cron-new-dot and .has-new-run styles."""
    with open('static/style.css') as f:
        src = f.read()

    assert '.cron-new-dot{' in src, '.cron-new-dot CSS rule not found'
    assert '.has-new-run{' in src, '.has-new-run CSS rule not found'
    assert 'cron-dot-pulse' in src, 'cron-dot-pulse animation not found'


