"""Metrics collection from Django - direct, no C extensions.

This module collects performance metrics directly from Django's built-in systems:
- django.db.connection.queries for database queries
- psutil for memory usage
- time.perf_counter() for timing

No ctypes, no mocks, no fallback chains - just straightforward data collection.
"""

import time
import logging
from typing import Optional, List

from .metrics import PerformanceMetrics, QueryInfo

logger = logging.getLogger(__name__)

# Optional dependencies
try:
    import psutil

    PSUTIL_AVAILABLE = True
except ImportError:
    PSUTIL_AVAILABLE = False
    logger.debug("psutil not available - memory metrics will use fallback")


class MetricsCollector:
    """Collects performance metrics from Django and system.

    Usage:
        collector = MetricsCollector()
        collector.start()
        # ... do work ...
        collector.stop()
        metrics = collector.get_metrics()
    """

    def __init__(self, operation_name: str = "", operation_type: str = "general"):
        self.operation_name = operation_name
        self.operation_type = operation_type

        self._start_time: Optional[float] = None
        self._end_time: Optional[float] = None
        self._start_query_count: int = 0
        self._queries: List[QueryInfo] = []
        self._memory_mb: float = 80.0  # Fallback

    def start(self) -> None:
        """Start collecting metrics."""
        self._start_time = time.perf_counter()

        # Get Django query count at start
        try:
            from django.db import connection, reset_queries

            # Reset queries to isolate this monitoring session
            reset_queries()
            self._start_query_count = len(connection.queries)
            logger.debug(
                f"Started monitoring {self.operation_name}, reset queries to {self._start_query_count}"
            )
        except ImportError:
            logger.debug("Django not available - query tracking disabled")
            self._start_query_count = 0
        except Exception as e:
            logger.debug(f"Could not access Django queries: {e}")
            self._start_query_count = 0

    def stop(self) -> None:
        """Stop collecting metrics and capture final state."""
        self._end_time = time.perf_counter()

        # Collect queries from Django
        try:
            from django.db import connection

            if hasattr(connection, "queries"):
                # Get all queries since start
                all_queries = connection.queries[self._start_query_count :]

                # Convert to QueryInfo objects
                self._queries = [
                    QueryInfo(
                        sql=q.get("sql", ""),
                        duration_seconds=float(q.get("time", 0)),
                        stack_trace=None,  # Django doesn't provide this by default
                    )
                    for q in all_queries
                ]

                logger.debug(f"Captured {len(self._queries)} queries for {self.operation_name}")
        except ImportError:
            logger.debug("Django not available - no queries captured")
        except Exception as e:
            logger.debug(f"Failed to capture queries: {e}")

        # Get memory usage
        if PSUTIL_AVAILABLE:
            try:
                import psutil

                process = psutil.Process()
                memory_info = process.memory_info()
                self._memory_mb = memory_info.rss / (1024 * 1024)  # Convert bytes to MB
            except Exception as e:
                logger.debug(f"Failed to get memory usage: {e}")
                self._memory_mb = 80.0  # Fallback to baseline
        else:
            self._memory_mb = 80.0  # Fallback when psutil not available

    def get_metrics(self) -> PerformanceMetrics:
        """Get collected metrics as a PerformanceMetrics object.

        Returns:
            PerformanceMetrics with all collected data

        Raises:
            RuntimeError: If called before start() or stop()
        """
        if self._start_time is None:
            raise RuntimeError("Metrics collection not started - call start() first")

        if self._end_time is None:
            raise RuntimeError("Metrics collection not stopped - call stop() first")

        # Calculate response time
        response_time_ms = (self._end_time - self._start_time) * 1000

        return PerformanceMetrics(
            operation_name=self.operation_name,
            operation_type=self.operation_type,
            response_time_ms=response_time_ms,
            memory_mb=self._memory_mb,
            query_count=len(self._queries),
            queries=self._queries,
            cache_hits=0,  # TODO: Add cache tracking if needed
            cache_misses=0,
        )
