"""Simple text plugin for indexing configuration and other text files."""

import hashlib
import logging
from pathlib import Path
from typing import Any, Dict, Iterable, Optional

from ..plugin_base import IndexShard, IPlugin, Reference, SearchResult, SymbolDef

logger = logging.getLogger(__name__)


class SimpleTextPlugin(IPlugin):
    """Simple plugin for indexing text files including configs and secrets."""

    def __init__(self, sqlite_store=None):
        """Initialize simple text plugin."""
        self.lang = "plaintext"
        self._sqlite_store = sqlite_store
        self._repository_id = 1  # Default repository ID

        # Extensions we support
        self.extensions = {
            ".txt",
            ".text",
            ".log",
            ".env",
            ".key",
            ".pem",
            ".crt",
            ".cer",
            ".pfx",
            ".p12",
            ".pub",
            ".pri",
            ".license",
            ".version",
            ".gitignore",
            ".dockerignore",
            ".npmignore",
            ".conf",
            ".cfg",
            ".ini",
            ".properties",
            ".sh",
            ".bash",
            ".zsh",
        }

        # Filenames without extensions
        self.exact_filenames = {
            "Dockerfile",
            "Makefile",
            "Procfile",
            "Gemfile",
            "Rakefile",
            "LICENSE",
            "README",
            "CHANGELOG",
            "TODO",
            "AUTHORS",
            ".env",
            ".env.local",
            ".env.production",
            ".env.development",
        }

    def supports(self, path: Path) -> bool:
        """Check if this plugin supports the given file."""
        # Check extensions
        if path.suffix.lower() in self.extensions:
            return True

        # Check exact filenames
        if path.name in self.exact_filenames:
            return True

        # Check patterns
        name_lower = path.name.lower()
        patterns = ["dockerfile", "makefile", ".env", "readme", "license"]
        if any(pattern in name_lower for pattern in patterns):
            return True

        return False

    def indexFile(self, path: Path, content: str) -> IndexShard:
        """Index a text file."""
        logger.info(f"Indexing text file: {path}")

        # Create basic shard as a dict (expected by dispatcher)
        shard = {
            "file": str(path),
            "language": "plaintext",
            "doc": f"Plain text file: {path.name}",
            "symbols": [],
            "content": content,
        }

        # For .env files, extract variables as symbols
        if ".env" in path.name:
            lines = content.splitlines()
            for i, line in enumerate(lines):
                line = line.strip()
                if line and not line.startswith("#") and "=" in line:
                    key = line.split("=", 1)[0].strip()
                    if key:
                        symbol = {
                            "name": key,
                            "kind": "variable",
                            "signature": line,
                            "doc": f"Environment variable in {path.name}",
                            "defined_in": str(path),
                            "line": i + 1,
                            "span": (i + 1, i + 1),
                        }
                        shard["symbols"].append(symbol)

        # Store in SQLite if available
        if self._sqlite_store:
            try:
                file_hash = hashlib.sha256(content.encode("utf-8")).hexdigest()
                file_id = self._sqlite_store.store_file(
                    self._repository_id,
                    str(path),
                    str(path.relative_to(Path.cwd()) if path.is_absolute() else path),
                    language="plaintext",
                    size=len(content),
                    hash=file_hash,
                )

                # Store symbols
                for symbol in shard["symbols"]:
                    self._sqlite_store.store_symbol(
                        file_id,
                        symbol["name"],
                        symbol["kind"],
                        line_start=symbol["line"],
                        line_end=symbol["line"],
                        column_start=0,
                        column_end=None,
                        signature=symbol.get("signature", ""),
                        documentation=symbol.get("doc", ""),
                    )

            except Exception as e:
                logger.error(f"Failed to store {path} in SQLite: {e}")

        return shard

    def getDefinition(self, symbol: str) -> Optional[SymbolDef]:
        """Get definition of a symbol."""
        if not self._sqlite_store:
            return None

        try:
            result = self._sqlite_store.get_definition(symbol, "plaintext")
            if result:
                return SymbolDef(
                    name=result["symbol"],
                    kind=result.get("kind", "variable"),
                    signature=result.get("signature", symbol),
                    doc=result.get("doc", ""),
                    defined_in=result["defined_in"],
                    line=result.get("line", 1),
                    span=(result.get("line", 1), result.get("line", 1)),
                )
        except Exception as e:
            logger.error(f"Error getting definition for {symbol}: {e}")

        return None

    def search(self, query: str, opts: Dict[str, Any] = None) -> Iterable[SearchResult]:
        """Search for text in files."""
        if not self._sqlite_store:
            return []

        opts = opts or {}
        limit = opts.get("limit", 20)

        try:
            results = self._sqlite_store.search(query, "plaintext", limit)
            for result in results:
                yield SearchResult(
                    file=result["file"],
                    start_line=result["line"],
                    end_line=result["line"],
                    snippet=result["snippet"],
                    score=result.get("score", 0.5),
                    kind=result.get("kind", "text"),
                )
        except Exception as e:
            logger.error(f"Error searching for {query}: {e}")
            return []

    def findReferences(self, symbol: str) -> Iterable[Reference]:
        """Find references to a symbol."""
        # For text files, we can search for the symbol as text
        if not self._sqlite_store:
            return []

        try:
            results = self._sqlite_store.search(symbol, "plaintext", 50)
            for result in results:
                yield Reference(
                    file=result["file"],
                    line=result["line"],
                    span=(result["line"], result["line"]),
                    kind="text",
                )
        except Exception as e:
            logger.error(f"Error finding references for {symbol}: {e}")
            return []
