"""Unit tests for validation pipeline"""

import pytest
from dss.models.project import Project
from dss.models.theme import Theme, DesignToken, TokenCategory
from dss.validators.schema import ProjectValidator, ValidationError, ValidationStage


@pytest.mark.unit
class TestProjectValidator:
    """Test project validation pipeline"""

    def test_validate_valid_project(self, valid_project_data):
        """Test validation passes for valid project"""
        validator = ProjectValidator()
        result = validator.validate(valid_project_data)

        assert result.is_valid is True
        assert len(result.errors) == 0
        assert result.stage == ValidationStage.COMPLETE

    def test_validate_missing_required_field(self):
        """Test validation fails when required field is missing"""
        invalid_data = {
            "name": "Test Project",
            # Missing 'id' field
            "theme": {
                "name": "Test Theme",
                "tokens": {}
            }
        }

        validator = ProjectValidator()
        result = validator.validate(invalid_data)

        assert result.is_valid is False
        assert len(result.errors) > 0
        assert any("id" in str(err).lower() for err in result.errors)

    def test_validate_invalid_token_value(self):
        """Test validation fails for invalid token values"""
        invalid_data = {
            "id": "test-project",
            "name": "Test Project",
            "theme": {
                "name": "Test Theme",
                "tokens": {
                    "primary": {
                        "name": "primary",
                        "value": "",  # Empty value is invalid
                        "type": "color",
                        "category": "color"
                    }
                }
            }
        }

        validator = ProjectValidator()
        result = validator.validate(invalid_data)

        assert result.is_valid is False
        assert ValidationStage.TOKEN_VALIDATION in [err.stage for err in result.errors]

    def test_validate_token_reference(self):
        """Test validation of token references"""
        data_with_ref = {
            "id": "test-project",
            "name": "Test Project",
            "theme": {
                "name": "Test Theme",
                "tokens": {
                    "primary": {
                        "name": "primary",
                        "value": "oklch(0.65 0.18 250)",
                        "type": "color",
                        "category": "color"
                    },
                    "primary-dark": {
                        "name": "primary-dark",
                        "value": "{primary}",  # Reference to primary token
                        "type": "color",
                        "category": "color"
                    }
                }
            }
        }

        validator = ProjectValidator()
        result = validator.validate(data_with_ref)

        # Should pass - valid reference
        assert result.is_valid is True

    def test_validate_broken_token_reference(self):
        """Test validation fails for broken token reference"""
        data_with_broken_ref = {
            "id": "test-project",
            "name": "Test Project",
            "theme": {
                "name": "Test Theme",
                "tokens": {
                    "primary": {
                        "name": "primary",
                        "value": "{nonexistent}",  # Reference to nonexistent token
                        "type": "color",
                        "category": "color"
                    }
                }
            }
        }

        validator = ProjectValidator()
        result = validator.validate(data_with_broken_ref)

        assert result.is_valid is False
        assert any("reference" in str(err).lower() for err in result.errors)

    def test_validate_component_dependencies(self):
        """Test validation of component dependencies"""
        data = {
            "id": "test-project",
            "name": "Test Project",
            "theme": {
                "name": "Test Theme",
                "tokens": {}
            },
            "components": [
                {
                    "name": "Card",
                    "source": "shadcn",
                    "dependencies": ["Button"]  # Depends on Button component
                },
                {
                    "name": "Button",
                    "source": "shadcn"
                }
            ]
        }

        validator = ProjectValidator()
        result = validator.validate(data)

        # Should pass - Button exists
        assert result.is_valid is True

    def test_validate_missing_component_dependency(self):
        """Test validation fails for missing component dependency"""
        data = {
            "id": "test-project",
            "name": "Test Project",
            "theme": {
                "name": "Test Theme",
                "tokens": {}
            },
            "components": [
                {
                    "name": "Card",
                    "source": "shadcn",
                    "dependencies": ["NonexistentComponent"]
                }
            ]
        }

        validator = ProjectValidator()
        result = validator.validate(data)

        assert result.is_valid is False
        assert any("dependency" in str(err).lower() for err in result.errors)

    def test_validation_stages_order(self):
        """Test validation stages execute in correct order"""
        # Data that fails at schema stage
        invalid_schema = {"invalid": "structure"}

        validator = ProjectValidator()
        result = validator.validate(invalid_schema)

        # Should fail at schema stage and not proceed
        assert result.is_valid is False
        assert result.stage == ValidationStage.SCHEMA

    def test_validate_token_category_enum(self):
        """Test validation accepts valid token categories"""
        data = {
            "id": "test-project",
            "name": "Test Project",
            "theme": {
                "name": "Test Theme",
                "tokens": {
                    "space-md": {
                        "name": "space-md",
                        "value": "16px",
                        "type": "dimension",
                        "category": "spacing"  # Valid category
                    }
                }
            }
        }

        validator = ProjectValidator()
        result = validator.validate(data)

        assert result.is_valid is True

    def test_validate_component_variants(self):
        """Test validation of component variants"""
        data = {
            "id": "test-project",
            "name": "Test Project",
            "theme": {
                "name": "Test Theme",
                "tokens": {}
            },
            "components": [
                {
                    "name": "Button",
                    "source": "shadcn",
                    "variants": ["default", "outline", "ghost", "destructive"]
                }
            ]
        }

        validator = ProjectValidator()
        result = validator.validate(data)

        assert result.is_valid is True


@pytest.mark.unit
class TestValidationResult:
    """Test ValidationResult model"""

    def test_create_valid_result(self):
        """Test creating a valid validation result"""
        from dss.validators.schema import ValidationResult

        result = ValidationResult(
            is_valid=True,
            stage=ValidationStage.COMPLETE,
            errors=[]
        )

        assert result.is_valid is True
        assert result.stage == ValidationStage.COMPLETE
        assert len(result.errors) == 0

    def test_create_invalid_result_with_errors(self):
        """Test creating invalid result with errors"""
        from dss.validators.schema import ValidationResult, ValidationError

        error = ValidationError(
            stage=ValidationStage.SCHEMA,
            message="Missing required field: id",
            field="id"
        )

        result = ValidationResult(
            is_valid=False,
            stage=ValidationStage.SCHEMA,
            errors=[error]
        )

        assert result.is_valid is False
        assert len(result.errors) == 1
        assert result.errors[0].field == "id"
