#!/usr/bin/env python3
"""Tests for cron-audit-662.py — Cron Fleet Audit."""

import json
import tempfile
from datetime import datetime, timezone, timedelta
from pathlib import Path
import pytest
import sys
sys.path.insert(0, str(Path(__file__).parent.parent / "scripts"))


class TestCrontabParsing:
    def test_standard_schedule(self):
        from cron_audit_662 import parse_crontab
        jobs = parse_crontab("*/15 * * * * /root/heartbeat.sh", source="test")
        assert len(jobs) == 1
        assert jobs[0]["schedule"] == "*/15 * * * *"
        assert jobs[0]["enabled"] is True

    def test_comment_name(self):
        from cron_audit_662 import parse_crontab
        jobs = parse_crontab("0 6 * * * /bin/backup.sh  # Morning Backup", source="test")
        assert "Morning Backup" in jobs[0]["name"]

    def test_reboot_entry(self):
        from cron_audit_662 import parse_crontab
        jobs = parse_crontab("@reboot /root/start.sh", source="test")
        assert len(jobs) == 1
        assert jobs[0]["schedule"] == "@reboot"

    def test_skips_comments(self):
        from cron_audit_662 import parse_crontab
        jobs = parse_crontab("# comment\n0 * * * * /bin/real.sh", source="test")
        assert len(jobs) == 1

    def test_multiple(self):
        from cron_audit_662 import parse_crontab
        jobs = parse_crontab("*/5 * * * * /bin/a.sh\n0 6 * * * /bin/b.sh # B\n@reboot /bin/c.sh", source="vps")
        assert len(jobs) == 3

    def test_source_tagged(self):
        from cron_audit_662 import parse_crontab
        jobs = parse_crontab("0 * * * * /bin/x.sh", source="allegro")
        assert "allegro" in jobs[0]["_source"]


class TestCategorizeJob:
    def test_ok_is_healthy(self):
        from cron_audit_662 import categorize_job
        now = datetime.now(timezone.utc)
        r = categorize_job({"name": "t", "last_status": "ok", "enabled": True, "state": "scheduled"}, now)
        assert r["category"] == "healthy"

    def test_recent_error_transient(self):
        from cron_audit_662 import categorize_job
        now = datetime.now(timezone.utc)
        r = categorize_job({"name": "t", "last_status": "error", "last_error": "fail",
                            "last_run_at": (now - timedelta(hours=2)).isoformat()}, now)
        assert r["category"] == "transient"

    def test_old_error_systemic(self):
        from cron_audit_662 import categorize_job
        now = datetime.now(timezone.utc)
        r = categorize_job({"name": "t", "last_status": "error", "last_error": "fail",
                            "last_run_at": (now - timedelta(hours=72)).isoformat()}, now)
        assert r["category"] == "systemic"

    def test_paused_healthy(self):
        from cron_audit_662 import categorize_job
        r = categorize_job({"name": "t", "state": "paused", "enabled": False}, datetime.now(timezone.utc))
        assert r["category"] == "healthy"


class TestAuditFleet:
    def test_empty(self):
        from cron_audit_662 import audit_fleet
        r = audit_fleet([], [])
        assert r["total_jobs"] == 0

    def test_mixed(self):
        from cron_audit_662 import audit_fleet, parse_crontab
        now = datetime.now(timezone.utc)
        hermes = [
            {"name": "good", "last_status": "ok", "enabled": True, "state": "scheduled"},
            {"name": "bad", "last_status": "error", "last_error": "fail",
             "last_run_at": (now - timedelta(hours=72)).isoformat()},
        ]
        crontab = parse_crontab("0 * * * * /bin/x.sh", source="vps")
        r = audit_fleet(hermes, crontab)
        assert r["total_jobs"] == 3
        assert r["hermes_jobs"] == 2
        assert r["crontab_jobs"] == 1
        assert len(r["systemic_jobs"]) == 1


class TestCrontabBackupLoading:
    def test_loads_directory(self, tmp_path):
        from cron_audit_662 import load_crontab_backups
        (tmp_path / "allegro-crontab-backup.txt").write_text("*/15 * * * * /root/hb.sh  # HB\n")
        (tmp_path / "ezra-crontab-backup.txt").write_text("0 6 * * * /root/rpt.sh\n")
        jobs = load_crontab_backups(tmp_path)
        assert len(jobs) == 2

    def test_empty_dir(self, tmp_path):
        from cron_audit_662 import load_crontab_backups
        assert load_crontab_backups(tmp_path) == []


class TestTimestampParsing:
    def test_iso_with_tz(self):
        from cron_audit_662 import parse_timestamp
        assert parse_timestamp("2026-04-14T15:30:00+00:00") is not None

    def test_empty(self):
        from cron_audit_662 import parse_timestamp
        assert parse_timestamp("") is None
        assert parse_timestamp(None) is None
