"""Tests for CredentialPatternDetector (Priority #3, OWASP MCP01/ASI06)."""

import pytest
from insa_its.detectors.credential_pattern import CredentialPatternDetector


class TestInit:
    def test_creates_detector(self):
        d = CredentialPatternDetector()
        assert d.name == "credential_pattern"
        assert d.enabled is True

    def test_initial_state(self):
        d = CredentialPatternDetector()
        assert d._detection_count == 0
        assert len(d._seen_hashes) == 0


class TestAWSKeyDetection:
    def test_detects_aws_access_key(self):
        d = CredentialPatternDetector()
        result = d.check("Here is the key: AKIAIOSFODNN7EXAMPLE", 1)
        assert result["detected"] is True
        assert "aws_access_key" in result["unique_types"]
        assert result["severity"] == "critical"

    def test_detects_aws_secret_in_config(self):
        d = CredentialPatternDetector()
        result = d.check("aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY12", 1)
        assert result["detected"] is True
        assert "aws_secret_key" in result["unique_types"]


class TestGitHubTokenDetection:
    def test_detects_github_pat(self):
        d = CredentialPatternDetector()
        result = d.check("Token: ghp_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghij", 1)
        assert result["detected"] is True
        assert "github_token" in result["unique_types"]

    def test_detects_fine_grained_token(self):
        d = CredentialPatternDetector()
        result = d.check("github_pat_abcdefghijklmnopqrstuv12345678", 1)
        assert result["detected"] is True
        assert "github_fine_grained" in result["unique_types"]


class TestAPIKeyDetection:
    def test_detects_anthropic_key(self):
        d = CredentialPatternDetector()
        result = d.check("sk-ant-abcdefghijklmnopqrstuvwxyz1234567890abcdefgh", 1)
        assert result["detected"] is True
        assert "anthropic_api_key" in result["unique_types"]

    def test_detects_stripe_live_key(self):
        d = CredentialPatternDetector()
        result = d.check("sk_live_abcdefghijklmnopqrstuv", 1)
        assert result["detected"] is True
        assert "stripe_key" in result["unique_types"]

    def test_detects_slack_token(self):
        d = CredentialPatternDetector()
        # Use xoxr- prefix (rare) to avoid GitHub push protection on xoxb- tokens
        result = d.check("xoxr-FAKE00000000-TEST0000000000-000000000000000000000000", 1)
        assert result["detected"] is True
        assert "slack_token" in result["unique_types"]

    def test_detects_generic_api_key(self):
        d = CredentialPatternDetector()
        result = d.check('api_key = "a1b2c3d4e5f6g7h8i9j0k1l2m3"', 1)
        assert result["detected"] is True
        assert "generic_api_key" in result["unique_types"]

    def test_detects_google_api_key(self):
        d = CredentialPatternDetector()
        result = d.check("AIzaSyA1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6Q", 1)
        assert result["detected"] is True
        assert "google_api_key" in result["unique_types"]


class TestPIIDetection:
    def test_detects_email(self):
        d = CredentialPatternDetector()
        result = d.check("Contact john.doe@company.com for details", 1)
        assert result["detected"] is True
        assert "email_address" in result["unique_types"]

    def test_detects_ssn(self):
        d = CredentialPatternDetector()
        result = d.check("SSN: 123-45-6789", 1)
        assert result["detected"] is True
        assert "us_ssn" in result["unique_types"]
        assert result["severity"] == "critical"

    def test_detects_credit_card_visa(self):
        d = CredentialPatternDetector()
        result = d.check("Card: 4111111111111111", 1)
        assert result["detected"] is True
        assert "credit_card_visa" in result["unique_types"]

    def test_detects_credit_card_amex(self):
        d = CredentialPatternDetector()
        result = d.check("Amex: 371449635398431", 1)
        assert result["detected"] is True
        assert "credit_card_amex" in result["unique_types"]


class TestPrivateKeyDetection:
    def test_detects_rsa_private_key(self):
        d = CredentialPatternDetector()
        result = d.check("-----BEGIN RSA PRIVATE KEY-----\nMIIEpA...", 1)
        assert result["detected"] is True
        assert "private_key_rsa" in result["unique_types"]
        assert result["severity"] == "critical"

    def test_detects_openssh_key(self):
        d = CredentialPatternDetector()
        result = d.check("-----BEGIN OPENSSH PRIVATE KEY-----", 1)
        assert result["detected"] is True


