"""
VitalGraph Client Triples Endpoint

Client-side implementation for Triples operations.
"""

import httpx
from typing import Dict, Any, Optional, List

from .base_endpoint import BaseEndpoint
from ..utils.client_utils import VitalGraphClientError, validate_required_params, build_query_params
from ...model.quad_model import QuadRequest
from ...model.triples_model import (
    TripleListResponse, TripleOperationResponse, TripleListRequest
)


class TriplesEndpoint(BaseEndpoint):
    """Client endpoint for Triples operations."""
    
    async def list_triples(self, space_id: str, graph_id: str, page_size: int = 10, offset: int = 0, 
                    subject: Optional[str] = None, predicate: Optional[str] = None, 
                    object: Optional[str] = None, object_filter: Optional[str] = None) -> TripleListResponse:
        """
        List/Search triples with optional filtering.
        
        Args:
            space_id: Space identifier
            graph_id: Graph identifier
            page_size: Number of triples per page
            offset: Offset for pagination
            subject: Subject URI filter (optional)
            predicate: Predicate URI filter (optional)
            object: Object value filter (optional)
            object_filter: Keyword to search within object values (optional)
            
        Returns:
            TripleListResponse containing triples data and pagination info
            
        Raises:
            VitalGraphClientError: If request fails
        """
        self._check_connection()
        validate_required_params(space_id=space_id, graph_id=graph_id)
        
        url = f"{self._get_server_url().rstrip('/')}/api/graphs/triples"
        params = build_query_params(
            space_id=space_id,
            graph_id=graph_id,
            page_size=page_size,
            offset=offset,
            subject=subject,
            predicate=predicate,
            object=object,
            object_filter=object_filter
        )
        
        return await self._make_typed_request('GET', url, TripleListResponse, params=params)
    
    async def add_triples(self, space_id: str, graph_id: str, quad_request: QuadRequest) -> TripleOperationResponse:
        """
        Add triples/quads to a graph. Operates at the raw triples level — no GraphObject validation.
        
        Args:
            space_id: Space identifier
            graph_id: Graph identifier
            quad_request: QuadRequest containing raw quads to add
            
        Returns:
            TripleOperationResponse containing operation result
            
        Raises:
            VitalGraphClientError: If request fails
        """
        self._check_connection()
        validate_required_params(space_id=space_id, graph_id=graph_id, quad_request=quad_request)
        
        url = f"{self._get_server_url().rstrip('/')}/api/graphs/triples"
        params = build_query_params(
            space_id=space_id,
            graph_id=graph_id
        )
        
        response = await self._make_authenticated_request(
            'POST', url, params=params, json=quad_request.model_dump()
        )
        return TripleOperationResponse.model_validate(response.json())
    
    async def delete_triples(self, space_id: str, graph_id: str, 
                      subject: Optional[str] = None, predicate: Optional[str] = None, 
                      object: Optional[str] = None) -> TripleOperationResponse:
        """
        Delete triples from a graph by pattern.
        
        Resolves the pattern to concrete quads via list_triples, then sends
        them as a QuadRequest body to the server DELETE endpoint.
        
        Args:
            space_id: Space identifier
            graph_id: Graph identifier
            subject: Subject URI filter for pattern-based deletion (optional)
            predicate: Predicate URI filter for pattern-based deletion (optional)
            object: Object value filter for pattern-based deletion (optional)
            
        Returns:
            TripleOperationResponse containing operation result
            
        Raises:
            VitalGraphClientError: If request fails
        """
        self._check_connection()
        validate_required_params(space_id=space_id, graph_id=graph_id)
        
        # Validate that at least one pattern filter is provided
        if not any([subject, predicate, object]):
            raise VitalGraphClientError("At least one pattern filter (subject/predicate/object) must be provided for deletion")
        
        # Resolve pattern to concrete quads by listing matching triples
        matching = await self.list_triples(
            space_id, graph_id, page_size=100,
            subject=subject, predicate=predicate, object=object
        )
        
        if not matching.success or not matching.results:
            return TripleOperationResponse(
                success=True,
                message="No matching triples found to delete",
                affected_count=0
            )
        
        # Build QuadRequest from the matched quads
        quad_request = QuadRequest(quads=matching.results)
        
        url = f"{self._get_server_url().rstrip('/')}/api/graphs/triples"
        params = build_query_params(
            space_id=space_id,
            graph_id=graph_id
        )
        
        response = await self._make_authenticated_request(
            'DELETE', url, params=params, json=quad_request.model_dump()
        )
        return TripleOperationResponse.model_validate(response.json())
