"""
Tests for VAT Validator

Tests cross-validation of VAT information from multiple sources.
"""

import pytest
from backend.validation.vat_validator import (
    VATValidationResult,
    VATValidator,
    MathCheckResult,
)
from backend.vat.vat_extractor import VATBreakdown, VATSummary
from backend.table.line_items_extractor import LineItem, LineItemsResult


class TestMathCheckResult:
    """Tests for MathCheckResult dataclass."""

    def test_create_math_check_result(self):
        """Test creating a math check result."""
        result = MathCheckResult(
            rate=25.0,
            base_amount=10000.0,
            expected_vat=2500.0,
            actual_vat=2500.0,
            is_valid=True,
            tolerance=0.01,
        )
        assert result.rate == 25.0
        assert result.is_valid is True

    def test_math_check_with_tolerance(self):
        """Test math check within tolerance."""
        result = MathCheckResult(
            rate=25.0,
            base_amount=10000.0,
            expected_vat=2500.0,
            actual_vat=2500.01,  # Within tolerance
            is_valid=True,
            tolerance=0.02,
        )
        assert result.is_valid is True


class TestVATValidationResult:
    """Tests for VATValidationResult dataclass."""

    def test_create_validation_result(self):
        """Test creating a validation result."""
        result = VATValidationResult(
            is_valid=True,
            confidence_score=0.95,
            math_checks=[],
            total_check=True,
            line_items_vs_summary=True,
            amount_consistency=True,
            needs_review=False,
            review_reasons=[],
        )
        assert result.is_valid is True
        assert result.confidence_score == 0.95
        assert result.needs_review is False

    def test_validation_result_with_review_reasons(self):
        """Test validation result requiring review."""
        result = VATValidationResult(
            is_valid=False,
            confidence_score=0.4,
            math_checks=[],
            total_check=False,
            line_items_vs_summary=None,
            amount_consistency=False,
            needs_review=True,
            review_reasons=["Math check failed", "Total mismatch"],
        )
        assert result.is_valid is False
        assert result.needs_review is True
        assert len(result.review_reasons) == 2


