"""IMA Stage 4 — Smart Compression.

Applies the depth decision to content:
  - full: store entire content as-is
  - summary: store AI-generated or extractive summary
  - key_only: store only key facts/values
"""

import logging

logger = logging.getLogger("soagila.ima.compressor")


class CompressedContent:
    """Result of Stage 4 compression."""

    def __init__(
        self,
        original_length: int,
        compressed_length: int,
        detail_level: str,
        content: str,
        compression_ratio: float,
    ):
        self.original_length = original_length
        self.compressed_length = compressed_length
        self.detail_level = detail_level
        self.content = content
        self.compression_ratio = compression_ratio

    def to_dict(self) -> dict:
        return {
            "original_length": self.original_length,
            "compressed_length": self.compressed_length,
            "detail_level": self.detail_level,
            "compression_ratio": round(self.compression_ratio, 3),
        }


def compress(
    content: str,
    detail_level: str,
    summary: str | None = None,
    key_points: list[str] | None = None,
) -> CompressedContent:
    """Compress content based on detail_level decision.

    Args:
        content: Original content to compress.
        detail_level: "full" | "summary" | "key_only"
        summary: AI-generated summary (from Stage 3), if available.
        key_points: AI-extracted key points (from Stage 3), if available.

    Returns:
        CompressedContent with the final stored version.
    """
    original_length = len(content)

    if detail_level == "full":
        result = content
    elif detail_level == "summary":
        result = _generate_summary(content, summary)
    elif detail_level == "key_only":
        result = _generate_key_only(content, key_points)
    else:
        # Unknown detail level — store full
        result = content

    compressed_length = len(result)
    ratio = compressed_length / original_length if original_length > 0 else 1.0

    logger.debug(
        f"IMA compressor: {detail_level} — {original_length} -> {compressed_length} chars "
        f"(ratio: {ratio:.2f})"
    )

    return CompressedContent(
        original_length=original_length,
        compressed_length=compressed_length,
        detail_level=detail_level,
        content=result,
        compression_ratio=ratio,
    )


def _generate_summary(content: str, ai_summary: str | None) -> str:
    """Generate summary — prefer AI summary, fallback to extractive."""
    if ai_summary:
        return ai_summary

    # Extractive fallback: first N sentences that cover key info
    sentences = []
    for part in content.replace("\n\n", "\n").split("\n"):
        part = part.strip()
        if not part:
            continue
        # Split by sentence boundaries
        for sentence in part.split(". "):
            s = sentence.strip()
            if s:
                if not s.endswith("."):
                    s += "."
                sentences.append(s)

    # Take first 5 sentences or 500 chars, whichever is less
    result_sentences = []
    total_len = 0
    for s in sentences:
        if total_len + len(s) > 500 and len(result_sentences) >= 2:
            break
        result_sentences.append(s)
        total_len += len(s)

    if not result_sentences:
        return content[:500]

    return " ".join(result_sentences)


def _generate_key_only(content: str, ai_key_points: list[str] | None) -> str:
    """Generate key-only version — prefer AI key points, fallback to extraction."""
    if ai_key_points:
        return "\n".join(f"- {point}" for point in ai_key_points)

    # Extractive fallback: lines that look like key-value pairs or bullet points
    lines = content.strip().split("\n")
    key_lines = []

    for line in lines:
        stripped = line.strip()
        if not stripped:
            continue

        # Keep lines that look like key info:
        # - Bullet points
        # - Key: value pairs
        # - Short declarative statements
        is_bullet = stripped.startswith(("-", "*", "•", "→"))
        is_kv = ":" in stripped and len(stripped) < 150
        is_short = len(stripped) < 120

        if is_bullet or is_kv or is_short:
            key_lines.append(stripped)

    if not key_lines:
        # Fallback: first 3 lines
        key_lines = [l.strip() for l in lines[:3] if l.strip()]

    return "\n".join(key_lines[:15])  # Max 15 key points
