"""
Pytest configuration and shared fixtures for TimeTracker tests.
This file contains common fixtures and test configuration used across all test modules.
"""

import pytest
import os
import tempfile
import uuid

# Set before app is imported so InstallationConfig uses a writable dir in tests (avoids /data on CI)
if "INSTALLATION_CONFIG_DIR" not in os.environ:
    os.environ["INSTALLATION_CONFIG_DIR"] = tempfile.mkdtemp(prefix="timetracker_install_")

from datetime import datetime, timedelta
from decimal import Decimal
from sqlalchemy.pool import NullPool

from app import create_app, db

# Import all models to ensure their tables are created by db.create_all()
from app.models import (
    User,
    Project,
    TimeEntry,
    Client,
    Settings,
    Invoice,
    InvoiceItem,
    Task,
    TaskActivity,
    Comment,
    ExpenseCategory,
    Mileage,
    PerDiem,
    PerDiemRate,
    ExtraGood,
    FocusSession,
    RecurringBlock,
    RateOverride,
    SavedFilter,
    ProjectCost,
    KanbanColumn,
    TimeEntryTemplate,
    Activity,
    UserFavoriteProject,
    UserSmartNotificationDismissal,
    UserClient,
    ClientNote,
    WeeklyTimeGoal,
    Expense,
    Permission,
    Role,
    ApiToken,
    CalendarEvent,
    BudgetAlert,
    DataImport,
    DataExport,
    InvoicePDFTemplate,
    ClientPrepaidConsumption,
    AuditLog,
    RecurringInvoice,
    InvoiceEmail,
    InvoicePeppolTransmission,
    Webhook,
    WebhookDelivery,
    InvoiceTemplate,
    Currency,
    ExchangeRate,
    TaxRule,
    Payment,
    CreditNote,
    InvoiceReminderSchedule,
    SavedReportView,
    ReportEmailSchedule,
    Warehouse,
    StockItem,
    WarehouseStock,
    StockMovement,
    StockReservation,
    ProjectStockAllocation,
    Quote,
    QuoteItem,
)


# ----------------------------------------------------------------------------
# Time control helpers (freezegun)
# ----------------------------------------------------------------------------
@pytest.fixture
def time_freezer():
    """
    Utility fixture to freeze time during a test.

    Usage:
        freezer = time_freezer()  # freezes at default "2024-01-01 09:00:00"
        # ... run code ...
        freezer.stop()

        # or with a custom timestamp:
        f = time_freezer("2024-06-15 12:30:00")
        # ... run code ...
        f.stop()
    """
    from freezegun import freeze_time as _freeze_time

    _active = []

    def _start(at: str = "2024-01-01 09:00:00"):
        f = _freeze_time(at)
        f.start()
        _active.append(f)
        return f

    try:
        yield _start
    finally:
        while _active:
            f = _active.pop()
            try:
                f.stop()
            except Exception:
                pass


# ============================================================================
# Application Fixtures
# ============================================================================


@pytest.fixture(scope="session")
def app_config():
    """Base test configuration."""
    return {
        "TESTING": True,
        # Use file-based SQLite to ensure consistent connections across contexts/threads
        "SQLALCHEMY_DATABASE_URI": "sqlite:///pytest_main.sqlite",
        # Mitigate SQLite 'database is locked' by increasing busy timeout and enabling pre-ping
        "SQLALCHEMY_ENGINE_OPTIONS": {
            "pool_pre_ping": True,
            "connect_args": {"timeout": 30},
            "poolclass": NullPool,
        },
        "FLASK_ENV": "testing",
        "SQLALCHEMY_TRACK_MODIFICATIONS": False,
        "WTF_CSRF_ENABLED": False,
        "SECRET_KEY": "test-secret-key-do-not-use-in-production",
        "SERVER_NAME": "localhost:5000",
        "APPLICATION_ROOT": "/",
        "PREFERRED_URL_SCHEME": "http",
        "SESSION_COOKIE_HTTPONLY": True,
        # Ensure a stable locale for Babel-dependent formatting in tests
        "BABEL_DEFAULT_LOCALE": "en",
    }


