"""Test cases for license exception override mechanism."""

from datetime import datetime, timedelta
from pathlib import Path

import pytest
import tomllib


@pytest.mark.unit
def test_license_exception_validation() -> None:
    """Test that license exceptions are properly validated."""
    # This test validates the exception format and logic
    # The actual license check runs in the pipeline, so we test the data structures

    # Valid exception format (use a future date so the test doesn't rot)
    future_date = (datetime.now().date() + timedelta(days=180)).strftime("%Y-%m-%d")
    valid_exception = {
        "package": "test-package",
        "license": "GPL-2.0+",
        "justification": "Test dependency only",
        "approved_by": "security-team",
        "expires": future_date,
    }

    # Test all required fields are present
    required_fields = ["package", "license", "justification", "approved_by", "expires"]
    for field in required_fields:
        assert field in valid_exception, f"Missing required field: {field}"

    # Test date format validation
    try:
        expires = datetime.strptime(valid_exception["expires"], "%Y-%m-%d").date()
        assert expires > datetime.now().date(), "Exception should not be expired"
    except ValueError:
        pytest.fail("Invalid date format in exception")


@pytest.mark.unit
def test_pyproject_toml_license_compliance_section() -> None:
    """Test that pyproject.toml contains the license-compliance configuration."""
    pyproject_path = Path(__file__).parent.parent / "pyproject.toml"

    with open(pyproject_path, "rb") as f:
        data = tomllib.load(f)

    # Verify license-compliance section exists
    assert "tool" in data, "Missing [tool] section in pyproject.toml"
    assert "license-compliance" in data["tool"], "Missing [tool.license-compliance] section"

    license_config = data["tool"]["license-compliance"]
    assert "exceptions" in license_config, "Missing 'exceptions' key in license-compliance config"
    assert isinstance(license_config["exceptions"], list), "exceptions should be a list"


@pytest.mark.unit
def test_exception_expiration_scenarios() -> None:
    """Test different expiration date scenarios."""
    today = datetime.now().date()

    # Test cases for different expiration scenarios
    test_cases = [
        {
            "name": "valid_future_date",
            "expires": (today + timedelta(days=60)).strftime("%Y-%m-%d"),
            "expected_status": "valid",
        },
        {
            "name": "expires_soon",
            "expires": (today + timedelta(days=15)).strftime("%Y-%m-%d"),
            "expected_status": "warning",  # Should warn when < 30 days
        },
        {
            "name": "expired",
            "expires": (today - timedelta(days=1)).strftime("%Y-%m-%d"),
            "expected_status": "expired",
        },
        {
            "name": "invalid_format",
            "expires": "invalid-date",
            "expected_status": "invalid",
        },
    ]

    for case in test_cases:
        expires_str = case["expires"]

        if case["expected_status"] == "invalid":
            with pytest.raises(ValueError):
                datetime.strptime(expires_str, "%Y-%m-%d")
        else:
            try:
                expires = datetime.strptime(expires_str, "%Y-%m-%d").date()
                days_left = (expires - today).days

                if case["expected_status"] == "expired":
                    assert days_left < 0, f"Case {case['name']}: Should be expired"
                elif case["expected_status"] == "warning":
                    assert 0 <= days_left <= 30, f"Case {case['name']}: Should warn when < 30 days"
                elif case["expected_status"] == "valid":
                    assert days_left > 30, f"Case {case['name']}: Should be valid when > 30 days"

            except ValueError:
                assert case["expected_status"] == "invalid", (
                    f"Case {case['name']}: Unexpected ValueError"
                )


@pytest.mark.unit
def test_exception_field_validation() -> None:
    """Test validation of required exception fields."""
    base_exception = {
        "package": "test-package",
        "license": "GPL-2.0+",
        "justification": "Test dependency only",
        "approved_by": "security-team",
        "expires": "2025-12-31",
    }

    required_fields = ["package", "license", "justification", "approved_by", "expires"]

    # Test that missing any required field makes exception invalid
    for field in required_fields:
        incomplete_exception = base_exception.copy()
        del incomplete_exception[field]

        # Verify the field is missing (this simulates the pipeline validation)
        missing_fields = [f for f in required_fields if f not in incomplete_exception]
        assert field in missing_fields, f"Field {field} should be detected as missing"


@pytest.mark.unit
def test_exception_package_matching() -> None:
    """Test that package names in exceptions match exactly."""
    test_dependencies = [
        {"Name": "mysqlclient", "License": "GPL-2.0+"},
        {"Name": "pytest-postgresql", "License": "GPL-3.0"},
        {"Name": "some-other-package", "License": "GPL-2.0"},
    ]

    exceptions = {
        "mysqlclient": {
            "package": "mysqlclient",
            "license": "GPL-2.0+",
            "justification": "Internal dev tools only",
            "approved_by": "legal-team",
            "expires": "2025-12-31",
        }
    }

    # Test exact matching
    for dep in test_dependencies:
        dep_name = dep["Name"]

        has_exception = dep_name in exceptions

        if dep_name == "mysqlclient":
            assert has_exception, "mysqlclient should have an exception"
        else:
            assert not has_exception, f"{dep_name} should not have an exception"


@pytest.mark.integration
def test_pipeline_license_check_with_exceptions() -> None:
    """Integration test for license check with exceptions (requires pipeline environment)."""
    # This test would run in CI environment where the actual license check script executes
    # It validates end-to-end behavior but requires the pipeline context
    pytest.skip("Integration test - requires pipeline environment with license dependencies")


@pytest.mark.unit
def test_license_exception_audit_trail() -> None:
    """Test that exceptions provide proper audit trail information."""
    exception = {
        "package": "test-package",
        "license": "GPL-2.0+",
        "justification": "Used only in development environment for testing database connections",
        "approved_by": "security-team",
        "expires": "2025-12-31",
    }

    # Verify audit trail completeness
    assert len(exception["justification"]) > 20, "Justification should be detailed"
    assert exception["approved_by"], "Approved by field should not be empty"
    assert exception["expires"], "Expiration date should not be empty"

    # Verify justification contains meaningful information
    justification = exception["justification"].lower()
    meaningful_keywords = [
        "dev",
        "test",
        "internal",
        "tool",
        "environment",
        "temporary",
    ]
    has_meaningful_context = any(keyword in justification for keyword in meaningful_keywords)
    assert has_meaningful_context, "Justification should explain the business context"
