"""
Test suite for validation utility functions.
"""

import pytest
from markitect_utils.validation_utils import (
    is_valid_email,
    is_valid_url,
    is_valid_semver,
    validate_required_fields,
)


class TestIsValidEmail:
    """Test cases for the is_valid_email function."""

    def test_valid_emails(self):
        """Test valid email addresses."""
        valid_emails = [
            "user@example.com",
            "test.email@domain.co.uk",
            "user+tag@example.org",
            "user123@test-domain.com",
            "a@b.co",
        ]
        for email in valid_emails:
            assert is_valid_email(email) is True, f"Failed for: {email}"

    def test_invalid_emails(self):
        """Test invalid email addresses."""
        invalid_emails = [
            "invalid.email",
            "@example.com",
            "user@",
            "user@.com",
            "user space@example.com",
            "user@domain",
            "user@@example.com",
            "",
        ]
        for email in invalid_emails:
            assert is_valid_email(email) is False, f"Should be invalid: {email}"

    def test_edge_cases(self):
        """Test edge cases."""
        assert is_valid_email(None) is False
        assert is_valid_email(123) is False
        assert is_valid_email([]) is False


class TestIsValidUrl:
    """Test cases for the is_valid_url function."""

    def test_valid_urls(self):
        """Test valid URLs."""
        valid_urls = [
            "https://example.com",
            "http://test.org",
            "https://sub.domain.com/path",
            "http://localhost:8000",
            "https://example.com/path?query=value",
            "http://192.168.1.1:3000",
        ]
        for url in valid_urls:
            assert is_valid_url(url) is True, f"Failed for: {url}"

    def test_invalid_urls(self):
        """Test invalid URLs."""
        invalid_urls = [
            "not-a-url",
            "ftp://example.com",
            "example.com",
            "://example.com",
            "https://",
            "http://.com",
            "",
        ]
        for url in invalid_urls:
            assert is_valid_url(url) is False, f"Should be invalid: {url}"

    def test_edge_cases(self):
        """Test edge cases."""
        assert is_valid_url(None) is False
        assert is_valid_url(123) is False
        assert is_valid_url([]) is False


class TestIsValidSemver:
    """Test cases for the is_valid_semver function."""

    def test_valid_versions(self):
        """Test valid semantic versions."""
        valid_versions = [
            "1.0.0",
            "0.1.0",
            "10.20.30",
            "1.0.0-alpha",
            "1.0.0-alpha.1",
            "1.0.0-0.3.7",
            "1.0.0-x.7.z.92",
            "1.0.0+20130313144700",
            "1.0.0-beta+exp.sha.5114f85",
        ]
        for version in valid_versions:
            assert is_valid_semver(version) is True, f"Failed for: {version}"

    def test_invalid_versions(self):
        """Test invalid semantic versions."""
        invalid_versions = [
            "1.0",
            "1.0.0-",
            "1.0.0+",
            "01.0.0",
            "1.01.0",
            "1.0.01",
            "1.0.0-",
            "1.0.0+",
            "v1.0.0",
            "",
        ]
        for version in invalid_versions:
            assert is_valid_semver(version) is False, f"Should be invalid: {version}"

    def test_edge_cases(self):
        """Test edge cases."""
        assert is_valid_semver(None) is False
        assert is_valid_semver(123) is False
        assert is_valid_semver([]) is False


class TestValidateRequiredFields:
    """Test cases for the validate_required_fields function."""

    def test_all_fields_present(self):
        """Test when all required fields are present and valid."""
        data = {
            "name": "John Doe",
            "email": "john@example.com",
            "age": 30
        }
        required = ["name", "email", "age"]
        result = validate_required_fields(data, required)

        assert result == {"missing": [], "empty": []}

    def test_missing_fields(self):
        """Test when some fields are missing."""
        data = {
            "name": "John Doe",
            "email": "john@example.com"
        }
        required = ["name", "email", "age", "phone"]
        result = validate_required_fields(data, required)

        assert set(result["missing"]) == {"age", "phone"}
        assert result["empty"] == []

    def test_empty_fields(self):
        """Test when some fields are empty."""
        data = {
            "name": "John Doe",
            "email": "",
            "age": 30,
            "phone": "   "  # whitespace only
        }
        required = ["name", "email", "age", "phone"]
        result = validate_required_fields(data, required)

        assert result["missing"] == []
        assert set(result["empty"]) == {"email", "phone"}

    def test_mixed_issues(self):
        """Test when there are both missing and empty fields."""
        data = {
            "name": "John Doe",
            "email": "",
        }
        required = ["name", "email", "age", "phone"]
        result = validate_required_fields(data, required)

        assert set(result["missing"]) == {"age", "phone"}
        assert result["empty"] == ["email"]

    def test_non_string_values(self):
        """Test with non-string values."""
        data = {
            "name": "John Doe",
            "age": 0,  # Zero should not be considered empty
            "active": False,  # False should not be considered empty
            "score": None,  # None should be considered empty
            "items": [],  # Empty list should be considered empty
        }
        required = ["name", "age", "active", "score", "items"]
        result = validate_required_fields(data, required)

        assert result["missing"] == []
        assert set(result["empty"]) == {"score", "items"}

    def test_edge_cases(self):
        """Test edge cases."""
        # Invalid inputs
        result = validate_required_fields("not a dict", ["field"])
        assert result == {"missing": [], "empty": []}

        result = validate_required_fields({}, "not a list")
        assert result == {"missing": [], "empty": []}

        # Empty data and requirements
        result = validate_required_fields({}, [])
        assert result == {"missing": [], "empty": []}

        # Empty requirements
        data = {"name": "John"}
        result = validate_required_fields(data, [])
        assert result == {"missing": [], "empty": []}