@pytest.fixture(scope="function")
def app(app_config):
    """Create application for testing with function scope."""
    # Use a unique SQLite file per test function to avoid Windows file locking
    unique_db_path = os.path.join(tempfile.gettempdir(), f"pytest_{uuid.uuid4().hex}.sqlite")
    config = dict(app_config)
    config["SQLALCHEMY_DATABASE_URI"] = f"sqlite:///{unique_db_path}"
    app = create_app(config)

    with app.app_context():
        # Import all models AFTER app creation but BEFORE db.create_all()
        # This ensures they're registered with SQLAlchemy's metadata
        # Import all models explicitly to ensure their tables are created
        from app.models import (
            User,
            Project,
            TimeEntry,
            Client,
            Settings,
            Invoice,
            InvoiceItem,
            Task,
            TaskActivity,
            Comment,
            ExpenseCategory,
            Mileage,
            PerDiem,
            PerDiemRate,
            ExtraGood,
            FocusSession,
            RecurringBlock,
            RateOverride,
            SavedFilter,
            ProjectCost,
            KanbanColumn,
            TimeEntryTemplate,
            Activity,
            UserFavoriteProject,
            UserClient,
            ClientNote,
            WeeklyTimeGoal,
            Expense,
            Permission,
            Role,
            ApiToken,
            CalendarEvent,
            BudgetAlert,
            DataImport,
            DataExport,
            InvoicePDFTemplate,
            ClientPrepaidConsumption,
            AuditLog,
            RecurringInvoice,
            InvoiceEmail,
            InvoicePeppolTransmission,
            Webhook,
            WebhookDelivery,
            InvoiceTemplate,
            Currency,
            ExchangeRate,
            TaxRule,
            Payment,
            CreditNote,
            InvoiceReminderSchedule,
            SavedReportView,
            ReportEmailSchedule,
        )

        # Ensure any lingering connections are closed to avoid SQLite file locks (Windows)
        try:
            db.engine.dispose()
        except Exception:
            pass
        # Drop all tables first to ensure clean state
        try:
            db.drop_all()
        except Exception:
            pass  # Ignore errors if tables don't exist

        # Create all tables, handling index creation errors gracefully
        # We need to create tables even if some indexes already exist
        # SQLAlchemy's create_all() stops on first error, so we need to handle this carefully
        try:
            db.create_all()
        except Exception as e:
            # SQLite may raise OperationalError if indexes already exist
            # This can happen if db.create_all() is called multiple times
            error_msg = str(e).lower()
            if "index" in error_msg and ("already exists" in error_msg or "duplicate" in error_msg):
                # Index already exists - this is okay, but we need to ensure all tables are created
                # Create tables individually to work around the issue
                from sqlalchemy import inspect

                inspector = inspect(db.engine)
                existing_tables = set(inspector.get_table_names())

                # Create missing tables explicitly
                for table_name, table in db.metadata.tables.items():
                    if table_name not in existing_tables:
                        try:
                            table.create(db.engine, checkfirst=True)
                        except Exception as table_error:
                            # Ignore errors for individual tables (might be index issues)
                            pass
            else:
                # Log other errors but try to continue
                import logging
                import traceback

                logger = logging.getLogger(__name__)
                logger.warning(f"Error during db.create_all(): {e}")
                logger.warning(traceback.format_exc())

        # Verify critical tables were created and create any missing ones
        from sqlalchemy import inspect

        inspector = inspect(db.engine)
        created_tables = set(inspector.get_table_names())
        required_tables = ["time_entries", "tasks", "users", "projects"]
        missing_tables = [t for t in required_tables if t not in created_tables]

        if missing_tables:
            # Try to create missing tables explicitly
            for table_name in missing_tables:
                if table_name in db.metadata.tables:
                    try:
                        db.metadata.tables[table_name].create(db.engine, checkfirst=True)
                    except Exception as e:
                        # Ignore errors - table might already exist or have dependency issues
                        pass

        # Create default settings
        settings = Settings()
        db.session.add(settings)
        db.session.commit()

        yield app

        db.session.remove()
        try:
            db.drop_all()
        except Exception:
            pass  # Ignore errors during cleanup
        try:
            db.engine.dispose()
        except Exception:
            pass
        # Remove the per-test database file
        try:
            if os.path.exists(unique_db_path):
                os.remove(unique_db_path)
        except Exception:
            pass


@pytest.fixture(scope="function")
def client(app):
    """Create test client."""
    return app.test_client()


@pytest.fixture(scope="function")
def runner(app):
    """Create test CLI runner."""
    return app.test_cli_runner()


# ============================================================================
# Database Fixtures
# ============================================================================


@pytest.fixture(scope="function")
def db_session(app):
    """Create a database session for tests."""
    with app.app_context():
        yield db.session


