
import stripe
from flask import current_app
from decimal import Decimal
import logging

logger = logging.getLogger(__name__)

# Configure Stripe API settings for reliability and security
stripe.max_network_retries = 2
stripe.default_http_client = stripe.http_client.RequestsClient(timeout=30)

def validate_stripe_config():
    """Validate Stripe API configuration at startup - ONLY if payments are enabled"""
    
    # Check if payments feature is enabled
    features = current_app.config.get('FEATURES', {})
    if not features.get('payments', False):
        print("[INFO] Payments feature is disabled - skipping Stripe validation")
        return
    
    # Only validate if payments are enabled
    publishable_key = current_app.config.get('STRIPE_PUBLISHABLE_KEY')
    secret_key = current_app.config.get('STRIPE_SECRET_KEY')
    
    if not publishable_key:
        print("[WARNING] STRIPE_PUBLISHABLE_KEY not set - using dummy key for disabled payments")
        return
    if not secret_key:
        print("[WARNING] STRIPE_SECRET_KEY not set - using dummy key for disabled payments")
        return
    
    # Test API connectivity (graceful failure during deployment)
    stripe.api_key = secret_key
    try:
        stripe.Account.retrieve()
        print("[SUCCESS] Stripe API connection validated")
    except stripe.error.AuthenticationError:
        print("[WARNING] Stripe API credentials invalid - payment features will be disabled")
        print("   This is normal during deployment. Payment system will work when keys are valid.")
    except Exception as e:
        print(f"[WARNING] Stripe API connection failed: {str(e)}")
        print("   Payment system will retry connection when needed.")

