"""Shared context helpers used across language handlers."""

import re

from aiservice.common.markdown_utils import split_markdown_code

__all__ = [
    "extract_code_and_explanation",
    "group_code",
    "is_markdown_structure_changed",
    "normalize_c_style_code",
    "split_markdown_code",
]


def normalize_c_style_code(code: str) -> str:
    """Normalize C-style code for comparison by stripping comments and whitespace.

    Works for JavaScript, TypeScript, and Java.
    """
    code = re.sub(r"//.*$", "", code, flags=re.MULTILINE)
    code = re.sub(r"/\*.*?\*/", "", code, flags=re.DOTALL)
    return " ".join(code.split())


def extract_code_and_explanation(
    content: str, code_pattern: re.Pattern[str], code_with_path_pattern: re.Pattern[str], is_multi_file: bool = False
) -> tuple[str | dict[str, str], str]:
    """Extract code and explanation from LLM response.

    Works for any language by accepting compiled regex patterns.
    """
    if is_multi_file:
        matches = code_with_path_pattern.findall(content)
        if matches:
            file_to_code: dict[str, str] = {}
            first_match_pos = content.find("```")
            explanation = content[:first_match_pos].strip() if first_match_pos > 0 else ""
            for file_path, code in matches:
                file_to_code[file_path.strip()] = code.strip()
            return file_to_code, explanation
        return extract_code_and_explanation(content, code_pattern, code_with_path_pattern, is_multi_file=False)

    match = code_pattern.search(content)
    if match:
        code = match.group(1).strip()
        explanation = content[: match.start()].strip()
        return code, explanation

    return "", content


def is_markdown_structure_changed(old: str, new: str, language: str = "python") -> bool:
    old_files = split_markdown_code(old, language).keys()
    new_files = split_markdown_code(new, language).keys()
    return old_files != new_files


def group_code(file_to_code: dict[str, str], language: str = "python") -> str:
    def format_block(file_path: str, code: str) -> str:
        # Ensure the code ends with a newline before the closing ```
        normalized = code if code.endswith("\n") else code + "\n"
        return f"```{language}:{file_path}\n{normalized}```"

    return "\n".join(format_block(path, code) for path, code in file_to_code.items())
