"""
Test Registry Data Models

Definiert die Datenstrukturen fuer das zentrale Test-Dashboard.
"""

from dataclasses import dataclass, field
from datetime import datetime
from enum import Enum
from typing import Optional, List, Dict, Any


class TestFramework(str, Enum):
    GO_TEST = "go_test"
    PYTEST = "pytest"
    JEST = "jest"
    PLAYWRIGHT = "playwright"
    BQAS_GOLDEN = "bqas_golden"
    BQAS_RAG = "bqas_rag"
    BQAS_SYNTHETIC = "bqas_synthetic"


class TestCategory(str, Enum):
    UNIT = "unit"
    INTEGRATION = "integration"
    E2E = "e2e"
    BQAS = "bqas"
    SECURITY = "security"
    PERFORMANCE = "performance"


class TestStatus(str, Enum):
    PENDING = "pending"
    RUNNING = "running"
    PASSED = "passed"
    FAILED = "failed"
    SKIPPED = "skipped"
    ERROR = "error"


class RunStatus(str, Enum):
    QUEUED = "queued"
    RUNNING = "running"
    COMPLETED = "completed"
    FAILED = "failed"
    CANCELLED = "cancelled"


@dataclass
class TestCase:
    """Einzelner Testfall"""
    id: str
    name: str
    file_path: str
    line_number: Optional[int] = None
    framework: TestFramework = TestFramework.GO_TEST
    category: TestCategory = TestCategory.UNIT
    duration_ms: Optional[float] = None
    status: TestStatus = TestStatus.PENDING
    error_message: Optional[str] = None
    output: Optional[str] = None


@dataclass
class TestSuite:
    """Test-Suite eines Services"""
    id: str
    service: str
    name: str
    framework: TestFramework
    category: TestCategory
    base_path: str
    pattern: str  # z.B. "*_test.go" oder "test_*.py"
    tests: List[TestCase] = field(default_factory=list)
    total_tests: int = 0
    passed_tests: int = 0
    failed_tests: int = 0
    skipped_tests: int = 0
    duration_ms: float = 0.0
    coverage_percent: Optional[float] = None
    last_run: Optional[datetime] = None
    status: TestStatus = TestStatus.PENDING


@dataclass
class TestRun:
    """Ein Test-Durchlauf"""
    id: str
    suite_id: str
    service: str
    started_at: datetime
    completed_at: Optional[datetime] = None
    status: RunStatus = RunStatus.QUEUED
    total_tests: int = 0
    passed_tests: int = 0
    failed_tests: int = 0
    skipped_tests: int = 0
    duration_seconds: float = 0.0
    git_commit: Optional[str] = None
    git_branch: Optional[str] = None
    coverage_percent: Optional[float] = None
    triggered_by: str = "manual"
    output: Optional[str] = None
    failed_test_ids: List[str] = field(default_factory=list)


@dataclass
class CoverageReport:
    """Coverage-Bericht fuer einen Service"""
    service: str
    framework: TestFramework
    line_coverage: float
    branch_coverage: Optional[float] = None
    function_coverage: Optional[float] = None
    statement_coverage: Optional[float] = None
    uncovered_files: List[str] = field(default_factory=list)
    timestamp: datetime = field(default_factory=datetime.now)


@dataclass
class ServiceTestInfo:
    """Aggregierte Test-Informationen fuer einen Service"""
    service: str
    display_name: str
    port: Optional[int] = None
    language: str = "unknown"
    total_tests: int = 0
    passed_tests: int = 0
    failed_tests: int = 0
    skipped_tests: int = 0
    pass_rate: float = 0.0
    coverage_percent: Optional[float] = None
    last_run: Optional[datetime] = None
    status: TestStatus = TestStatus.PENDING
    suites: List[TestSuite] = field(default_factory=list)


@dataclass
class TestRegistryStats:
    """Gesamtstatistik des Test-Registrys"""
    total_tests: int = 0
    total_passed: int = 0
    total_failed: int = 0
    total_skipped: int = 0
    overall_pass_rate: float = 0.0
    average_coverage: Optional[float] = None
    services_count: int = 0
    last_full_run: Optional[datetime] = None
    by_category: Dict[str, int] = field(default_factory=dict)
    by_framework: Dict[str, int] = field(default_factory=dict)


