"""
Intelligence Analyzer - LLM-powered intelligence analysis

Provides AI-powered query refinement, result filtering, and comprehensive
intelligence analysis for OSINT investigations.
"""

import json
from dataclasses import dataclass, field
from datetime import datetime
from typing import Optional

from groknroll.osint.content_scraper import ScrapedContent
from groknroll.osint.dark_web_search import SearchResult


@dataclass
class IntelligenceReport:
    """Represents an intelligence analysis report."""

    query: str
    refined_query: str
    summary: str
    key_findings: list[str]
    threat_indicators: list[str]
    recommendations: list[str]
    sources_analyzed: int
    artifacts_found: int
    generated_at: datetime = field(default_factory=datetime.utcnow)

    def to_dict(self) -> dict:
        """Convert to dictionary."""
        return {
            "query": self.query,
            "refined_query": self.refined_query,
            "summary": self.summary,
            "key_findings": self.key_findings,
            "threat_indicators": self.threat_indicators,
            "recommendations": self.recommendations,
            "sources_analyzed": self.sources_analyzed,
            "artifacts_found": self.artifacts_found,
            "generated_at": self.generated_at.isoformat(),
        }


class IntelligenceAnalyzer:
    """
    LLM-powered intelligence analysis for OSINT investigations.

    Provides:
    - Query refinement for better search results
    - Relevance-based result filtering
    - Comprehensive intelligence analysis
    - Report generation

    Usage:
        analyzer = IntelligenceAnalyzer(backend="anthropic")
        refined = analyzer.refine_query("lockbit ransomware")
        filtered = analyzer.filter_results(results, query, top_k=20)
        report = analyzer.analyze_content(contents, query)
    """

    # System prompts for different analysis tasks
    REFINE_QUERY_PROMPT = """You are a Cybercrime Threat Intelligence Expert \
specializing in dark web investigations.

Your task is to refine search queries for dark web search engines to maximize relevant results.

Guidelines:
- Focus on key terms that will appear in dark web content
- Remove common words that add noise
- Keep the query concise (max 5 words)
- Do not use boolean operators (AND, OR, NOT)
- Consider aliases, codenames, and common misspellings

Respond with ONLY the refined query, nothing else."""

    FILTER_RESULTS_PROMPT = """You are a Cybercrime Threat Intelligence Expert.

Analyze the following search results and select the most relevant ones for the investigation query.

Investigation Query: {query}

Search Results:
{results}

Select up to {top_k} most relevant results based on:
1. Direct relevance to the investigation topic
2. Likelihood of containing actionable intelligence
3. Source credibility indicators
4. Recency signals

Respond with ONLY a JSON array of indices (0-based) of the selected results, e.g., [0, 3, 5, 7]"""

    ANALYZE_CONTENT_PROMPT = """You are a Cybercrime Threat Intelligence Expert \
conducting an OSINT investigation.

Investigation Query: {query}

Analyze the following scraped content and generate a comprehensive intelligence report.

Content:
{content}

Extracted Artifacts:
{artifacts}

Generate a detailed intelligence report including:
1. Executive Summary (2-3 sentences)
2. Key Findings (bullet points)
3. Threat Indicators (IOCs, TTPs, infrastructure)
4. Recommended Actions (next investigation steps)

Format your response as JSON with keys:
- summary: string
- key_findings: array of strings
- threat_indicators: array of strings
- recommendations: array of strings"""

    def __init__(
        self,
        backend: str = "anthropic",
        model: str = "claude-sonnet-4-20250514",
        max_tokens: int = 4096,
    ):
        """
        Initialize intelligence analyzer.

        Args:
            backend: LLM backend ('anthropic', 'openai', 'google')
            model: Model identifier
            max_tokens: Maximum tokens for responses
        """
        self.backend = backend
        self.model = model
        self.max_tokens = max_tokens
        self._client = None

    def _get_client(self):
        """Get or create LLM client."""
        if self._client is not None:
            return self._client

        if self.backend == "anthropic":
            import anthropic

            self._client = anthropic.Anthropic()
        elif self.backend == "openai":
            import openai

            self._client = openai.OpenAI()
        elif self.backend == "google":
            import google.generativeai as genai

            self._client = genai
        else:
            raise ValueError(f"Unsupported backend: {self.backend}")

        return self._client

    def _call_llm(self, system: str, user: str) -> str:
        """
        Make LLM API call.

        Args:
            system: System prompt
            user: User message

        Returns:
            LLM response text
        """
        client = self._get_client()

        if self.backend == "anthropic":
            response = client.messages.create(
                model=self.model,
                max_tokens=self.max_tokens,
                system=system,
                messages=[{"role": "user", "content": user}],
            )
            return response.content[0].text

        elif self.backend == "openai":
            response = client.chat.completions.create(
                model=self.model,
                max_tokens=self.max_tokens,
                messages=[
                    {"role": "system", "content": system},
                    {"role": "user", "content": user},
                ],
            )
            return response.choices[0].message.content

        elif self.backend == "google":
            model = client.GenerativeModel(self.model)
            response = model.generate_content(f"{system}\n\n{user}")
            return response.text

        raise ValueError(f"Unsupported backend: {self.backend}")

    def refine_query(self, query: str) -> str:
        """
        Use LLM to optimize search query for dark web engines.

        Args:
            query: Original search query

        Returns:
            Refined search query
        """
        try:
            response = self._call_llm(
                system=self.REFINE_QUERY_PROMPT,
                user=f"Original query: {query}",
            )
            # Clean up response
            refined = response.strip().strip("\"'")
            # Validate response length
            if len(refined) > 100:
                return query  # Fallback to original
            return refined
        except Exception:
            return query  # Fallback to original on error

    def filter_results(
        self,
        results: list[SearchResult],
        query: str,
        top_k: int = 20,
    ) -> list[SearchResult]:
        """
        Use LLM to filter and rank search results by relevance.

        Args:
            results: List of search results to filter
            query: Investigation query
            top_k: Maximum results to return

        Returns:
            Filtered and ranked list of SearchResult objects
        """
        if len(results) <= top_k:
            return results

        # Format results for LLM
        results_text = "\n".join(
            f"{i}. {r.title[:50]} - {r.url[:60]}"
            for i, r in enumerate(results[:100])  # Limit input size
        )

        prompt = self.FILTER_RESULTS_PROMPT.format(
            query=query,
            results=results_text,
            top_k=top_k,
        )

        try:
            response = self._call_llm(
                system="You are a relevance filtering assistant. Respond only with JSON.",
                user=prompt,
            )

            # Parse indices from response
            indices = json.loads(response.strip())
            if isinstance(indices, list):
                filtered = [results[i] for i in indices if i < len(results)]
                # Update relevance scores
                for rank, result in enumerate(filtered):
                    result.relevance_score = 1.0 - (rank / len(filtered))
                return filtered

        except Exception:
            pass

        # Fallback: return first top_k results
        return results[:top_k]

    def analyze_content(
        self,
        contents: list[ScrapedContent],
        query: str,
        artifacts: Optional[list[dict]] = None,
    ) -> IntelligenceReport:
        """
        Generate comprehensive intelligence report from scraped content.

        Args:
            contents: List of scraped content to analyze
            query: Investigation query
            artifacts: Optional list of extracted artifacts

        Returns:
            IntelligenceReport object
        """
        # Prepare content for analysis
        content_text = ""
        for i, content in enumerate(contents[:20], 1):  # Limit to 20 sources
            if content.success and content.content:
                truncated = content.content[:1000]
                content_text += f"\n--- Source {i}: {content.url} ---\n"
                content_text += f"Title: {content.title}\n"
                content_text += f"Content: {truncated}\n"

        # Format artifacts
        artifacts_text = "None extracted"
        if artifacts:
            artifacts_text = json.dumps(artifacts[:50], indent=2)

        prompt = self.ANALYZE_CONTENT_PROMPT.format(
            query=query,
            content=content_text[:15000],  # Limit total content
            artifacts=artifacts_text[:3000],
        )

        try:
            response = self._call_llm(
                system="You are an intelligence analyst. Respond only with valid JSON.",
                user=prompt,
            )

            # Parse JSON response
            # Handle potential markdown code blocks
            if "```json" in response:
                response = response.split("```json")[1].split("```")[0]
            elif "```" in response:
                response = response.split("```")[1].split("```")[0]

            data = json.loads(response.strip())

            return IntelligenceReport(
                query=query,
                refined_query=query,
                summary=data.get("summary", "Analysis complete."),
                key_findings=data.get("key_findings", []),
                threat_indicators=data.get("threat_indicators", []),
                recommendations=data.get("recommendations", []),
                sources_analyzed=len(contents),
                artifacts_found=len(artifacts) if artifacts else 0,
            )

        except Exception as e:
            # Return basic report on error
            return IntelligenceReport(
                query=query,
                refined_query=query,
                summary=(
                    f"Analysis completed with {len(contents)} sources. "
                    f"Error during LLM analysis: {str(e)[:100]}"
                ),
                key_findings=[f"Analyzed {len(contents)} dark web sources"],
                threat_indicators=[],
                recommendations=["Review scraped content manually"],
                sources_analyzed=len(contents),
                artifacts_found=len(artifacts) if artifacts else 0,
            )
