"""Redis command analysis for issue detection.

Analyzes captured Redis operations for errors, slow commands,
hot keys, and connection issues.
"""

from __future__ import annotations

from collections import Counter
from typing import TYPE_CHECKING, List

if TYPE_CHECKING:
    from autodebug.detection.transcript_analyzer import RedisRecord, TranscriptInsight


# Commands known to be expensive / blocking
EXPENSIVE_COMMANDS = {
    "KEYS", "FLUSHDB", "FLUSHALL", "SMEMBERS", "HGETALL", "LRANGE", "SORT",
    "ZUNIONSTORE", "ZINTERSTORE", "MIGRATE", "HSCAN", "SSCAN", "ZSCAN",
    # Blocking/stream commands
    "BLPOP", "BRPOP", "BRPOPLPUSH", "BLMOVE", "XREAD", "XREADGROUP",
}

# Typical write commands
WRITE_COMMANDS = {"SET", "MSET", "DEL", "HSET", "LPUSH", "RPUSH", "SADD", "ZADD", "INCR", "EXPIRE"}


class RedisAnalyzer:
    """Analyze Redis command records for issues.

    Detects:
    - Redis errors / connection failures
    - Slow commands
    - Expensive commands (KEYS, FLUSHALL, etc.)
    - Hot keys (same key accessed many times)
    - Large value warnings
    """

    def __init__(
        self,
        slow_threshold_ms: float = 50,
        hot_key_threshold: int = 20,
    ):
        self.slow_threshold_ms = slow_threshold_ms
        self.hot_key_threshold = hot_key_threshold

    def analyze(self, records: List[RedisRecord]) -> List[TranscriptInsight]:
        """Analyze Redis records for issues."""

        insights: List[TranscriptInsight] = []

        for record in records:
            insights.extend(self._check_error(record))
            insights.extend(self._check_slow_command(record))
            insights.extend(self._check_expensive_command(record))

        insights.extend(self._detect_hot_keys(records))

        return insights

    def _check_error(self, record: RedisRecord) -> List[TranscriptInsight]:
        from autodebug.detection.transcript_analyzer import TranscriptInsight

        if not record.error:
            return []

        error_lower = record.error.lower()

        if "clusterdown" in error_lower:
            severity = 5
            category = "redis_cluster_down"
            suggestion = "Redis cluster is down - check cluster health"
        elif "loading" in error_lower:
            severity = 4
            category = "redis_loading"
            suggestion = "Redis is loading dataset - wait or check persistence config"
        elif "moved" in error_lower or "ask" in error_lower:
            severity = 1
            category = "redis_cluster_redirect"
            suggestion = "Cluster redirect - client should follow MOVED/ASK"
        elif "connection" in error_lower or "refused" in error_lower:
            severity = 5
            category = "redis_connection_error"
            suggestion = "Check if Redis server is running and reachable"
        elif "oom" in error_lower or "memory" in error_lower:
            severity = 5
            category = "redis_oom"
            suggestion = "Redis is out of memory - check maxmemory policy"
        elif "readonly" in error_lower:
            severity = 4
            category = "redis_readonly"
            suggestion = "Redis is in read-only mode (replica or maxmemory reached)"
        else:
            severity = 4
            category = "redis_error"
            suggestion = "Check Redis server state and command arguments"

        return [
            TranscriptInsight(
                category=category,
                severity=severity,
                description=f"Redis {record.command} error: {record.error[:200]}",
                evidence={
                    "command": record.command,
                    "key": record.key,
                    "error": record.error[:500],
                },
                related_records=[record.seq],
                suggested_investigation=suggestion,
            )
        ]

    def _check_slow_command(self, record: RedisRecord) -> List[TranscriptInsight]:
        from autodebug.detection.transcript_analyzer import TranscriptInsight

        if record.duration_ms < self.slow_threshold_ms:
            return []

        severity = 4 if record.duration_ms > 200 else 3

        return [
            TranscriptInsight(
                category="slow_redis",
                severity=severity,
                description=f"Slow Redis {record.command} ({record.duration_ms:.0f}ms) on key {record.key}",
                evidence={
                    "command": record.command,
                    "key": record.key,
                    "duration_ms": record.duration_ms,
                },
                related_records=[record.seq],
                suggested_investigation="Check key size, Redis server load, or network latency",
            )
        ]

    def _check_expensive_command(self, record: RedisRecord) -> List[TranscriptInsight]:
        from autodebug.detection.transcript_analyzer import TranscriptInsight

        tokens = record.command.split() if record.command else []
        cmd_upper = tokens[0].upper() if tokens else ""
        sub_upper = tokens[1].upper() if len(tokens) > 1 else ""

        # Treat blocking XREAD/XREADGROUP as expensive when BLOCK is used
        if cmd_upper in {"XREAD", "XREADGROUP"} and any(t.upper() == "BLOCK" for t in tokens):
            cmd_upper = "XREAD"

        # Cluster/multi commands sometimes hide expensive ops in subcommands
        if cmd_upper in {"CLUSTER", "CLIENT", "SCRIPT"} and sub_upper in EXPENSIVE_COMMANDS:
            cmd_upper = sub_upper

        if cmd_upper not in EXPENSIVE_COMMANDS:
            return []

        if cmd_upper in ("FLUSHDB", "FLUSHALL"):
            return [
                TranscriptInsight(
                    category="redis_dangerous_command",
                    severity=5,
                    description=f"Dangerous Redis command: {cmd_upper}",
                    evidence={"command": cmd_upper},
                    related_records=[record.seq],
                    suggested_investigation="Avoid FLUSH commands in production code",
                )
            ]

        return [
            TranscriptInsight(
                category="redis_expensive_command",
                severity=3,
                description=f"Expensive Redis command: {cmd_upper} (blocks server)",
                evidence={"command": cmd_upper, "key": record.key},
                related_records=[record.seq],
                suggested_investigation=f"Replace {cmd_upper} with SCAN-based alternative",
            )
        ]

    def _detect_hot_keys(self, records: List[RedisRecord]) -> List[TranscriptInsight]:
        from autodebug.detection.transcript_analyzer import TranscriptInsight

        key_counts: Counter = Counter()
        for record in records:
            if record.key:
                key_counts[record.key] += 1

        insights: List[TranscriptInsight] = []
        for key, count in key_counts.most_common(5):
            if count >= self.hot_key_threshold:
                insights.append(
                    TranscriptInsight(
                        category="redis_hot_key",
                        severity=3,
                        description=f"Hot key detected: {key} accessed {count} times",
                        evidence={"key": key, "access_count": count},
                        related_records=[],
                        suggested_investigation="Consider caching locally or using a different key structure",
                    )
                )

        return insights
