from __future__ import annotations

from dataclasses import dataclass
from typing import Any


@dataclass(frozen=True)
class Chunk:
    id: str
    relpath: str
    start_line: int
    end_line: int
    text: str
    file_hash: str
    vector_idx: int | None = None

    def to_dict(self) -> dict[str, Any]:
        return {
            "id": self.id,
            "relpath": self.relpath,
            "start_line": self.start_line,
            "end_line": self.end_line,
            "text": self.text,
            "file_hash": self.file_hash,
            "vector_idx": self.vector_idx,
        }

    @staticmethod
    def from_dict(data: dict[str, Any]) -> "Chunk":
        return Chunk(
            id=data["id"],
            relpath=data["relpath"],
            start_line=int(data["start_line"]),
            end_line=int(data["end_line"]),
            text=data["text"],
            file_hash=data["file_hash"],
            vector_idx=data.get("vector_idx"),
        )


@dataclass(frozen=True)
class SearchResult:
    relpath: str
    start_line: int
    end_line: int
    score: float
    snippet: str


@dataclass
class IndexMeta:
    repo_id: str
    repo_path: str
    created_at: str
    updated_at: str
    embedding_provider: str
    model: str
    embedding_dim: int
    chunk_lines: int
    chunk_overlap: int
    max_bytes: int
    files: dict[str, str]
    chunks: int

    def to_dict(self) -> dict[str, Any]:
        return {
            "repo_id": self.repo_id,
            "repo_path": self.repo_path,
            "created_at": self.created_at,
            "updated_at": self.updated_at,
            "embedding_provider": self.embedding_provider,
            "model": self.model,
            "embedding_dim": self.embedding_dim,
            "chunk_lines": self.chunk_lines,
            "chunk_overlap": self.chunk_overlap,
            "max_bytes": self.max_bytes,
            "files": self.files,
            "chunks": self.chunks,
        }

    @staticmethod
    def from_dict(data: dict[str, Any]) -> "IndexMeta":
        return IndexMeta(
            repo_id=data["repo_id"],
            repo_path=data["repo_path"],
            created_at=data["created_at"],
            updated_at=data["updated_at"],
            embedding_provider=data["embedding_provider"],
            model=data["model"],
            embedding_dim=int(data.get("embedding_dim", 0)),
            chunk_lines=int(data["chunk_lines"]),
            chunk_overlap=int(data["chunk_overlap"]),
            max_bytes=int(data["max_bytes"]),
            files={str(k): str(v) for k, v in data.get("files", {}).items()},
            chunks=int(data.get("chunks", 0)),
        )


@dataclass(frozen=True)
class IndexResult:
    repo_id: str
    chunks_indexed: int
    took_ms: int


@dataclass(frozen=True)
class IndexStatus:
    indexed: bool
    chunks: int
    last_index_time: str | None
    model: str | None
