import hashlib
from typing import List

from app.models.chunk import DocChunk
from app.models.document import RepoDocumentSection


class TextChunker:
    """
    Splits document sections into overlapping fixed-size chunks.
    Tries to break at sentence boundaries when possible.
    """

    def __init__(self, chunk_size: int = 1000, chunk_overlap: int = 200):
        self.chunk_size = chunk_size
        self.chunk_overlap = chunk_overlap

    def chunk_sections(
        self,
        sections: List[RepoDocumentSection],
        repo_id: str,
        doc_path: str,
    ) -> List[DocChunk]:
        chunks: List[DocChunk] = []
        for section in sections:
            if not section.content.strip():
                continue
            for idx, chunk_text in enumerate(self._split_text(section.content)):
                chunk_hash = hashlib.sha256(chunk_text.encode()).hexdigest()
                chunks.append(
                    DocChunk(
                        repo_id=repo_id,
                        doc_path=doc_path,
                        section_title=section.section_title,
                        chunk_text=chunk_text,
                        chunk_hash=chunk_hash,
                        source_type="repo_doc",
                        metadata={
                            "section_level": section.section_level,
                            "heading": section.heading,
                            "chunk_index": idx,
                        },
                    )
                )
        return chunks

    def _split_text(self, text: str) -> List[str]:
        if len(text) <= self.chunk_size:
            return [text]

        chunks: List[str] = []
        start = 0
        while start < len(text):
            end = min(start + self.chunk_size, len(text))
            if end < len(text):
                # Prefer a sentence boundary
                boundary = text.rfind(". ", start, end)
                if boundary > start:
                    end = boundary + 1
            chunk = text[start:end].strip()
            if chunk:
                chunks.append(chunk)
            if end >= len(text):
                break
            start = end - self.chunk_overlap
        return chunks
