"""
LangChain Tool for generating MercadoPago payment links.
"""
from typing import Optional, Type
from langchain.tools import BaseTool
from langchain.callbacks.manager import CallbackManagerForToolRun
from pydantic import BaseModel, Field
from langchain_mercadopago_link.mercadopago_service import MercadoPagoService


class MercadoPagoPaymentToolInput(BaseModel):
    """Input schema for the MercadoPago Tool."""
    
    title: str = Field(description="Title of the product or service to pay")
    description: str = Field(description="Detailed description of the product or service")
    amount: float = Field(description="Payment amount")
    currency: str = Field(default="ARS", description="Payment currency (ARS, USD, EUR, etc.)")
    quantity: int = Field(default=1, description="Quantity of items")
    success_url: Optional[str] = Field(default=None, description="Redirect URL after successful payment")
    failure_url: Optional[str] = Field(default=None, description="Redirect URL after failed payment")
    pending_url: Optional[str] = Field(default=None, description="Redirect URL for pending payment")
    external_reference: Optional[str] = Field(default=None, description="External reference for the payment")


class MercadoPagoPaymentTool(BaseTool):
    """
    LangChain Tool for generating MercadoPago payment links.
    
    This tool allows LangChain agents to generate MercadoPago payment links
    integrated into their reasoning chains.
    
    Usage example:
        ```python
        from langchain_mercadopago_link import MercadoPagoPaymentTool
        
        tool = MercadoPagoPaymentTool(
            access_token="YOUR_ACCESS_TOKEN",
            local_id="YOUR_LOCAL_ID"
        )
        
        result = tool.run({
            "title": "Consultoría",
            "description": "Servicios de consultoría en desarrollo",
            "amount": 5000.0,
            "currency": "ARS"
        })
        ```
    """
    
    name: str = "mercadopago_payment_link_generator"
    description: str = (
        "Generates a MercadoPago payment link for a product or service. "
        "Requires title, description and amount. Currency defaults to ARS but can be changed. "
        "Returns a payment link that can be shared with the client."
    )
    args_schema: Type[BaseModel] = MercadoPagoPaymentToolInput
    
    access_token: str = Field(description="MercadoPago Access Token")
    local_id: Optional[str] = Field(default=None, description="MercadoPago Local ID")
    
    def __init__(self, access_token: str, local_id: Optional[str] = None, **kwargs):
        """
        Initializes the MercadoPago Tool.
        
        Args:
            access_token: MercadoPago Access Token
            local_id: MercadoPago Local ID (optional)
            **kwargs: Additional arguments for BaseTool
        """
        # Call super().__init__ first with required parameters
        super().__init__(
            access_token=access_token,
            local_id=local_id,
            **kwargs
        )
        
        # Initialize service after super().__init__
        # Use object.__setattr__ to avoid Pydantic validation
        service = MercadoPagoService(access_token, local_id)
        object.__setattr__(self, '_service', service)
    
    @property
    def service(self) -> MercadoPagoService:
        """
        Property to access the MercadoPago service.
        Useful when you need to use the service directly without going through the tool.
        """
        return getattr(self, '_service', None)
    
    def _run(
        self,
        title: str,
        description: str,
        amount: float,
        currency: str = "ARS",
        quantity: int = 1,
        success_url: Optional[str] = None,
        failure_url: Optional[str] = None,
        pending_url: Optional[str] = None,
        external_reference: Optional[str] = None,
        run_manager: Optional[CallbackManagerForToolRun] = None,
    ) -> str:
        """
        Executes the tool to generate a payment link.
        
        Args:
            title: Product/service title
            description: Product/service description
            amount: Payment amount
            currency: Currency (default: ARS)
            quantity: Quantity (default: 1)
            success_url: Success URL (optional)
            failure_url: Failure URL (optional)
            pending_url: Pending URL (optional)
            external_reference: External reference (optional)
            run_manager: Callback manager (optional)
        
        Returns:
            String with payment link or error message
        """
        # Get service using getattr to avoid Pydantic issues
        service = getattr(self, '_service', None)
        if service is None:
            # If it doesn't exist, create it
            service = MercadoPagoService(self.access_token, self.local_id)
            object.__setattr__(self, '_service', service)
        
        result = service.create_payment_link(
            title=title,
            description=description,
            amount=amount,
            currency=currency,
            quantity=quantity,
            success_url=success_url,
            failure_url=failure_url,
            pending_url=pending_url,
            external_reference=external_reference
        )
        
        if result.get("success"):
            payment_link = result.get("payment_link", "")
            preference_id = result.get("preference_id", "")
            return f"Payment link generated successfully:\nURL: {payment_link}\nPreference ID: {preference_id}"
        else:
            error = result.get("error", "Unknown error")
            return f"Error generating payment link: {error}"
    
    async def _arun(
        self,
        title: str,
        description: str,
        amount: float,
        currency: str = "ARS",
        quantity: int = 1,
        success_url: Optional[str] = None,
        failure_url: Optional[str] = None,
        pending_url: Optional[str] = None,
        external_reference: Optional[str] = None,
        run_manager: Optional[CallbackManagerForToolRun] = None,
    ) -> str:
        """
        Async version of the tool.
        
        Args:
            Same parameters as _run
        
        Returns:
            String with payment link or error message
        """
        # For now, execute synchronously
        return self._run(
            title=title,
            description=description,
            amount=amount,
            currency=currency,
            quantity=quantity,
            success_url=success_url,
            failure_url=failure_url,
            pending_url=pending_url,
            external_reference=external_reference,
            run_manager=run_manager
        )