# Service-Definitionen mit Test-Informationen
SERVICE_DEFINITIONS = [
    {
        "service": "consent-service",
        "display_name": "Consent Service",
        "port": 8081,
        "language": "go",
        "base_path": "/consent-service",
        "test_pattern": "*_test.go",
        "framework": TestFramework.GO_TEST,
    },
    {
        "service": "backend",
        "display_name": "Python Backend",
        "port": 8000,
        "language": "python",
        "base_path": "/backend/tests",
        "test_pattern": "test_*.py",
        "framework": TestFramework.PYTEST,
    },
    {
        "service": "voice-service",
        "display_name": "Voice Service",
        "port": 8091,
        "language": "python",
        "base_path": "/app/tests",
        "test_pattern": "test_*.py",
        "framework": TestFramework.PYTEST,
        "container_name": "breakpilot-pwa-voice-service",
        "run_in_container": True,
        "pytest_args": "--ignore=/app/tests/bqas",  # Exclude BQAS tests - run separately
    },
    {
        "service": "klausur-service",
        "display_name": "Klausur Service",
        "port": 8086,
        "language": "python",
        "base_path": "/app/tests",
        "test_pattern": "test_*.py",
        "framework": TestFramework.PYTEST,
        "container_name": "breakpilot-pwa-klausur-service",
        "run_in_container": True,
    },
    {
        "service": "billing-service",
        "display_name": "Billing Service",
        "port": 8082,
        "language": "go",
        "base_path": "/billing-service",
        "test_pattern": "*_test.go",
        "framework": TestFramework.GO_TEST,
    },
    {
        "service": "school-service",
        "display_name": "School Service",
        "port": 8084,
        "language": "go",
        "base_path": "/school-service",
        "test_pattern": "*_test.go",
        "framework": TestFramework.GO_TEST,
    },
    {
        "service": "edu-search-service",
        "display_name": "Edu Search Service",
        "port": 8088,
        "language": "go",
        "base_path": "/edu-search-service",
        "test_pattern": "*_test.go",
        "framework": TestFramework.GO_TEST,
    },
    {
        "service": "ai-compliance-sdk",
        "display_name": "AI Compliance SDK",
        "port": None,
        "language": "go",
        "base_path": "/ai-compliance-sdk",
        "test_pattern": "*_test.go",
        "framework": TestFramework.GO_TEST,
    },
    {
        "service": "geo-service",
        "display_name": "Geo Service",
        "port": 8089,
        "language": "mixed",
        "base_path": "/geo-service",
        "test_pattern": "*_test.go",
        "framework": TestFramework.GO_TEST,
        "disabled": True,  # Keine Tests vorhanden - Verzeichnis ist leer
        "disabled_reason": "Keine Test-Dateien vorhanden",
    },
    {
        "service": "website",
        "display_name": "Website (Jest)",
        "port": 3000,
        "language": "typescript",
        "base_path": "/website",
        "test_pattern": "*.test.{ts,tsx}",
        "framework": TestFramework.JEST,
        "requires_setup": True,  # Erfordert npm install im Website-Verzeichnis
        "setup_note": "Fuehren Sie 'npm install' im website-Verzeichnis aus, um Tests lokal auszufuehren",
    },
    # Website E2E entfernt - keine Playwright-Tests vorhanden
    {
        "service": "bqas-golden",
        "display_name": "BQAS Golden Suite",
        "port": 8091,
        "language": "python",
        "base_path": "/app/tests/bqas/test_golden.py",
        "test_pattern": "test_*.py",
        "framework": TestFramework.PYTEST,
        "container_name": "breakpilot-pwa-voice-service",
        "run_in_container": True,
    },
    {
        "service": "bqas-rag",
        "display_name": "BQAS RAG Tests",
        "port": 8091,
        "language": "python",
        "base_path": "/app/tests/bqas/test_rag.py",
        "test_pattern": "test_*.py",
        "framework": TestFramework.PYTEST,
        "container_name": "breakpilot-pwa-voice-service",
        "run_in_container": True,
    },
]