# ============================================================================
# User Fixtures
# ============================================================================


@pytest.fixture
def user(app):
    """Create a regular test user."""
    # Idempotent: return existing test user if already present (PostgreSQL CI)
    try:
        existing = User.query.filter_by(username="testuser").first()
        if existing:
            if not existing.is_active:
                existing.is_active = True
                db.session.commit()
            # Ensure password is set for login endpoint
            if not existing.check_password("password123"):
                existing.set_password("password123")
                db.session.commit()
            db.session.refresh(existing)
            return existing
    except Exception:
        # Tables don't exist yet or other DB error, rollback and proceed to create user
        db.session.rollback()

    try:
        user = User(username="testuser", role="user", email="testuser@example.com")
        user.is_active = True  # Set after creation
        user.set_password("password123")  # Set password for login endpoint
        db.session.add(user)
        db.session.commit()

        # Refresh to ensure all relationships are loaded and object stays in session
        db.session.refresh(user)
        return user
    except Exception:
        # If tables still don't exist, try to create them
        db.session.rollback()
        db.create_all()

        # Try again after creating tables
        user = User(username="testuser", role="user", email="testuser@example.com")
        user.is_active = True  # Set after creation
        user.set_password("password123")  # Set password for login endpoint
        db.session.add(user)
        db.session.commit()

        db.session.refresh(user)
        return user


@pytest.fixture
def admin_user(app):
    """Create an admin test user."""
    # Idempotent: return existing admin user if already present (PostgreSQL CI)
    try:
        existing = User.query.filter_by(username="admin").first()
        if existing:
            if existing.role != "admin":
                existing.role = "admin"
                existing.is_active = True
                db.session.commit()
            # Ensure password is set for login endpoint
            if not existing.check_password("password123"):
                existing.set_password("password123")
                db.session.commit()
            db.session.refresh(existing)
            return existing
    except Exception:
        # Tables don't exist yet or other DB error, rollback and proceed to create admin
        db.session.rollback()

    try:
        admin = User(username="admin", role="admin", email="admin@example.com")
        admin.is_active = True  # Set after creation
        admin.set_password("password123")  # Set password for login endpoint
        db.session.add(admin)
        db.session.commit()

        # Refresh to ensure all relationships are loaded and object stays in session
        db.session.refresh(admin)
        return admin
    except Exception:
        # If tables still don't exist, try to create them
        db.session.rollback()
        db.create_all()

        # Try again after creating tables
        admin = User(username="admin", role="admin", email="admin@example.com")
        admin.is_active = True  # Set after creation
        admin.set_password("password123")  # Set password for login endpoint
        db.session.add(admin)
        db.session.commit()

        db.session.refresh(admin)
        return admin


@pytest.fixture
def auth_user(user):
    """Alias for user fixture (for backward compatibility with older tests)."""
    return user


@pytest.fixture
def multiple_users(app):
    """Create multiple test users."""
    users = []
    for i in range(1, 4):
        user = User(username=f"user{i}", role="user", email=f"user{i}@example.com")
        user.is_active = True  # Set after creation
        users.append(user)
    db.session.add_all(users)
    db.session.commit()

    for user in users:
        db.session.refresh(user)

    return users


# ============================================================================
# Client Fixtures
# ============================================================================


@pytest.fixture
def test_client(app, user):
    """Create a test client (business client, not test client)."""
    client_model = Client(
        name="Test Client Corp",
        description="Test client for integration tests",
        contact_person="John Doe",
        email="john@testclient.com",
        phone="+1 (555) 123-4567",
        address="123 Test Street, Test City, TC 12345",
        default_hourly_rate=Decimal("85.00"),
    )
    client_model.status = "active"  # Set after creation
    db.session.add(client_model)
    # Flush to assign primary key before commit to avoid expired attribute reloads
    db.session.flush()
    client_id = client_model.id
    db.session.commit()
    # Re-query to ensure we return a persistent instance without relying on refresh
    persisted_client = Client.query.get(client_id) or Client.query.filter_by(id=client_id).first()
    # Fallback to the original instance if re-query unexpectedly returns None
    return persisted_client or client_model


@pytest.fixture
def multiple_clients(app, user):
    """Create multiple test clients."""
    clients = []
    for i in range(1, 4):
        client = Client(
            name=f"Client {i}", email=f"client{i}@example.com", default_hourly_rate=Decimal("75.00") + Decimal(i * 10)
        )
        client.status = "active"  # Set after creation
        clients.append(client)
    db.session.add_all(clients)
    db.session.commit()

    for client in clients:
        db.session.refresh(client)

    return clients


