"""
Billing Service - Razorpay Integration
"""
import razorpay
from datetime import datetime, timedelta
from typing import Optional, Dict, Any
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
import logging

from app.config import settings
from app.models.billing import Invoice, Payment, PaymentStatus, PaymentMethod, InvoiceStatus
from app.models.subscription import Subscription, SubscriptionStatus
from app.models.client import Client

logger = logging.getLogger(__name__)


class BillingService:
    """Handle billing operations with Razorpay"""

    def __init__(self):
        self.client = None
        if settings.RAZORPAY_KEY_ID and settings.RAZORPAY_KEY_SECRET:
            self.client = razorpay.Client(
                auth=(settings.RAZORPAY_KEY_ID, settings.RAZORPAY_KEY_SECRET)
            )

    async def create_order(
            self,
            db: AsyncSession,
            client_id: int,
            amount: float,
            currency: str = "INR"
    ) -> Dict[str, Any]:
        """
        Create a Razorpay order for payment

        Args:
            db: Database session
            client_id: Client ID
            amount: Amount in rupees
            currency: Currency code

        Returns:
            Razorpay order details
        """
        if not self.client:
            raise ValueError("Razorpay not configured")

        # Create Razorpay order
        order_data = {
            "amount": int(amount * 100),  # Razorpay expects paise
            "currency": currency,
            "receipt": f"order_{client_id}_{datetime.now().strftime('%Y%m%d%H%M%S')}",
            "notes": {
                "client_id": str(client_id)
            }
        }

        order = self.client.order.create(data=order_data)

        logger.info(f"Razorpay order created: {order['id']} for client {client_id}")

        return {
            "order_id": order["id"],
            "amount": amount,
            "currency": currency,
            "key_id": settings.RAZORPAY_KEY_ID
        }

    async def verify_payment(
            self,
            db: AsyncSession,
            razorpay_order_id: str,
            razorpay_payment_id: str,
            razorpay_signature: str,
            invoice_id: int
    ) -> bool:
        """
        Verify Razorpay payment signature and update records

        Args:
            db: Database session
            razorpay_order_id: Razorpay order ID
            razorpay_payment_id: Razorpay payment ID
            razorpay_signature: Razorpay signature
            invoice_id: Invoice ID to update

        Returns:
            True if payment verified successfully
        """
        if not self.client:
            raise ValueError("Razorpay not configured")

        # Verify signature
        params = {
            "razorpay_order_id": razorpay_order_id,
            "razorpay_payment_id": razorpay_payment_id,
            "razorpay_signature": razorpay_signature
        }

        try:
            self.client.utility.verify_payment_signature(params)
        except razorpay.errors.SignatureVerificationError:
            logger.error(f"Payment signature verification failed for order {razorpay_order_id}")
            return False

        # Get invoice
        result = await db.execute(select(Invoice).where(Invoice.id == invoice_id))
        invoice = result.scalar_one_or_none()

        if not invoice:
            logger.error(f"Invoice {invoice_id} not found")
            return False

        # Create payment record
        payment = Payment(
            invoice_id=invoice_id,
            amount=invoice.total_amount,
            currency=invoice.currency,
            status=PaymentStatus.SUCCESS,
            method=PaymentMethod.RAZORPAY,
            gateway_payment_id=razorpay_payment_id,
            gateway_order_id=razorpay_order_id,
            gateway_signature=razorpay_signature,
            completed_at=datetime.utcnow()
        )
        db.add(payment)

        # Update invoice
        invoice.status = InvoiceStatus.PAID
        invoice.paid_at = datetime.utcnow()
        invoice.payment_method = PaymentMethod.RAZORPAY
        invoice.transaction_id = razorpay_payment_id

        await db.commit()

        logger.info(f"Payment verified and recorded for invoice {invoice_id}")

        return True

    async def create_subscription(
            self,
            db: AsyncSession,
            client_id: int,
            plan_id: int
    ) -> Dict[str, Any]:
        """
        Create a recurring subscription in Razorpay

        Args:
            db: Database session
            client_id: Client ID
            plan_id: Plan ID

        Returns:
            Subscription details
        """
        # This would integrate with Razorpay Subscriptions API
        # For now, we create a local subscription
        pass

    async def generate_invoice(
            self,
            db: AsyncSession,
            client_id: int,
            subscription_id: int,
            amount: float,
            description: str
    ) -> Invoice:
        """
        Generate a new invoice

        Args:
            db: Database session
            client_id: Client ID
            subscription_id: Subscription ID
            amount: Amount
            description: Invoice description

        Returns:
            Created invoice
        """
        # Calculate tax (GST 18%)
        tax_percentage = 18
        tax_amount = amount * (tax_percentage / 100)
        total_amount = amount + tax_amount

        invoice = Invoice(
            client_id=client_id,
            subscription_id=subscription_id,
            invoice_number=Invoice.generate_invoice_number(),
            status=InvoiceStatus.PENDING,
            billing_period_start=datetime.utcnow(),
            billing_period_end=datetime.utcnow() + timedelta(days=30),
            subtotal=amount,
            tax_percentage=tax_percentage,
            tax_amount=tax_amount,
            total_amount=total_amount,
            due_date=datetime.utcnow() + timedelta(days=7),
            line_items=[{
                "description": description,
                "quantity": 1,
                "unit_price": float(amount),
                "amount": float(amount)
            }]
        )

        db.add(invoice)
        await db.commit()
        await db.refresh(invoice)

        logger.info(f"Invoice {invoice.invoice_number} generated for client {client_id}")

        return invoice

    async def get_payment_history(
            self,
            db: AsyncSession,
            client_id: int,
            limit: int = 10
    ) -> list:
        """
        Get payment history for a client

        Args:
            db: Database session
            client_id: Client ID
            limit: Number of records to return

        Returns:
            List of payments
        """
        result = await db.execute(
            select(Payment)
            .join(Invoice)
            .where(Invoice.client_id == client_id)
            .order_by(Payment.created_at.desc())
            .limit(limit)
        )
        return result.scalars().all()


# Singleton instance
billing_service = BillingService()