class TestConnectionStringDetection:
    def test_detects_postgres_url(self):
        d = CredentialPatternDetector()
        result = d.check("postgres://user:password@host:5432/dbname", 1)
        assert result["detected"] is True
        assert "database_url" in result["unique_types"]

    def test_detects_mongodb_url(self):
        d = CredentialPatternDetector()
        result = d.check("mongodb://admin:secretpass@cluster0.mongodb.net/mydb", 1)
        assert result["detected"] is True


class TestCloudMetadataDetection:
    def test_detects_aws_metadata_ip(self):
        d = CredentialPatternDetector()
        result = d.check("Fetching from 169.254.169.254 for instance metadata", 1)
        assert result["detected"] is True
        assert "aws_metadata" in result["unique_types"]
        assert result["severity"] == "critical"

    def test_detects_metadata_url(self):
        d = CredentialPatternDetector()
        result = d.check("curl http://169.254.169.254/latest/meta-data/iam/", 1)
        assert result["detected"] is True


class TestJWTDetection:
    def test_detects_jwt(self):
        d = CredentialPatternDetector()
        jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U"
        result = d.check(f"Authorization: Bearer {jwt}", 1)
        assert result["detected"] is True


class TestAllowlist:
    def test_skips_placeholder_keys(self):
        d = CredentialPatternDetector()
        result = d.check("api_key = YOUR_API_KEY", 1)
        assert result["detected"] is False or "generic_api_key" not in result.get("unique_types", [])

    def test_skips_masked_values(self):
        d = CredentialPatternDetector()
        result = d.check("api_key = **********************", 1)
        assert result["detected"] is False or "generic_api_key" not in result.get("unique_types", [])


class TestCleanMessages:
    def test_normal_message_no_detection(self):
        d = CredentialPatternDetector()
        result = d.check("The quarterly report is ready for review.", 1)
        assert result["detected"] is False

    def test_code_without_secrets(self):
        d = CredentialPatternDetector()
        result = d.check("def process_order(order_id): return order_id * 2", 1)
        assert result["detected"] is False


class TestMultipleFindings:
    def test_multiple_credentials(self):
        d = CredentialPatternDetector()
        text = (
            "AWS key: AKIAIOSFODNN7EXAMPLE, "
            "Email: admin@corp.com, "
            "SSN: 123-45-6789"
        )
        result = d.check(text, 1)
        assert result["detected"] is True
        assert result["finding_count"] >= 3
        assert len(result["unique_types"]) >= 3


class TestHashingNeverRaw:
    def test_findings_contain_hash_not_raw(self):
        d = CredentialPatternDetector()
        secret = "AKIAIOSFODNN7EXAMPLE"
        result = d.check(f"Key: {secret}", 1)
        assert result["detected"] is True
        for finding in result["findings"]:
            assert "hash" in finding
            assert secret not in finding.get("hash", "")
            assert len(finding["hash"]) == 16  # Truncated SHA-256


class TestDuplicateTracking:
    def test_same_credential_tracked(self):
        d = CredentialPatternDetector()
        d.check("AKIAIOSFODNN7EXAMPLE", 1)
        result = d.check("AKIAIOSFODNN7EXAMPLE", 2)
        assert result["detected"] is True
        # Second occurrence should be marked as not new
        for f in result["findings"]:
            if f["type"] == "aws_access_key":
                assert f["is_new"] is False


class TestReset:
    def test_reset_clears_state(self):
        d = CredentialPatternDetector()
        d.check("AKIAIOSFODNN7EXAMPLE", 1)
        d.reset()
        assert d._detection_count == 0
        assert len(d._seen_hashes) == 0


class TestResultFormat:
    def test_result_has_required_fields(self):
        d = CredentialPatternDetector()
        result = d.check("Clean message", 1)
        assert "detected" in result
        assert "anomaly_type" in result
        assert "severity" in result
        assert "findings" in result
        assert "finding_count" in result
        assert "unique_types" in result
        assert "timestamp_us" in result
        assert result["anomaly_type"] == "CREDENTIAL_EXPOSURE"
