"""Payment processing routes."""

from fastapi import APIRouter, HTTPException, Header, Request
from pydantic import BaseModel, EmailStr, field_validator
from typing import Optional, Dict, Any, Literal
from slowapi import Limiter, _rate_limit_exceeded_handler
from slowapi.util import get_remote_address
from agenticlypay.payments import PaymentProcessor
from agenticlypay.utils.firestore_storage import FirestoreStorage
from agenticlypay.api.middleware.auth import resolve_email_from_auth
from agenticlypay.api.exceptions import (
    ValidationError,
    PaymentError,
    AuthenticationError,
)
from agenticlypay.api.validators import (
    validate_amount,
    validate_stripe_account_id,
    validate_currency,
)

router = APIRouter()
payment_processor = PaymentProcessor()
storage = FirestoreStorage()


class ProcessPaymentRequest(BaseModel):
    """Request model for processing a payment."""

    protocol: Literal["AUTO"]
    amount: int  # in cents
    currency: str = "usd"
    developer_account_id: str
    email: EmailStr  # Required for usage tracking (deprecated - use API token)
    metadata: Optional[Dict[str, Any]] = None
    description: Optional[str] = None
    mandate: Optional[Dict[str, Any]] = None  # Required for AP2
    resource_url: Optional[str] = None  # Optional for x402

    @field_validator("amount")
    @classmethod
    def validate_amount(cls, v: int) -> int:
        return validate_amount(v)

    @field_validator("developer_account_id")
    @classmethod
    def validate_account_id(cls, v: str) -> str:
        return validate_stripe_account_id(v)

    @field_validator("currency")
    @classmethod
    def validate_currency(cls, v: str) -> str:
        return validate_currency(v)


class ConfirmPaymentRequest(BaseModel):
    """Request model for confirming a payment."""

    protocol: Literal["AUTO"]
    payment_id: str
    payment_method: Optional[str] = None


def get_limiter(request: Request) -> Limiter:
    """Get rate limiter from app state."""
    return request.app.state.limiter


@router.post("/process")
async def process_payment(request: Request, payment_request: ProcessPaymentRequest):
    """Process a payment using the specified protocol.
    
    Note: Email in request body is deprecated. Use API token authentication instead.
    """
    # Resolve email from auth (API token preferred, fallback to email in body for backward compatibility)
    email = resolve_email_from_auth(request) or payment_request.email
    
    if not email:
        raise AuthenticationError("Authentication required. Use API token or provide email in request.")
    
    try:
        # Auto-detect protocol if requested
        protocol = payment_request.protocol
        if protocol.upper() == "AUTO":
            if payment_request.mandate is not None:
                protocol = "AP2"
            elif payment_request.resource_url is not None:
                protocol = "x402"
            else:
                protocol = "ACP"

        result = payment_processor.process_payment(
            protocol=protocol,
            amount=payment_request.amount,
            currency=payment_request.currency,
            developer_account_id=payment_request.developer_account_id,
            metadata=payment_request.metadata,
            description=payment_request.description,
            mandate=payment_request.mandate,
            resource_url=payment_request.resource_url,
        )
        
        # Log usage by email
        try:
            storage.log_usage(
                email=email,
                endpoint="POST /api/v1/payments/process",
                status_code=200,
            )
        except Exception:
            pass  # Don't fail payment if logging fails
        
        return {"success": True, "payment": result}
    except (ValidationError, PaymentError):
        # Re-raise custom exceptions
        raise
    except ValueError as e:
        # Log error usage
        try:
            storage.log_usage(
                email=email,
                endpoint="POST /api/v1/payments/process",
                status_code=400,
            )
        except Exception:
            pass
        raise PaymentError(f"Payment processing failed: {str(e)}")
    except Exception as e:
        # Log error usage
        try:
            storage.log_usage(
                email=email,
                endpoint="POST /api/v1/payments/process",
                status_code=500,
            )
        except Exception:
            pass
        # Don't expose internal errors - let global handler deal with it
        raise


@router.post("/confirm")
async def confirm_payment(request: Request, payment_request: ConfirmPaymentRequest):
    """Confirm a payment."""
    # Resolve email from auth (API token or header)
    email = resolve_email_from_auth(request)
    if not email:
        raise AuthenticationError("Authentication required. Use API token or X-Developer-Email header.")
    
    try:
        result = payment_processor.confirm_payment(
            email=email,
            protocol=payment_request.protocol,
            payment_id=payment_request.payment_id,
            payment_method=payment_request.payment_method,
        )
        return {"success": True, "payment": result}
    except (ValidationError, PaymentError):
        raise
    except Exception as e:
        raise PaymentError(f"Payment confirmation failed: {str(e)}")


@router.get("/status/{protocol}/{payment_id}")
async def get_payment_status(request: Request, protocol: str, payment_id: str):
    """Get payment status.
    
    Note: Email query parameter is deprecated. Use API token authentication instead.
    """
    # Resolve email from auth (API token or header, no query param for security)
    email = resolve_email_from_auth(request)
    if not email:
        raise AuthenticationError("Authentication required. Use API token or X-Developer-Email header.")
    
    try:
        result = payment_processor.get_payment_status(
            email=email,
            protocol=protocol.upper(), 
            payment_id=payment_id
        )
        return {"success": True, "status": result}
    except (ValidationError, PaymentError):
        raise
    except Exception as e:
        raise PaymentError(f"Failed to get payment status: {str(e)}")


@router.get("/fee/{amount}")
async def calculate_fee(request: Request, amount: int):
    """Calculate platform fee for an amount.
    
    Returns the developer fee: 6.5% + $0.30 (Stripe fees are absorbed by AgenticlyPay).
    
    Note: Email query parameter is deprecated. Use API token authentication instead.
    """
    # Validate amount
    try:
        validate_amount(amount)
    except ValidationError:
        raise
    
    # Resolve email from auth (optional for fee calculation, but preferred)
    email = resolve_email_from_auth(request) or "anonymous"
    
    try:
        # Calculate developer fee (6.5% + $0.30) - Stripe fees are absorbed
        from agenticlypay.config import config
        
        developer_fee = config.calculate_fee(amount)
        net_amount = amount - developer_fee
        
        fee_response = {
            "amount": amount,
            "fee": developer_fee,
            "net_amount": net_amount,
            "fee_percentage": config.platform_fee_percentage,
            "fee_fixed": config.platform_fee_fixed,
            "note": "Stripe processing fees are included - no additional charges"
        }
        
        return {"success": True, "fee": fee_response}
    except Exception as e:
        raise ValidationError(f"Failed to calculate fee: {str(e)}")

