"""
Pure diff functions for impact analysis.

Implements FR-8.2: Structural diff-based impact measurement.

Uses difflib.SequenceMatcher for computing change magnitude between
old and new content versions.
"""

import difflib
from typing import Optional


def structural_diff_ratio(old_content: str, new_content: str) -> float:
    """
    Calculate structural similarity ratio between old and new content.

    Uses SequenceMatcher to compute a ratio of matching blocks.
    Returns the *change* ratio (1.0 - similarity), so higher values
    mean more change.

    Args:
        old_content: Previous content
        new_content: Current content

    Returns:
        Change ratio from 0.0 (identical) to 1.0 (completely different)
    """
    if old_content == new_content:
        return 0.0
    if not old_content and not new_content:
        return 0.0
    if not old_content or not new_content:
        return 1.0

    matcher = difflib.SequenceMatcher(None, old_content, new_content)
    similarity = matcher.ratio()
    return 1.0 - similarity


def line_diff_ratio(old_content: str, new_content: str) -> float:
    """
    Calculate line-level change ratio between old and new content.

    Splits content into lines and computes SequenceMatcher ratio
    at the line level. Returns the change ratio.

    Args:
        old_content: Previous content
        new_content: Current content

    Returns:
        Change ratio from 0.0 (identical) to 1.0 (completely different)
    """
    if old_content == new_content:
        return 0.0
    if not old_content and not new_content:
        return 0.0
    if not old_content or not new_content:
        return 1.0

    old_lines = old_content.splitlines()
    new_lines = new_content.splitlines()
    matcher = difflib.SequenceMatcher(None, old_lines, new_lines)
    similarity = matcher.ratio()
    return 1.0 - similarity


def calculate_change_magnitude(
    old_content: Optional[str],
    new_content: Optional[str],
    method: str = "structural",
) -> float:
    """
    Calculate the magnitude of a change between two content versions.

    This is the primary entry point for impact measurement (FR-8.2).

    Args:
        old_content: Previous content (None for created artifacts)
        new_content: Current content (None for deleted artifacts)
        method: Diff method to use ("structural" or "line")

    Returns:
        Change magnitude from 0.0 (no change) to 1.0 (complete change)
    """
    # Handle None cases (creation/deletion)
    if old_content is None and new_content is None:
        return 0.0
    if old_content is None or new_content is None:
        return 1.0

    if method == "line":
        return line_diff_ratio(old_content, new_content)
    return structural_diff_ratio(old_content, new_content)
