# #region TestMetricsCumulative [C:3] [TYPE Module] [SEMANTICS test, metrics, cumulative, tokens]
# @BRIEF Validate cumulative_tokens and cumulative_cost aggregation in TranslationMetrics.
# @RELATION BINDS_TO -> [TranslationMetrics]

import pytest
from datetime import datetime, timezone

from sqlalchemy import create_engine, event
from sqlalchemy.orm import Session, sessionmaker

from src.models.translate import (
    Base,
    TranslationJob,
    TranslationRun,
    TranslationRunLanguageStats,
)
from src.plugins.translate.metrics import TranslationMetrics
import uuid


# region db_session [TYPE Fixture]
@pytest.fixture
def db_session():
    engine = create_engine("sqlite:///:memory", echo=False)

    @event.listens_for(engine, "connect")
    def _set_sqlite_pragma(dbapi_connection, connection_record):
        cursor = dbapi_connection.cursor()
        cursor.execute("PRAGMA foreign_keys=ON")
        cursor.close()

    Base.metadata.create_all(bind=engine)
    session = sessionmaker(bind=engine)()
    try:
        yield session
    finally:
        session.close()
        Base.metadata.drop_all(bind=engine)
# endregion db_session


class TestCumulativeTokens:
    """Verify cumulative_tokens aggregation across runs."""

    # region test_cumulative_tokens_single_run [C:2] [TYPE Function]
    def test_cumulative_tokens_single_run(self, db_session: Session):
        job = TranslationJob(id=str(uuid.uuid4()), name="Test Job", source_dialect="a", target_dialect="b", status="ACTIVE", created_by="test")
        db_session.add(job)
        db_session.flush()

        run = TranslationRun(
            id=str(uuid.uuid4()), job_id=job.id,
            status="COMPLETED",
            started_at=datetime.now(timezone.utc),
            created_at=datetime.now(timezone.utc),
        )
        db_session.add(run)
        db_session.flush()

        stats = TranslationRunLanguageStats(
            run_id=run.id, language_code="en",
            token_count=1500, estimated_cost=0.003,
            translated_rows=50,
        )
        db_session.add(stats)
        db_session.commit()

        metrics = TranslationMetrics(db_session).get_job_metrics(job.id)
        assert metrics["cumulative_tokens"] == 1500
        assert metrics["cumulative_cost"] == 0.003
        assert metrics["per_language_metrics"]["en"]["tokens"] == 1500
    # endregion test_cumulative_tokens_single_run

    # region test_cumulative_tokens_multi_run [C:2] [TYPE Function]
    def test_cumulative_tokens_multi_run(self, db_session: Session):
        job = TranslationJob(id=str(uuid.uuid4()), name="Multi Run Job", source_dialect="a", target_dialect="b", status="ACTIVE", created_by="test")
        db_session.add(job)
        db_session.flush()

        for i in range(3):
            run = TranslationRun(
                id=str(uuid.uuid4()), job_id=job.id,
                status="COMPLETED",
                started_at=datetime.now(timezone.utc),
                created_at=datetime.now(timezone.utc),
            )
            db_session.add(run)
            db_session.flush()

            stats = TranslationRunLanguageStats(
                run_id=run.id, language_code="en",
                token_count=1000 * (i + 1),
                estimated_cost=0.001 * (i + 1),
                translated_rows=10 * (i + 1),
            )
            db_session.add(stats)

        db_session.commit()

        metrics = TranslationMetrics(db_session).get_job_metrics(job.id)
        # tokens: 1000 + 2000 + 3000 = 6000
        assert metrics["cumulative_tokens"] == 6000
        # cost: 0.001 + 0.002 + 0.003 = 0.006
        assert abs(metrics["cumulative_cost"] - 0.006) < 1e-10
    # endregion test_cumulative_tokens_multi_run

    # region test_cumulative_tokens_multi_language [C:2] [TYPE Function]
    def test_cumulative_tokens_multi_language(self, db_session: Session):
        job = TranslationJob(id=str(uuid.uuid4()), name="Multi Lang Job", source_dialect="a", target_dialect="b", status="ACTIVE", created_by="test")
        db_session.add(job)
        db_session.flush()

        run = TranslationRun(
            id=str(uuid.uuid4()), job_id=job.id,
            status="COMPLETED",
            started_at=datetime.now(timezone.utc),
            created_at=datetime.now(timezone.utc),
        )
        db_session.add(run)
        db_session.flush()

        db_session.add(TranslationRunLanguageStats(
            run_id=run.id, language_code="en",
            token_count=5000, estimated_cost=0.01, translated_rows=100,
        ))
        db_session.add(TranslationRunLanguageStats(
            run_id=run.id, language_code="ru",
            token_count=3000, estimated_cost=0.006, translated_rows=60,
        ))
        db_session.commit()

        metrics = TranslationMetrics(db_session).get_job_metrics(job.id)
        assert metrics["cumulative_tokens"] == 8000  # 5000 + 3000
        assert abs(metrics["cumulative_cost"] - 0.016) < 1e-10
    # endregion test_cumulative_tokens_multi_language

    # region test_cumulative_tokens_no_runs [C:2] [TYPE Function]
    def test_cumulative_tokens_no_runs(self, db_session: Session):
        job = TranslationJob(id=str(uuid.uuid4()), name="No Runs Job", source_dialect="a", target_dialect="b", status="DRAFT", created_by="test")
        db_session.add(job)
        db_session.commit()

        metrics = TranslationMetrics(db_session).get_job_metrics(job.id)
        assert metrics["cumulative_tokens"] == 0
        assert metrics["cumulative_cost"] == 0.0
        assert metrics["per_language_metrics"] == {}
    # endregion test_cumulative_tokens_no_runs

    # region test_cumulative_tokens_with_null_values [C:2] [TYPE Function]
    def test_cumulative_tokens_with_null_values(self, db_session: Session):
        job = TranslationJob(id=str(uuid.uuid4()), name="Null Tokens", source_dialect="a", target_dialect="b", status="ACTIVE", created_by="test")
        db_session.add(job)
        db_session.flush()

        run = TranslationRun(
            id=str(uuid.uuid4()), job_id=job.id,
            status="COMPLETED",
            started_at=datetime.now(timezone.utc),
            created_at=datetime.now(timezone.utc),
        )
        db_session.add(run)
        db_session.commit()

        # Add stats with null token_count and estimated_cost
        stats = TranslationRunLanguageStats(
            run_id=run.id, language_code="en",
            token_count=None, estimated_cost=None,
            translated_rows=10,
        )
        db_session.add(stats)
        db_session.commit()

        metrics = TranslationMetrics(db_session).get_job_metrics(job.id)
        assert metrics["cumulative_tokens"] == 0  # None treated as 0
        assert metrics["cumulative_cost"] == 0.0
    # endregion test_cumulative_tokens_with_null_values
# #endregion TestMetricsCumulative
