"""SQLAlchemy implementation of TestRepository."""

from __future__ import annotations

import uuid

from sqlalchemy import func
from sqlalchemy.orm import Session

from app.domain.enums import TestState
from app.models.test import Test


class SATestRepository:
    """Concrete test repository backed by SQLAlchemy."""

    def __init__(self, session: Session) -> None:
        self._session = session

    def find_by_id(self, test_id: uuid.UUID) -> Test | None:
        return (
            self._session.query(Test)
            .filter(Test.id == test_id)
            .first()
        )

    def list_by_technique(self, technique_id: uuid.UUID) -> list[Test]:
        return (
            self._session.query(Test)
            .filter(Test.technique_id == technique_id)
            .order_by(Test.created_at)
            .all()
        )

    def list_by_state(self, state: TestState) -> list[Test]:
        return (
            self._session.query(Test)
            .filter(Test.state == state)
            .all()
        )

    def count_by_technique_and_state(
        self,
        technique_id: uuid.UUID,
    ) -> dict[TestState, int]:
        rows = (
            self._session.query(Test.state, func.count(Test.id))
            .filter(Test.technique_id == technique_id)
            .group_by(Test.state)
            .all()
        )
        result: dict[TestState, int] = {}
        for state_val, count in rows:
            key = (
                state_val
                if isinstance(state_val, TestState)
                else TestState(state_val)
            )
            result[key] = count
        return result

    def get_states_and_results_for_technique(
        self,
        technique_id: uuid.UUID,
    ) -> list[tuple[str, str | None]]:
        """Return lightweight (state, detection_result) pairs.

        Used by TechniqueEntity.recalculate_status() without loading
        full Test models.
        """
        rows = (
            self._session.query(Test.state, Test.detection_result)
            .filter(Test.technique_id == technique_id)
            .all()
        )
        return [
            (
                r.state.value if hasattr(r.state, "value") else str(r.state),
                (
                    r.detection_result.value
                    if hasattr(r.detection_result, "value")
                    else r.detection_result
                ),
            )
            for r in rows
        ]