# ============================================================================
# Project Fixtures
# ============================================================================


@pytest.fixture
def project(app, test_client):
    """Create a test project."""
    # Resolve client_id robustly to avoid issues with expired/detached instances
    try:
        cid = getattr(test_client, "id", None)
    except Exception:
        cid = None
    if not cid:
        existing = Client.query.filter_by(name="Test Client Corp").first() or Client.query.first()
        if existing:
            cid = existing.id
        else:
            fallback = Client(
                name="Test Client Corp", email="john@testclient.com", default_hourly_rate=Decimal("85.00")
            )
            fallback.status = "active"
            db.session.add(fallback)
            db.session.flush()
            cid = fallback.id

    project = Project(
        name="Test Project",
        client_id=cid,
        description="Test project description",
        billable=True,
        hourly_rate=Decimal("75.00"),
    )
    project.status = "active"  # Set after creation
    db.session.add(project)
    # Flush to assign ID before commit and return the same instance to avoid re-query issues
    db.session.flush()
    db.session.commit()
    return project


@pytest.fixture
def multiple_projects(app, test_client):
    """Create multiple test projects."""
    # Resolve client_id robustly
    try:
        cid = getattr(test_client, "id", None)
    except Exception:
        cid = None
    if not cid:
        existing = Client.query.filter_by(name="Test Client Corp").first() or Client.query.first()
        if existing:
            cid = existing.id
        else:
            fallback = Client(
                name="Test Client Corp", email="john@testclient.com", default_hourly_rate=Decimal("85.00")
            )
            fallback.status = "active"
            db.session.add(fallback)
            db.session.flush()
            cid = fallback.id

    projects = []
    for i in range(1, 4):
        project = Project(
            name=f"Project {i}",
            client_id=cid,
            description=f"Test project {i}",
            billable=True,
            hourly_rate=Decimal("75.00"),
        )
        project.status = "active"  # Set after creation
        projects.append(project)
    db.session.add_all(projects)
    db.session.commit()

    for proj in projects:
        db.session.refresh(proj)

    return projects


# ============================================================================
# Time Entry Fixtures
# ============================================================================


@pytest.fixture
def time_entry(app, user, project):
    """Create a single time entry."""
    start_time = datetime.utcnow() - timedelta(hours=2)
    end_time = datetime.utcnow()

    entry = TimeEntry(
        user_id=user.id,
        project_id=project.id,
        start_time=start_time,
        end_time=end_time,
        notes="Test time entry",
        tags="test,development",
        source="manual",
        billable=True,
    )
    db.session.add(entry)
    db.session.commit()

    # Refresh entry, but handle case where related objects might be deleted
    try:
        db.session.refresh(entry)
    except Exception:
        # If refresh fails, just return the entry as-is
        # This can happen if user/project are deleted before this fixture is used
        pass
    return entry


@pytest.fixture
def multiple_time_entries(app, user, project):
    """Create multiple time entries."""
    base_time = datetime.utcnow() - timedelta(days=7)
    entries = []

    for i in range(5):
        start = base_time + timedelta(days=i, hours=9)
        end = base_time + timedelta(days=i, hours=17)

        entry = TimeEntry(
            user_id=user.id,
            project_id=project.id,
            start_time=start,
            end_time=end,
            notes=f"Work day {i+1}",
            tags="development,testing",
            source="manual",
            billable=True,
        )
        entries.append(entry)

    db.session.add_all(entries)
    db.session.commit()

    for entry in entries:
        db.session.refresh(entry)

    return entries


@pytest.fixture
def active_timer(app, user, project):
    """Create an active timer (time entry without end time)."""
    timer = TimeEntry(
        user_id=user.id,
        project_id=project.id,
        start_time=datetime.utcnow(),
        notes="Active timer",
        source="auto",
        billable=True,
    )
    db.session.add(timer)
    db.session.commit()

    db.session.refresh(timer)
    return timer


# ============================================================================
# Task Fixtures
# ============================================================================


@pytest.fixture
def task(app, project, user):
    """Create a test task."""
    task = Task(
        name="Test Task",
        description="Test task description",
        project_id=project.id,
        priority="medium",
        created_by=user.id,
    )
    task.status = "todo"  # Set after creation
    db.session.add(task)
    db.session.commit()

    db.session.refresh(task)
    return task