class TestVATValidator:
    """Tests for VATValidator."""

    def test_validate_simple_vat(self):
        """Test validating simple single-rate VAT."""
        validator = VATValidator()

        vat_summary = VATSummary(
            breakdowns=[
                VATBreakdown(rate=25.0, base_amount="10 000,00", vat_amount="2 500,00", source="regex")
            ],
            total_excl_vat="10 000,00",
            total_vat="2 500,00",
            total_incl_vat="12 500,00",
            confidence=0.9,
        )

        result = validator.validate(vat_summary)

        assert result.is_valid is True
        assert result.confidence_score >= 0.9
        assert result.total_check is True

    def test_validate_multiple_vat_rates(self):
        """Test validating multiple VAT rates."""
        validator = VATValidator()

        vat_summary = VATSummary(
            breakdowns=[
                VATBreakdown(rate=25.0, base_amount="8 000,00", vat_amount="2 000,00", source="regex"),
                VATBreakdown(rate=12.0, base_amount="2 000,00", vat_amount="240,00", source="regex"),
            ],
            total_excl_vat="10 000,00",
            total_vat="2 240,00",
            total_incl_vat="12 240,00",
            confidence=0.9,
        )

        result = validator.validate(vat_summary)

        assert result.is_valid is True
        assert len(result.math_checks) == 2

    def test_validate_math_check_failure(self):
        """Test detecting math check failure."""
        validator = VATValidator()

        # VAT amount doesn't match rate
        vat_summary = VATSummary(
            breakdowns=[
                VATBreakdown(rate=25.0, base_amount="10 000,00", vat_amount="3 000,00", source="regex")  # Should be 2500
            ],
            total_excl_vat="10 000,00",
            total_vat="3 000,00",
            total_incl_vat="13 000,00",
            confidence=0.9,
        )

        result = validator.validate(vat_summary)

        assert result.is_valid is False
        assert result.needs_review is True
        assert any("Math" in reason or "math" in reason for reason in result.review_reasons)

    def test_validate_total_mismatch(self):
        """Test detecting total amount mismatch."""
        validator = VATValidator()

        vat_summary = VATSummary(
            breakdowns=[
                VATBreakdown(rate=25.0, base_amount="10 000,00", vat_amount="2 500,00", source="regex")
            ],
            total_excl_vat="10 000,00",
            total_vat="2 500,00",
            total_incl_vat="15 000,00",  # Wrong - should be 12500
            confidence=0.9,
        )

        result = validator.validate(vat_summary)

        assert result.total_check is False
        assert result.needs_review is True

    def test_validate_with_line_items(self):
        """Test validation with line items comparison."""
        validator = VATValidator()

        line_items = LineItemsResult(
            items=[
                LineItem(row_index=0, description="Item 1", amount="5 000,00", vat_rate="25"),
                LineItem(row_index=1, description="Item 2", amount="5 000,00", vat_rate="25"),
            ],
            header_row=["Description", "Amount"],
            raw_html="<table>...</table>",
        )

        vat_summary = VATSummary(
            breakdowns=[
                VATBreakdown(rate=25.0, base_amount="10 000,00", vat_amount="2 500,00", source="regex")
            ],
            total_excl_vat="10 000,00",
            total_vat="2 500,00",
            total_incl_vat="12 500,00",
            confidence=0.9,
        )

        result = validator.validate(vat_summary, line_items=line_items)

        assert result.line_items_vs_summary is not None

    def test_validate_amount_consistency(self):
        """Test consistency check with extracted amount field."""
        validator = VATValidator()

        vat_summary = VATSummary(
            breakdowns=[
                VATBreakdown(rate=25.0, base_amount="10 000,00", vat_amount="2 500,00", source="regex")
            ],
            total_excl_vat="10 000,00",
            total_vat="2 500,00",
            total_incl_vat="12 500,00",
            confidence=0.9,
        )

        # Existing amount field from YOLO extraction
        existing_amount = "12 500,00"

        result = validator.validate(vat_summary, existing_amount=existing_amount)

        assert result.amount_consistency is True

    def test_validate_amount_inconsistency(self):
        """Test detecting amount field inconsistency."""
        validator = VATValidator()

        vat_summary = VATSummary(
            breakdowns=[
                VATBreakdown(rate=25.0, base_amount="10 000,00", vat_amount="2 500,00", source="regex")
            ],
            total_excl_vat="10 000,00",
            total_vat="2 500,00",
            total_incl_vat="12 500,00",
            confidence=0.9,
        )

        # Different amount from YOLO extraction
        existing_amount = "15 000,00"

        result = validator.validate(vat_summary, existing_amount=existing_amount)

        assert result.amount_consistency is False
        assert result.needs_review is True

    def test_validate_empty_summary(self):
        """Test validating empty VAT summary."""
        validator = VATValidator()

        vat_summary = VATSummary(
            breakdowns=[],
            total_excl_vat=None,
            total_vat=None,
            total_incl_vat=None,
            confidence=0.0,
        )

        result = validator.validate(vat_summary)

        assert result.confidence_score == 0.0
        assert result.is_valid is False

    def test_validate_without_base_amounts(self):
        """Test validation when base amounts are not available."""
        validator = VATValidator()

        vat_summary = VATSummary(
            breakdowns=[
                VATBreakdown(rate=25.0, base_amount=None, vat_amount="2 500,00", source="regex")
            ],
            total_excl_vat="10 000,00",
            total_vat="2 500,00",
            total_incl_vat="12 500,00",
            confidence=0.9,
        )

        result = validator.validate(vat_summary)

        # Should still validate totals even without per-rate base amounts
        assert result.total_check is True

    def test_confidence_score_calculation(self):
        """Test confidence score calculation."""
        validator = VATValidator()

        # All checks pass - high confidence
        vat_summary_good = VATSummary(
            breakdowns=[
                VATBreakdown(rate=25.0, base_amount="10 000,00", vat_amount="2 500,00", source="regex")
            ],
            total_excl_vat="10 000,00",
            total_vat="2 500,00",
            total_incl_vat="12 500,00",
            confidence=0.95,
        )
        result_good = validator.validate(vat_summary_good)

        # Some checks fail - lower confidence
        vat_summary_bad = VATSummary(
            breakdowns=[
                VATBreakdown(rate=25.0, base_amount="10 000,00", vat_amount="3 000,00", source="regex")
            ],
            total_excl_vat="10 000,00",
            total_vat="3 000,00",
            total_incl_vat="12 500,00",  # Doesn't match
            confidence=0.5,
        )
        result_bad = validator.validate(vat_summary_bad)

        assert result_good.confidence_score > result_bad.confidence_score

    def test_tolerance_configuration(self):
        """Test configurable tolerance for math checks."""
        # Strict tolerance
        validator_strict = VATValidator(tolerance=0.001)
        # Lenient tolerance
        validator_lenient = VATValidator(tolerance=1.0)

        vat_summary = VATSummary(
            breakdowns=[
                VATBreakdown(rate=25.0, base_amount="10 000,00", vat_amount="2 500,50", source="regex")  # Off by 0.50
            ],
            total_excl_vat="10 000,00",
            total_vat="2 500,50",
            total_incl_vat="12 500,50",
            confidence=0.9,
        )

        result_strict = validator_strict.validate(vat_summary)
        result_lenient = validator_lenient.validate(vat_summary)

        # Strict should fail, lenient should pass
        assert result_strict.math_checks[0].is_valid is False
        assert result_lenient.math_checks[0].is_valid is True
