"""Analytics service — flat JSON optimized for PowerBI / BI tools."""

# Enable future language features for compatibility
from __future__ import annotations

# Import func from sqlalchemy
from sqlalchemy import func

# Import Session from sqlalchemy.orm
from sqlalchemy.orm import Session

# Import CoverageSnapshot from app.models.coverage_snapshot
from app.models.coverage_snapshot import CoverageSnapshot

# Import Technique from app.models.technique
from app.models.technique import Technique

# Import Test from app.models.test
from app.models.test import Test

# Import User from app.models.user
from app.models.user import User


# Define function get_coverage_analytics
def get_coverage_analytics(db: Session) -> list[dict]:
    """Coverage per technique — flat format for BI dashboards."""
    # Assign techniques = db.query(Technique).all()
    techniques = db.query(Technique).all()
    # Return [
    return [
        {
            # Literal argument value
            "mitre_id": t.mitre_id,
            # Literal argument value
            "name": t.name,
            # Literal argument value
            "tactic": t.tactic,
            # Literal argument value
            "status": t.status_global.value if t.status_global else "not_evaluated",
            # Literal argument value
            "is_subtechnique": t.is_subtechnique,
            # Literal argument value
            "test_count": len(t.tests) if t.tests else 0,
            # Literal argument value
            "review_required": t.review_required,
            # Literal argument value
            "last_review_date": (
                t.last_review_date.isoformat() if t.last_review_date else None
            ),
        }
        for t in techniques
    ]


# Define function get_tests_analytics
def get_tests_analytics(
    # Entry: db
    db: Session,
    *,
    # Entry: date_from
    date_from: str | None = None,
    # Entry: date_to
    date_to: str | None = None,
) -> list[dict]:
    """All tests with timestamps — flat format for BI dashboards."""
    # Assign query = db.query(Test)
    query = db.query(Test)
    # Check: date_from
    if date_from:
        # Assign query = query.filter(Test.created_at >= date_from)
        query = query.filter(Test.created_at >= date_from)
    # Check: date_to
    if date_to:
        # Assign query = query.filter(Test.created_at <= date_to)
        query = query.filter(Test.created_at <= date_to)
    # Assign tests = query.all()
    tests = query.all()

    # Return [
    return [
        {
            # Literal argument value
            "id": str(t.id),
            # Literal argument value
            "technique_id": str(t.technique_id),
            # Literal argument value
            "name": t.name,
            # Literal argument value
            "state": t.state.value if t.state else None,
            # Literal argument value
            "result": t.result.value if t.result else None,
            # Literal argument value
            "detection_result": (
                t.detection_result.value if t.detection_result else None
            ),
            # Literal argument value
            "created_at": t.created_at.isoformat() if t.created_at else None,
            # Literal argument value
            "execution_date": (
                t.execution_date.isoformat() if t.execution_date else None
            ),
            # Literal argument value
            "platform": t.platform,
            # Literal argument value
            "tool_used": t.tool_used,
            # Literal argument value
            "attack_success": t.attack_success.value if t.attack_success else None,
            # Literal argument value
            "remediation_status": t.remediation_status,
        }
        for t in tests
    ]


# Define function get_trends_analytics
def get_trends_analytics(db: Session) -> list[dict]:
    """Historical coverage snapshots for trend visualization."""
    # Assign snapshots = (
    snapshots = (
        db.query(CoverageSnapshot)
        # Chain .order_by() call
        .order_by(CoverageSnapshot.created_at)
        # Chain .all() call
        .all()
    )
    # Return [
    return [
        {
            # Literal argument value
            "date": s.created_at.isoformat() if s.created_at else None,
            # Literal argument value
            "name": s.name,
            # Literal argument value
            "total_techniques": s.total_techniques,
            # Literal argument value
            "validated_count": s.validated_count,
            # Literal argument value
            "partial_count": s.partial_count,
            # Literal argument value
            "not_covered_count": s.not_covered_count,
            # Literal argument value
            "organization_score": s.organization_score,
        }
        for s in snapshots
    ]


# Define function get_operators_analytics
def get_operators_analytics(db: Session) -> list[dict]:
    """Per-operator metrics — for workload management dashboards."""
    # Assign results = (
    results = (
        db.query(
            User.username,
            User.role,
            func.count(Test.id).label("test_count"),
        )
        # Chain .outerjoin() call
        .outerjoin(Test, Test.created_by == User.id)
        # Chain .group_by() call
        .group_by(User.id, User.username, User.role)
        # Chain .all() call
        .all()
    )
    # Return [
    return [
        {"username": r[0], "role": r[1], "test_count": r[2]}
        for r in results
    ]