# ============================================================================
# Invoice Fixtures
# ============================================================================


@pytest.fixture
def invoice(app, user, project, test_client):
    """Create a test invoice."""
    from datetime import date
    from factories import InvoiceFactory

    invoice = InvoiceFactory(
        invoice_number=Invoice.generate_invoice_number(),
        project_id=project.id,
        client_id=test_client.id,
        client_name=test_client.name,
        due_date=date.today() + timedelta(days=30),
        created_by=user.id,
        tax_rate=Decimal("20.00"),
        status="draft",
    )
    db.session.commit()

    db.session.refresh(invoice)
    return invoice


@pytest.fixture
def invoice_with_items(app, invoice):
    """Create an invoice with items."""
    from factories import InvoiceItemFactory

    items = [
        InvoiceItemFactory(
            invoice_id=invoice.id,
            description="Development work",
            quantity=Decimal("10.00"),
            unit_price=Decimal("75.00"),
        ),
        InvoiceItemFactory(
            invoice_id=invoice.id, description="Testing work", quantity=Decimal("5.00"), unit_price=Decimal("60.00")
        ),
    ]
    db.session.commit()

    invoice.calculate_totals()
    db.session.commit()

    db.session.refresh(invoice)
    for item in items:
        db.session.refresh(item)

    return invoice, items


# ============================================================================
# Authentication Fixtures
# ============================================================================


@pytest.fixture
def authenticated_client(client, user):
    """Create an authenticated test client."""
    # Use the actual login endpoint to properly authenticate
    # If CSRF is enabled, fetch a token and include it in the form submit
    try:
        from flask import current_app

        csrf_enabled = bool(current_app.config.get("WTF_CSRF_ENABLED"))
    except Exception:
        csrf_enabled = False

    login_data = {"username": user.username, "password": "password123"}
    headers = {}

    if csrf_enabled:
        try:
            resp = client.get("/auth/csrf-token")
            token = ""
            if resp.is_json:
                token = (resp.get_json() or {}).get("csrf_token") or ""
            login_data["csrf_token"] = token
            headers["X-CSRFToken"] = token
        except Exception:
            pass

    client.post("/login", data=login_data, headers=headers or None, follow_redirects=True)
    return client


@pytest.fixture
def admin_authenticated_client(client, admin_user):
    """Create an authenticated admin test client."""
    # Use the actual login endpoint to properly authenticate (same as authenticated_client)
    # If CSRF is enabled, fetch a token and include it in the form submit
    try:
        from flask import current_app

        csrf_enabled = bool(current_app.config.get("WTF_CSRF_ENABLED"))
    except Exception:
        csrf_enabled = False

    login_data = {"username": admin_user.username, "password": "password123"}
    headers = {}

    if csrf_enabled:
        try:
            resp = client.get("/auth/csrf-token")
            token = ""
            if resp.is_json:
                token = (resp.get_json() or {}).get("csrf_token") or ""
            login_data["csrf_token"] = token
            headers["X-CSRFToken"] = token
        except Exception:
            pass

    client.post("/login", data=login_data, headers=headers or None, follow_redirects=True)
    return client


@pytest.fixture
def auth_headers(user):
    """Create authentication headers for API tests (session-based)."""
    # Note: For tests that use headers, they should use authenticated_client instead
    # This fixture is here for backward compatibility
    return {}


# Default scopes for API token (full access to common resources)
DEFAULT_API_TOKEN_SCOPES = (
    "read:projects,write:projects,read:time_entries,write:time_entries,"
    "read:tasks,write:tasks,read:clients,write:clients,read:reports,read:users"
)


@pytest.fixture
def api_token(app, user):
    """Create an API token for the given user with default full scopes. Returns (token_model, plain_token)."""
    with app.app_context():
        token, plain_token = ApiToken.create_token(
            user_id=user.id,
            name="Test API Token",
            scopes=DEFAULT_API_TOKEN_SCOPES,
            expires_days=30,
        )
        db.session.add(token)
        db.session.commit()
        return token, plain_token


@pytest.fixture
def client_with_token(app, api_token):
    """Test client with Authorization: Bearer <token>. Use for API tests."""
    token_model, plain_token = api_token
    test_client = app.test_client()
    test_client.environ_base["HTTP_AUTHORIZATION"] = f"Bearer {plain_token}"
    return test_client


