"""Tests for the expanded GET /tests filters and the new GET /tests/count.

Block: Validated Tests page couldn't show a true total once there were
more than `limit` (max 200) matching tests, and had no server-side way to
filter by technique/platform/date/outcome beyond a client-side name search.
count_tests() shares its query-building with list_tests() (_build_test_query)
so the two can't silently drift out of sync.
"""

from datetime import datetime, timedelta

from app.models.enums import AttackSuccessResult, TestResult, TestState
from app.models.technique import Technique
from app.models.test import Test
from app.services.test_crud_service import count_tests, list_tests


def _seed(db, owner_id, *, mitre_id, name, technique_name=None, state=TestState.validated, **overrides):
    tech = Technique(mitre_id=mitre_id, name=technique_name or f"Technique {mitre_id}", tactic="execution", platforms=["windows"])
    db.add(tech)
    db.flush()
    test = Test(technique_id=tech.id, name=name, state=state, created_by=owner_id, **overrides)
    db.add(test)
    db.commit()
    db.refresh(test)
    return test


def test_count_tests_matches_list_tests_total_beyond_page_size(db, red_lead_user):
    for i in range(5):
        _seed(db, red_lead_user.id, mitre_id=f"T900{i}", name=f"Validated {i}")

    total = count_tests(db, state="validated")
    page = list_tests(db, state="validated", limit=2)

    assert total == 5
    assert len(page) == 2


def test_technique_search_matches_mitre_id_or_name(db, red_lead_user):
    _seed(db, red_lead_user.id, mitre_id="T1059.001", name="PowerShell test", technique_name="Command Line Interface")
    _seed(db, red_lead_user.id, mitre_id="T1055", name="Process Injection test", technique_name="Process Injection")

    by_id = list_tests(db, technique_search="T1059")
    by_name = list_tests(db, technique_search="injection")

    assert [t.name for t in by_id] == ["PowerShell test"]
    assert [t.name for t in by_name] == ["Process Injection test"]


def test_attack_success_and_detection_result_filters(db, red_lead_user):
    _seed(
        db, red_lead_user.id, mitre_id="T9010", name="Successful and detected",
        attack_success=AttackSuccessResult.successful, detection_result=TestResult.detected,
    )
    _seed(
        db, red_lead_user.id, mitre_id="T9011", name="Successful and not detected",
        attack_success=AttackSuccessResult.successful, detection_result=TestResult.not_detected,
    )

    results = list_tests(db, attack_success="successful", detection_result="detected")

    assert [t.name for t in results] == ["Successful and detected"]


def test_validated_date_range_filter(db, red_lead_user):
    old = _seed(db, red_lead_user.id, mitre_id="T9020", name="Old validation")
    old.blue_validated_at = datetime.utcnow() - timedelta(days=30)
    recent = _seed(db, red_lead_user.id, mitre_id="T9021", name="Recent validation")
    recent.blue_validated_at = datetime.utcnow() - timedelta(days=1)
    db.commit()

    results = list_tests(db, validated_from=datetime.utcnow() - timedelta(days=7))

    assert [t.name for t in results] == ["Recent validation"]


def test_count_tests_endpoint_returns_true_total(api, db, red_lead_user, auth_headers):
    for i in range(3):
        _seed(db, red_lead_user.id, mitre_id=f"T903{i}", name=f"Counted {i}")

    resp = api("get", "/api/v1/tests/count?state=validated", auth_headers)

    assert resp.status_code == 200
    assert resp.json()["total"] == 3
