"""Webhook handlers for Stripe events."""

import logging
from fastapi import APIRouter, Request, HTTPException, Header
from typing import Optional, Dict, Any
import json
import base64
import hashlib
import hmac
import stripe
from agenticlypay.stripe_client import StripeClient
from agenticlypay.payments import PaymentProcessor
from agenticlypay.config import config
from agenticlypay.utils.firestore_storage import FirestoreStorage

logger = logging.getLogger(__name__)
router = APIRouter()
stripe_client = StripeClient()
payment_processor = PaymentProcessor()
storage = FirestoreStorage()


def reconcile_stripe_fees(charge: Dict[str, Any]) -> None:
    """
    Reconcile actual Stripe fees vs estimated fees.
    
    When a charge succeeds, we can see the actual Stripe fees charged.
    If our estimate was off, we can log this for accounting/reconciliation.
    
    Args:
        charge: Stripe charge object from webhook
    """
    try:
        charge_id = charge.get("id")
        payment_intent_id = charge.get("payment_intent")
        
        if not payment_intent_id:
            return
        
        # Retrieve payment intent to get metadata
        try:
            payment_intent = stripe.PaymentIntent.retrieve(payment_intent_id)
            metadata = payment_intent.metadata or {}
            developer_account_id = metadata.get("developer_account_id")
            
            if not developer_account_id:
                return
            
            # Get actual Stripe fees from balance transaction
            balance_transaction_id = charge.get("balance_transaction")
            if balance_transaction_id:
                balance_transaction = stripe.BalanceTransaction.retrieve(balance_transaction_id)
                actual_stripe_fee = balance_transaction.fee
                actual_stripe_fee_details = {
                    "amount": balance_transaction.amount,
                    "fee": balance_transaction.fee,
                    "net": balance_transaction.net,
                    "currency": balance_transaction.currency,
                }
                
                # Calculate what we estimated
                amount = charge.get("amount", 0)
                currency = charge.get("currency", "usd")
                # Check if international (simplified - in production, check card country)
                is_international = charge.get("payment_method_details", {}).get("card", {}).get("country") != "US"
                requires_conversion = currency != "usd"
                
                estimated_stripe_fee = config.estimate_stripe_fee(
                    amount, currency, is_international, requires_conversion
                )
                
                # Log fee reconciliation for accounting
                fee_reconciliation = {
                    "charge_id": charge_id,
                    "payment_intent_id": payment_intent_id,
                    "developer_account_id": developer_account_id,
                    "amount": amount,
                    "currency": currency,
                    "estimated_stripe_fee": estimated_stripe_fee,
                    "actual_stripe_fee": actual_stripe_fee,
                    "difference": actual_stripe_fee - estimated_stripe_fee,
                    "balance_transaction": actual_stripe_fee_details,
                    "timestamp": balance_transaction.created,
                }
                
                # Store in Firestore for reconciliation
                try:
                    from google.cloud import firestore
                    db = firestore.Client(project=config.project_id or "agenticlypay-com")
                    db.collection("fee_reconciliations").document(charge_id).set(fee_reconciliation)
                    logger.info(f"Fee reconciliation logged for charge {charge_id}: difference = {fee_reconciliation['difference']} cents")
                except Exception as e:
                    logger.error(f"Failed to store fee reconciliation: {str(e)}")
                    
        except Exception as e:
            logger.error(f"Error reconciling fees for charge {charge_id}: {str(e)}")
            
    except Exception as e:
        logger.error(f"Error in fee reconciliation: {str(e)}")


@router.post("/stripe")
async def stripe_webhook(
    request: Request,
    stripe_signature: Optional[str] = Header(None, alias="stripe-signature"),
):
    """Handle Stripe webhook events."""
    if not stripe_signature:
        raise HTTPException(status_code=400, detail="Missing stripe-signature header")

    try:
        payload = await request.body()
        event = stripe_client.construct_webhook_event(
            payload=payload, sig_header=stripe_signature
        )

        # Handle the event
        event_data = event.to_dict()
        event_type = event_data.get("type")
        
        # Reconcile fees when charge succeeds
        if event_type == "charge.succeeded":
            charge_data = event_data.get("data", {}).get("object", {})
            reconcile_stripe_fees(charge_data)
        
        result = payment_processor.handle_webhook(event_data)

        return {"success": True, "handled": result.get("handled", False), "result": result}
    except ValueError as e:
        raise HTTPException(status_code=400, detail=f"Invalid payload: {str(e)}")
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.post("/square")
async def square_webhook(
    request: Request,
    x_square_signature: Optional[str] = Header(None, alias="x-square-signature"),
):
    """Handle Square webhook events."""
    try:
        raw_body = await request.body()
        payload = json.loads(raw_body.decode("utf-8"))

        # Verify webhook signature if configured
        signature_key = config.square_webhook_signature_key
        if signature_key and x_square_signature:
            computed_signature = base64.b64encode(
                hmac.new(
                    signature_key.encode("utf-8"),
                    raw_body,
                    hashlib.sha1,
                ).digest()
            ).decode("utf-8")

            if not hmac.compare_digest(computed_signature, x_square_signature):
                raise HTTPException(status_code=401, detail="Invalid Square signature")

        event_type = payload.get("type")
        data = payload.get("data", {})
        payout_object = data.get("object", {})

        if event_type and event_type.startswith("payout."):
            payout_id = payout_object.get("id") or payout_object.get("payout_id")
            new_status = payout_object.get("status")

            if payout_id:
                from google.cloud import firestore

                db = firestore.Client()
                payouts_query = (
                    db.collection("square_payouts")
                    .where("payout_id", "==", str(payout_id))
                    .limit(1)
                    .stream()
                )

                for doc in payouts_query:
                    doc.reference.update(
                        {
                            "status": new_status or doc.to_dict().get("status", "PENDING"),
                            "updated_at": firestore.SERVER_TIMESTAMP,
                        }
                    )
                    break

        return {"success": True, "event_type": event_type, "handled": True}
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.get("/test")
async def test_webhook():
    """Test webhook endpoint."""
    return {"status": "webhook endpoint is active"}

