from __future__ import annotations

import os
import sys
import time
import pytest
from pathlib import Path

# Add src/ to path
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))

import metrics


def test_collect_cpu():
    res = metrics.collect_cpu()
    assert "usage_percent" in res
    assert "cores" in res
    assert "load_average" in res
    assert "steal_percent" in res
    assert "iowait_percent" in res
    assert isinstance(res["usage_percent"], float)
    assert isinstance(res["cores"], int)
    assert isinstance(res["load_average"], list)


def test_collect_ram():
    res = metrics.collect_ram()
    assert "total" in res
    assert "used" in res
    assert "free" in res
    assert "cached" in res
    assert "buffers" in res
    assert "swap" in res
    assert isinstance(res["swap"], dict)
    assert "total" in res["swap"]


def test_collect_disk():
    res = metrics.collect_disk()
    assert isinstance(res, list)
    if res:
        item = res[0]
        assert "mount_point" in item
        assert "total" in item
        assert "used" in item
        assert "free" in item
        assert "inodes_total" in item


def test_collect_network():
    res = metrics.collect_network()
    assert isinstance(res, list)
    if res:
        item = res[0]
        assert "interface" in item
        assert "rx_bytes" in item
        assert "tx_bytes" in item
        assert "rx_rate_bps" in item


def test_collect_process():
    res = metrics.collect_process()
    assert "top_cpu" in res
    assert "top_ram" in res
    assert isinstance(res["top_cpu"], list)
    assert isinstance(res["top_ram"], list)
    if res["top_cpu"]:
        proc = res["top_cpu"][0]
        assert "pid" in proc
        assert "name" in proc
        assert "cpu" in proc
        assert "ram" in proc


def test_collect_services():
    res = metrics.collect_services()
    assert isinstance(res, dict)
    assert "nginx" in res
    assert "mysql" in res


def test_collect_docker():
    res = metrics.collect_docker()
    assert isinstance(res, list)


def test_collect_ssl():
    res = metrics.collect_ssl()
    assert isinstance(res, list)


def test_collect_all():
    res = metrics.collect_all(timeout=2.0)
    for key in ("cpu", "ram", "disk", "network", "process", "services", "docker", "ssl", "disk_io", "uptime"):
        assert key in res


def test_caching_and_updater():
    # Test that caching works and background updater launches/stops safely
    metrics.start_updater(interval=1)
    time.sleep(0.2)
    m = metrics.get_metrics()
    assert m  # Should not be empty
    assert "cpu" in m
    metrics.stop_updater()


def test_sanitize_cmdline():
    assert metrics.sanitize_cmdline("mysql -u root -pSecret123") == "mysql -u root -p***"
    assert metrics.sanitize_cmdline("mysql -u root --password=Secret123") == "mysql -u root --password=***"
    assert metrics.sanitize_cmdline("python app.py --token 123456") == "python app.py --token ***"
    assert metrics.sanitize_cmdline("curl -H 'Authorization: Bearer my-token'") == "curl -H 'Authorization: Bearer ***'"
    assert metrics.sanitize_cmdline("cmd --pwd=123 --secret:456") == "cmd --pwd=*** --secret:***"
    assert metrics.sanitize_cmdline("") == ""


def test_slow_collectors_caching_ttl():
    # Cache initially empty
    metrics._docker_cache_data = None
    metrics._docker_cache_time = 0.0
    
    # Run once
    res1 = metrics.collect_docker()
    
    # Store dummy data in cache to verify it is returned within TTL
    dummy = [{"id": "dummy_cid", "name": "dummy_container", "status": "running"}]
    metrics._docker_cache_data = dummy
    metrics._docker_cache_time = time.time()
    
    res2 = metrics.collect_docker()
    assert res2 == dummy  # Returned from cache within TTL
    
    # Cache initially empty for SSL
    metrics._ssl_cache_data = None
    metrics._ssl_cache_time = 0.0
    
    res3 = metrics.collect_ssl()
    dummy_ssl = [{"path": "/etc/ssl/certs/dummy.pem", "expire": None, "issuer": "dummy"}]
    metrics._ssl_cache_data = dummy_ssl
    metrics._ssl_cache_time = time.time()
    
    res4 = metrics.collect_ssl()
    assert res4 == dummy_ssl
