"""AI-powered scanner — sends source files directly to Grok for vulnerability analysis."""

from __future__ import annotations

import logging
from pathlib import Path
from typing import Any

from secagent.llm.grok_client import GrokClient
from secagent.prompts import load as _load_prompt
from secagent.scanners.base_scanner import BaseScanner

logger = logging.getLogger(__name__)

_SYSTEM_PROMPT = _load_prompt("ai_scanner.txt")

_SKIP_DIRS = {".git", "__pycache__", "node_modules", ".venv", "venv", ".secagent"}
_SKIP_EXTENSIONS = {".pyc", ".pyo", ".so", ".dll", ".exe", ".bin", ".png", ".jpg", ".gif", ".ico", ".pdf"}


class AIScanner(BaseScanner):
    """LLM-powered scanner — no external tools required, just a Grok API key."""

    def __init__(self, client: GrokClient | None = None) -> None:
        self._client = client

    @property
    def name(self) -> str:
        return "ai-scanner"

    def is_available(self) -> bool:
        """Available as long as a Grok API key is configured."""
        import os
        return bool(os.getenv("GROK_API_KEY", ""))

    def run(self, target: Path) -> list[dict[str, Any]]:
        client = self._client or GrokClient()
        findings: list[dict[str, Any]] = []

        for file_path in self._collect_files(target):
            try:
                content = file_path.read_text(encoding="utf-8", errors="replace")
            except OSError:
                continue

            if not content.strip():
                continue

            logger.info("AI scanner analysing %s", file_path)
            user_prompt = f"File: {file_path}\n\n```\n{content}\n```"

            response = client.chat(
                system_prompt=_SYSTEM_PROMPT,
                user_prompt=user_prompt,
                json_mode=True,
                max_tokens=4096,
            )

            raw_vulns = response.get("vulnerabilities", []) if isinstance(response, dict) else []
            for v in raw_vulns:
                v["_file"] = str(file_path)
                findings.append(v)

            logger.info("AI scanner: %d finding(s) in %s", len(raw_vulns), file_path)

        return findings

    @staticmethod
    def _collect_files(target: Path) -> list[Path]:
        if target.is_file():
            if target.suffix not in _SKIP_EXTENSIONS:
                return [target]
            return []

        results: list[Path] = []
        for p in sorted(target.rglob("*")):
            if any(skip in p.parts for skip in _SKIP_DIRS):
                continue
            if p.is_file() and p.suffix not in _SKIP_EXTENSIONS:
                results.append(p)
        return results
