"""Configuration management for AgenticlyPay."""

import os
import logging
from typing import Optional
from pydantic_settings import BaseSettings
from pydantic import Field, field_validator
from dotenv import load_dotenv

# Load environment variables from .env file
load_dotenv()

logger = logging.getLogger(__name__)


class Config(BaseSettings):
    """Application configuration."""

    # Stripe Configuration (required for payment processing)
    stripe_secret_key: Optional[str] = Field(None, description="Stripe secret key")
    stripe_webhook_secret: Optional[str] = Field(None, description="Stripe webhook secret")

    # Platform Configuration
    platform_fee_percentage: float = 0.065  # 6.5%
    platform_fee_fixed: int = 30  # $0.30 in cents
    platform_name: str = "AgenticlyPay"

    # API Configuration
    api_host: str = "0.0.0.0"
    api_port: int = 8000
    api_reload: bool = False

    # Frontend Configuration
    frontend_url: str = "https://agenticlypay.com"

    # Cloud Run Configuration
    project_id: Optional[str] = None
    region: str = "us-central1"
    backend_service_name: str = "agenticlypay-backend"
    frontend_service_name: str = "agenticlypay-frontend"

    # Square API Configuration
    square_application_id: Optional[str] = None
    square_access_token: Optional[str] = None
    square_location_id: Optional[str] = None
    square_environment: str = "production"  # or "sandbox"
    square_webhook_signature_key: Optional[str] = None

    # 1099 Tax Form Configuration
    payer_name: str = "AgenticlyPay"
    payer_tin: Optional[str] = None  # Business EIN
    payer_address_street: Optional[str] = None
    payer_address_city: Optional[str] = None
    payer_address_state: Optional[str] = None
    payer_address_zip: Optional[str] = None
    payer_phone: Optional[str] = None

    class Config:
        env_file = ".env"
        env_file_encoding = "utf-8"
        case_sensitive = False
        extra = "ignore"  # Ignore extra fields from .env file

    def validate_required(self, require_stripe: bool = True, require_square: bool = False):
        """Validate that required configuration is present.
        
        Args:
            require_stripe: Whether Stripe config is required (default: True)
            require_square: Whether Square config is required (default: False)
        
        Raises:
            ConfigurationError: If required configuration is missing
        """
        # Import here to avoid circular import
        from agenticlypay.api.exceptions import ConfigurationError
        
        errors = []
        
        if require_stripe:
            if not self.stripe_secret_key:
                errors.append("STRIPE_SECRET_KEY is required for payment processing")
            if not self.stripe_webhook_secret:
                errors.append("STRIPE_WEBHOOK_SECRET is required for webhook verification")
        
        if require_square:
            if not self.square_access_token:
                errors.append("SQUARE_ACCESS_TOKEN is required for Square payouts")
        
        if errors:
            raise ConfigurationError(
                f"Configuration errors: {'; '.join(errors)}. "
                "Please check your .env file or environment variables."
            )

    def calculate_fee(self, amount_cents: int) -> int:
        """
        Calculate platform fee for a transaction (developer-facing fee).
        
        This is the fee that developers pay: 6.5% + $0.30.
        Stripe fees are absorbed by AgenticlyPay.

        Args:
            amount_cents: Transaction amount in cents

        Returns:
            Fee amount in cents (6.5% + $0.30)
        """
        percentage_fee = int(amount_cents * self.platform_fee_percentage)
        return percentage_fee + self.platform_fee_fixed

    def estimate_stripe_fee(
        self,
        amount_cents: int,
        currency: str = "usd",
        is_international: bool = False,
        requires_conversion: bool = False,
    ) -> int:
        """
        Estimate Stripe processing fees for a transaction.
        
        Stripe fees vary by:
        - Payment method (card, ACH, etc.)
        - Card origin (domestic vs international)
        - Currency conversion
        
        This uses conservative estimates (worst case) to ensure we don't undercharge.

        Args:
            amount_cents: Transaction amount in cents
            currency: Currency code (default: usd)
            is_international: Whether card is issued outside merchant country
            requires_conversion: Whether currency conversion is needed

        Returns:
            Estimated Stripe fee in cents
        """
        # Base Stripe fee for online card payments (domestic)
        # 2.9% + $0.30
        base_percentage = 0.029
        base_fixed = 30  # $0.30 in cents
        
        # Additional fees for international transactions
        if is_international:
            base_percentage += 0.015  # +1.5% for international cards
        
        if requires_conversion:
            base_percentage += 0.01  # +1.0% for currency conversion
        
        # Calculate fee
        percentage_fee = int(amount_cents * base_percentage)
        total_fee = percentage_fee + base_fixed
        
        return total_fee

    def calculate_application_fee(
        self,
        amount_cents: int,
        currency: str = "usd",
        is_international: bool = False,
        requires_conversion: bool = False,
    ) -> int:
        """
        Calculate application fee for Stripe Connect that absorbs Stripe fees.
        
        This ensures developers only pay 6.5% + $0.30 total, with AgenticlyPay
        absorbing all Stripe processing fees.

        Args:
            amount_cents: Transaction amount in cents
            currency: Currency code (default: usd)
            is_international: Whether card is issued outside merchant country
            requires_conversion: Whether currency conversion is needed

        Returns:
            Application fee amount in cents to charge via Stripe Connect
        """
        # Target: Developer pays only 6.5% + $0.30
        developer_fee = self.calculate_fee(amount_cents)
        target_developer_net = amount_cents - developer_fee
        
        # Estimate what Stripe will charge
        estimated_stripe_fee = self.estimate_stripe_fee(
            amount_cents, currency, is_international, requires_conversion
        )
        
        # Application fee = amount - developer_net - stripe_fee
        # This ensures developer receives exactly: amount - (6.5% + $0.30)
        # Formula: developer_net = amount - application_fee - stripe_fee
        # Therefore: application_fee = amount - developer_net - stripe_fee
        application_fee = amount_cents - target_developer_net - estimated_stripe_fee
        
        # Safety check: application fee should never be negative
        # If Stripe fees are very high (exceed amount - developer_fee), we'd get negative
        # In practice, this should never happen, but protect against edge cases
        if application_fee < 0:
            # Fallback: charge at least our platform fee (we'll absorb the loss)
            logger.warning(
                f"Estimated Stripe fee ({estimated_stripe_fee}) exceeds available amount "
                f"for transaction {amount_cents}. Using platform fee as minimum."
            )
            application_fee = developer_fee
        
        return application_fee

    def calculate_net_amount(self, amount_cents: int) -> int:
        """
        Calculate net amount after platform fee.

        Args:
            amount_cents: Transaction amount in cents

        Returns:
            Net amount in cents (amount - fee)
        """
        fee = self.calculate_fee(amount_cents)
        return amount_cents - fee


# Global config instance
config = Config()