class StripeService:
    """Stripe payment processing for Australian construction marketplace"""
    
    def __init__(self):
        # Initialize stripe.api_key only when needed, not at import time
        pass
    
    def _ensure_stripe_key(self):
        """Ensure Stripe API key is set before making API calls"""
        if not stripe.api_key:
            stripe.api_key = current_app.config.get('STRIPE_SECRET_KEY')
    
    def create_payment_intent(self, amount_aud, currency='aud', metadata=None, idempotency_key=None):
        """Create Stripe PaymentIntent for escrow payment"""
        self._ensure_stripe_key()
        try:
            # Convert to cents (Stripe uses smallest currency unit)
            # Use Decimal to avoid float precision issues
            amount_decimal = Decimal(str(amount_aud))
            amount_cents = int(amount_decimal * 100)
            
            # Validate amount is within Stripe limits
            if amount_cents <= 0:
                raise ValueError("Payment amount must be positive")
            if amount_cents > 99999999:  # Stripe maximum ~$999,999.99
                raise ValueError("Payment amount exceeds maximum allowed")
            
            intent_params = {
                'amount': amount_cents,
                'currency': currency,
                'metadata': metadata or {},
                'capture_method': 'manual',  # For escrow - capture later
                'description': 'RateRight Construction Job Payment'
            }
            
            # Add idempotency key if provided
            if idempotency_key:
                intent_params['idempotency_key'] = idempotency_key
            
            intent = stripe.PaymentIntent.create(**intent_params)
            
            logger.info(f"Created PaymentIntent: {intent.id} for ${amount_aud} AUD")
            return intent
            
        except stripe.error.StripeError as e:
            logger.error(f"Stripe error creating PaymentIntent: {str(e)}")
            raise Exception(f"Payment processing error: {str(e)}")
    
    def capture_payment(self, payment_intent_id, amount_to_capture=None):
        """Capture payment from escrow when work is completed"""
        self._ensure_stripe_key()
        try:
            intent = stripe.PaymentIntent.retrieve(payment_intent_id)
            
            if amount_to_capture:
                # Validate capture amount doesn't exceed authorized amount
                amount_decimal = Decimal(str(amount_to_capture))
                amount_cents = int(amount_decimal * 100)
                
                # Stripe returns amount in cents
                authorized_amount = intent.amount
                if amount_cents > authorized_amount:
                    raise ValueError(
                        f"Cannot capture ${amount_to_capture} - exceeds authorized amount of ${authorized_amount/100}"
                    )
                
                captured = stripe.PaymentIntent.capture(
                    payment_intent_id,
                    amount_to_capture=amount_cents
                )
            else:
                captured = stripe.PaymentIntent.capture(payment_intent_id)
            
            logger.info(f"Captured payment: {payment_intent_id}")
            return captured
            
        except stripe.error.StripeError as e:
            logger.error(f"Stripe error capturing payment: {str(e)}")
            raise Exception(f"Payment capture error: {str(e)}")
    
    def refund_payment(self, payment_intent_id, amount_to_refund=None, reason='requested_by_customer'):
        """Refund payment (for disputes or cancellations)"""
        self._ensure_stripe_key()
        try:
            refund_data = {
                'payment_intent': payment_intent_id,
                'reason': reason
            }
            
            if amount_to_refund:
                amount_decimal = Decimal(str(amount_to_refund))
                refund_data['amount'] = int(amount_decimal * 100)
            
            refund = stripe.Refund.create(**refund_data)
            
            logger.info(f"Created refund: {refund.id} for PaymentIntent: {payment_intent_id}")
            return refund
            
        except stripe.error.StripeError as e:
            logger.error(f"Stripe error creating refund: {str(e)}")
            raise Exception(f"Refund processing error: {str(e)}")
    
    def create_connect_account(self, user_data):
        """Create Stripe Connect account for contractors/workers"""
        self._ensure_stripe_key()
        try:
            account = stripe.Account.create(
                type='express',
                country='AU',
                email=user_data.get('email'),
                business_type='individual',
                individual={
                    'first_name': user_data.get('first_name'),
                    'last_name': user_data.get('last_name'),
                    'email': user_data.get('email')
                },
                capabilities={
                    'card_payments': {'requested': True},
                    'transfers': {'requested': True}
                }
            )
            
            logger.info(f"Created Stripe Connect account: {account.id}")
            return account
            
        except stripe.error.StripeError as e:
            logger.error(f"Stripe error creating Connect account: {str(e)}")
            raise Exception(f"Account creation error: {str(e)}")
    
    def transfer_to_worker(self, amount_aud, destination_account_id, metadata=None):
        """Transfer payment to worker after escrow release"""
        self._ensure_stripe_key()
        try:
            amount_decimal = Decimal(str(amount_aud))
            amount_cents = int(amount_decimal * 100)
            
            transfer = stripe.Transfer.create(
                amount=amount_cents,
                currency='aud',
                destination=destination_account_id,
                metadata=metadata or {}
            )
            
            logger.info(f"Created transfer: {transfer.id} to {destination_account_id}")
            return transfer
            
        except stripe.error.StripeError as e:
            logger.error(f"Stripe error creating transfer: {str(e)}")
            raise Exception(f"Transfer error: {str(e)}")
    
    def create_onboarding_link(self, account_id, return_url, refresh_url):
        """Create Stripe Connect onboarding link for hosted onboarding"""
        self._ensure_stripe_key()
        try:
            account_link = stripe.AccountLink.create(
                account=account_id,
                return_url=return_url,
                refresh_url=refresh_url,
                type='account_onboarding'
            )
            
            logger.info(f"Created onboarding link for account: {account_id}")
            return account_link
            
        except stripe.error.StripeError as e:
            logger.error(f"Stripe error creating onboarding link: {str(e)}")
            raise Exception(f"Onboarding link error: {str(e)}")
    
    def get_account_status(self, account_id):
        """Get Stripe Connect account status and capabilities"""
        self._ensure_stripe_key()
        try:
            account = stripe.Account.retrieve(account_id)
            
            return {
                'id': account.id,
                'charges_enabled': account.charges_enabled,
                'payouts_enabled': account.payouts_enabled,
                'details_submitted': account.details_submitted,
                'requirements': account.requirements,
                'capabilities': account.capabilities
            }
            
        except stripe.error.StripeError as e:
            logger.error(f"Stripe error retrieving account: {str(e)}")
            raise Exception(f"Account status error: {str(e)}")
    
    def create_dashboard_link(self, account_id):
        """Create link to Stripe Express dashboard for account management"""
        self._ensure_stripe_key()
        try:
            login_link = stripe.Account.create_login_link(account_id)
            
            logger.info(f"Created dashboard link for account: {account_id}")
            return login_link
            
        except stripe.error.StripeError as e:
            logger.error(f"Stripe error creating dashboard link: {str(e)}")
            raise Exception(f"Dashboard link error: {str(e)}")

# Initialize service
stripe_service = StripeService()
