from typing import Any

from mirage.accessor.chroma import ChromaAccessor
from mirage.commands.builtin.chroma import COMMANDS
from mirage.core.chroma.read import read_bytes, read_stream
from mirage.core.chroma.readdir import readdir
from mirage.core.chroma.stat import stat
from mirage.ops.chroma import OPS as CHROMA_VFS_OPS
from mirage.resource.base import BaseResource
from mirage.resource.chroma.config import ChromaConfig
from mirage.resource.chroma.prompt import PROMPT
from mirage.types import PathSpec, ResourceName
from mirage.utils.glob_walk import make_resolve_glob

_resolve_glob = make_resolve_glob(readdir)

_CHROMA_OPS = {
    "read_bytes": read_bytes,
    "read_stream": read_stream,
    "readdir": readdir,
    "stat": stat,
}


class ChromaResource(BaseResource):

    accessor: ChromaAccessor
    name: str = ResourceName.CHROMA
    caches_reads: bool = False
    # Every file is sized exactly, by one chunk scan per directory the
    # caller stats; the path tree's own size is the producer's source
    # number and never becomes the reported byte length.
    SIZES_ALWAYS_KNOWN: bool = True
    _ops = _CHROMA_OPS
    PROMPT: str = PROMPT
    SUPPORTS_SNAPSHOT: bool = False

    def __init__(self, config: ChromaConfig) -> None:
        super().__init__()
        self.config = config
        self.accessor = ChromaAccessor(config)

        for fn in COMMANDS:
            self.register(fn)
        for fn in CHROMA_VFS_OPS:
            self.register_op(fn)

    async def resolve_glob(
        self,
        paths: list[PathSpec],
        prefix: str = '',
    ) -> list[PathSpec]:
        return await _resolve_glob(self.accessor, paths, index=self._index)

    def get_state(self) -> dict[str, Any]:
        return {
            "type": self.name,
            "needs_override": True,
            "redacted_fields": [],
            "config": self.config.model_dump(),
        }

    def load_state(self, state: dict[str, Any]) -> None:
        pass