@pytest.fixture
def scope_restricted_user(app, test_client):
    """
    User with subcontractor role and one assigned client (scope-restricted).
    Use with project fixture that uses this client so user_can_access_project is True for that project only.
    """
    role = Role.query.filter_by(name="subcontractor").first()
    if not role:
        role = Role(name="subcontractor", description="Restricted to assigned clients")
        db.session.add(role)
        db.session.flush()

    sub_user = User(
        username="scope_restricted_user",
        email="sub@example.com",
        role="user",
    )
    sub_user.is_active = True
    sub_user.set_password("password123")
    db.session.add(sub_user)
    db.session.flush()

    if role not in sub_user.roles:
        sub_user.roles.append(role)
    db.session.flush()

    # Assign the single test client so this user can only access that client and its projects
    uc = UserClient(user_id=sub_user.id, client_id=test_client.id)
    db.session.add(uc)
    db.session.commit()
    db.session.refresh(sub_user)
    # Force load relationships so they are available when user is used in tests
    _ = list(sub_user.roles)
    _ = list(sub_user.assigned_clients.all())
    return sub_user


@pytest.fixture
def scope_restricted_authenticated_client(client, scope_restricted_user):
    """Test client logged in as scope_restricted_user (subcontractor with one assigned client)."""
    login_data = {"username": scope_restricted_user.username, "password": "password123"}
    headers = {}
    try:
        from flask import current_app

        if current_app.config.get("WTF_CSRF_ENABLED"):
            resp = client.get("/auth/csrf-token")
            token = (resp.get_json() or {}).get("csrf_token", "") if resp.is_json else ""
            login_data["csrf_token"] = token
            headers["X-CSRFToken"] = token
    except Exception:
        pass
    client.post("/login", data=login_data, headers=headers or None, follow_redirects=True)
    return client


@pytest.fixture
def regular_user(user):
    """Alias for user fixture (regular non-admin user)."""
    return user


# ============================================================================
# Utility Fixtures
# ============================================================================


@pytest.fixture
def temp_file():
    """Create a temporary file for testing."""
    fd, path = tempfile.mkstemp()
    yield path
    os.close(fd)
    os.unlink(path)


@pytest.fixture
def temp_dir():
    """Create a temporary directory for testing."""
    dirpath = tempfile.mkdtemp()
    yield dirpath
    import shutil

    shutil.rmtree(dirpath)


# ============================================================================
# Alias Fixtures (for compatibility with different test naming conventions)
# ============================================================================


@pytest.fixture
def test_client_obj(test_client):
    """Alias for test_client to avoid naming conflicts"""
    return test_client


@pytest.fixture
def test_user(user):
    """Alias for user fixture"""
    return user


@pytest.fixture
def auth_user(user):
    """Alias for user fixture"""
    return user


@pytest.fixture
def test_project(project):
    """Alias for project fixture"""
    return project


@pytest.fixture
def test_task(task):
    """Alias for task fixture"""
    return task


# ============================================================================
# Installation Config Fixture
# ============================================================================


@pytest.fixture
def installation_config(temp_dir):
    """Create a temporary installation config for testing"""
    from app.utils.installation import InstallationConfig

    # Override the config directory to use temp directory
    original_config_dir = InstallationConfig.CONFIG_DIR
    InstallationConfig.CONFIG_DIR = temp_dir

    # Create the config instance
    config = InstallationConfig()

    yield config

    # Restore original config directory
    InstallationConfig.CONFIG_DIR = original_config_dir


# ============================================================================
# OpenTelemetry teardown (allows each test app to re-run init_opentelemetry)
# ============================================================================


@pytest.fixture(autouse=True)
def _reset_opentelemetry_after_test():
    yield
    try:
        from app.telemetry.otel_setup import reset_for_testing

        reset_for_testing()
    except Exception:
        pass


# ============================================================================
# Pytest Markers
# ============================================================================


def pytest_configure(config):
    """Configure custom pytest markers."""
    config.addinivalue_line("markers", "smoke: Quick smoke tests")
    config.addinivalue_line("markers", "unit: Unit tests")
    config.addinivalue_line("markers", "integration: Integration tests")
    config.addinivalue_line("markers", "api: API endpoint tests")
    config.addinivalue_line("markers", "database: Database-related tests")
    config.addinivalue_line("markers", "models: Model tests")
    config.addinivalue_line("markers", "routes: Route tests")
    config.addinivalue_line("markers", "security: Security tests")
    config.addinivalue_line("markers", "performance: Performance tests")
    config.addinivalue_line("markers", "slow: Slow running tests")
