"""
Extraction Service - AI-powered memory extraction from conversations
"""

from typing import List, Optional, Dict, Any
from dataclasses import dataclass


@dataclass
class ExtractedMemory:
    """Extracted memory from conversation"""
    content: str
    type: str  # 'preference', 'fact', 'pattern', 'error_fix', 'insight'
    context: str
    confidence: float
    source_text: Optional[str] = None
    metadata: Optional[Dict[str, Any]] = None


@dataclass
class ExtractionResult:
    """Result from memory extraction"""
    memories: List[ExtractedMemory]
    total_extracted: int
    stored_count: int
    skipped_count: int
    processing_time_ms: int


@dataclass
class ExtractMemoriesRequest:
    """Request for memory extraction"""
    conversation: str
    context: Optional[str] = None
    types: Optional[List[str]] = None
    auto_store: bool = True
    min_confidence: float = 0.7


class ExtractionService:
    """
    Extraction service for AI-powered memory extraction

    Automatically extracts valuable memories from conversations,
    including user preferences, facts, patterns, error fixes, and insights.
    """

    def __init__(self, client):
        self.client = client

    async def extract(self, request: ExtractMemoriesRequest) -> ExtractionResult:
        """
        Extract memories from a conversation

        Args:
            request: Extraction request with conversation and options

        Returns:
            Extraction result with extracted memories

        Example:
            ```python
            from xache.services.extraction import ExtractMemoriesRequest

            result = await client.extraction.extract(ExtractMemoriesRequest(
                conversation="User: I prefer dark mode for all apps.\\nAssistant: ...",
                context="user-preferences",
                auto_store=True,
                min_confidence=0.8
            ))

            print(f"Extracted {result.total_extracted} memories")
            for m in result.memories:
                print(f"  [{m.type}] {m.content} (confidence: {m.confidence})")
            ```
        """
        body = {
            "conversation": request.conversation,
            "autoStore": request.auto_store,
            "minConfidence": request.min_confidence,
        }

        if request.context:
            body["context"] = request.context
        if request.types:
            body["types"] = request.types

        response = await self.client.request("POST", "/v1/extraction/extract", body)

        if not response.success or not response.data:
            raise Exception(
                response.error.get("message", "Failed to extract memories")
                if response.error
                else "Failed to extract memories"
            )

        data = response.data
        return ExtractionResult(
            memories=[
                ExtractedMemory(
                    content=m["content"],
                    type=m["type"],
                    context=m.get("context", ""),
                    confidence=m["confidence"],
                    source_text=m.get("sourceText"),
                    metadata=m.get("metadata"),
                )
                for m in data.get("memories", [])
            ],
            total_extracted=data.get("totalExtracted", 0),
            stored_count=data.get("storedCount", 0),
            skipped_count=data.get("skippedCount", 0),
            processing_time_ms=data.get("processingTimeMs", 0),
        )

    async def analyze(self, conversation: str) -> Dict[str, Any]:
        """
        Analyze a conversation without storing memories

        Args:
            conversation: Conversation text to analyze

        Returns:
            Analysis result with potential memories

        Example:
            ```python
            analysis = await client.extraction.analyze(
                "User: I always use vim keybindings..."
            )

            print(f"Found {len(analysis['potentialMemories'])} potential memories")
            ```
        """
        response = await self.client.request(
            "POST", "/v1/extraction/analyze", {"conversation": conversation}
        )

        if not response.success or not response.data:
            raise Exception(
                response.error.get("message", "Failed to analyze conversation")
                if response.error
                else "Failed to analyze conversation"
            )

        return response.data

    async def get_types(self) -> List[Dict[str, Any]]:
        """
        Get supported memory types for extraction

        Returns:
            List of supported memory types with descriptions

        Example:
            ```python
            types = await client.extraction.get_types()
            for t in types:
                print(f"{t['type']}: {t['description']}")
            ```
        """
        response = await self.client.request(
            "GET", "/v1/extraction/types", skip_auth=True
        )

        if not response.success or not response.data:
            raise Exception(
                response.error.get("message", "Failed to get extraction types")
                if response.error
                else "Failed to get extraction types"
            )

        return response.data.get("types", [])
