"""Main Validator class for AI document validation"""

import requests
from typing import Dict, Optional

from .exceptions import AuthenticationError, APIError
from .config import Config


class Validator:
    """
    AI Validator client for document validation and text extraction.
    
    Args:
        key (str): Your API key from the AI Validator dashboard
        pid (str): Your product ID
        mid (str): Your merchant ID (_id from users collection)
        timeout (int, optional): Request timeout in seconds. Default: 30
    
    Example:
        >>> validator = Validator(
        ...     key="sk_test_...",
        ...     pid="tnmc",
        ...     mid="USQDQVKC68"
        ... )
        >>> result = validator.extractText(
        ...     publicUrl="https://s3.../doc.pdf",
        ...     extra={"fc": "kyc", "fid": "123"}
        ... )
    """
    
    def __init__(
        self,
        key: str,
        pid: str,
        mid: str,
        timeout: int = Config.DEFAULT_TIMEOUT
    ):
        if not key:
            raise AuthenticationError("API key is required")
        if not pid:
            raise ValueError("Product ID is required")
        if not mid:
            raise ValueError("Merchant ID is required")
        
        self.key = key
        self.pid = pid
        self.mid = mid
        self.timeout = timeout
        self.baseUrl = Config.BASE_URL
        self.queueEndpoint = f"{self.baseUrl}{Config.QUEUE_ENDPOINT}"
    
    def _getHeaders(self) -> Dict[str, str]:
        """Get request headers with authentication"""
        return {
            "Content-Type": "application/json",
            "X-API-Key": self.key
        }
    
    def _submitValidationRequest(
        self,
        publicUrl: str,
        service: str,
        extra: Optional[Dict] = None
    ) -> Dict:
        """Submit validation request to the queue"""
        
        payload = {
            "productId": self.pid,
            "userKey": self.mid,
            "accessKey": self.key,
            "service": service,
            "publicUrl": publicUrl,
        }
        
        # Merge extra fields if provided
        if extra:
            payload.update(extra)
        
        response = requests.post(
            self.queueEndpoint,
            json=payload,
            headers=self._getHeaders(),
            timeout=self.timeout
        )
        
        if response.status_code != 200:
            raise APIError(
                f"API request failed with status {response.status_code}",
                statusCode=response.status_code,
                response=response.text
            )
        
        data = response.json()
        
        if data.get("status") == 0:
            raise APIError(
                data.get("msg", "Request failed"),
                statusCode=response.status_code,
                response=data
            )
        
        return data
    
    def extractText(
        self,
        publicUrl: str,
        extra: Optional[Dict] = None
    ) -> Dict:
        """
        Extract text from a document.
        
        Args:
            publicUrl (str): Public URL of the document (from your S3/storage)
            extra (dict, optional): Additional fields (fc, fid, uid, ruid, aid, rid, formValues, etc.)
        
        Returns:
            dict: Response with queued task information
            
        Example:
            >>> result = validator.extractText(
            ...     publicUrl="https://s3.../doc.pdf",
            ...     extra={
            ...         "fc": "kyc",
            ...         "fid": "123",
            ...         "uid": "user_456",
            ...         "formValues": {"field1": "value1"}
            ...     }
            ... )
        """
        return self._submitValidationRequest(
            publicUrl=publicUrl,
            service="textExtraction",
            extra=extra
        )
    
    def validateFace(
        self,
        publicUrl: str,
        referencePhotoUrl: Optional[str] = None,
        extra: Optional[Dict] = None
    ) -> Dict:
        """
        Validate face in a document.
        
        Args:
            publicUrl (str): Public URL of the document
            referencePhotoUrl (str, optional): URL of reference photo for face comparison
            extra (dict, optional): Additional fields
        
        Returns:
            dict: Response with queued task information
        """
        extraData = extra.copy() if extra else {}
        
        if referencePhotoUrl:
            if 'formValues' not in extraData:
                extraData['formValues'] = {}
            extraData['formValues']['referencePhoto'] = referencePhotoUrl
        
        return self._submitValidationRequest(
            publicUrl=publicUrl,
            service="faceValidation",
            extra=extraData
        )
    
    def validateDocument(
        self,
        publicUrl: str,
        referencePhotoUrl: Optional[str] = None,
        extractText: bool = True,
        validateFace: bool = False,
        extra: Optional[Dict] = None
    ) -> Dict:
        """
        Perform combined document validation (text + face).
        
        Args:
            publicUrl (str): Public URL of the document
            referencePhotoUrl (str, optional): URL of reference photo for face comparison
            extractText (bool): Whether to extract text. Default: True
            validateFace (bool): Whether to validate face. Default: False
            extra (dict, optional): Additional fields
        
        Returns:
            dict: Response with queued task information
        """
        if extractText and validateFace:
            service = "fullValidation"
        elif extractText:
            service = "textExtraction"
        elif validateFace:
            service = "faceValidation"
        else:
            raise ValueError("At least one of extractText or validateFace must be True")
        
        extraData = extra.copy() if extra else {}
        
        if referencePhotoUrl and validateFace:
            if 'formValues' not in extraData:
                extraData['formValues'] = {}
            extraData['formValues']['referencePhoto'] = referencePhotoUrl
        
        return self._submitValidationRequest(
            publicUrl=publicUrl,
            service=service,
            extra=extraData
        )