from fastapi import APIRouter, Depends, Request
from sqlalchemy.ext.asyncio import AsyncSession
from app.db.session import get_db
from app.models.webhooksubscriptions import WebhookSubscriptions
from sqlalchemy import select
from pydantic import BaseModel, ValidationError
from app.utils.responses import custom_response
from app.core.logging import logger
import time
import json
from typing import List, Optional, Dict, Any
import base64
from datetime import datetime

router = APIRouter()


class ReceiptNotificationRequest(BaseModel):
    signedPayload: str


def get_expiration_intent_info(key: str) -> str:
    """
    Convert Apple subscription expiration intent code to human-readable message.
    """
    expiration_intents = {
        '1': "The customer voluntarily canceled their subscription.",
        '2': "Billing error; for example, the customer's payment information was no longer valid.",
        '3': "The customer did not agree to a recent price increase.",
        '4': "The product was not available for purchase at the time of renewal.",
        '5': "Unknown error."
    }
    return expiration_intents.get(str(key), '')


def jwt_decode(token: str) -> Dict[str, Any]:
    """
    Decode a JWT without verifying the signature, returning header and payload as dicts.
    Equivalent to PHP's base64_decode + json_decode.
    """
    try:
        token_parts = token.split(".")
        if len(token_parts) < 2:
            raise ValueError("Invalid JWT format")

        # Base64 decode header and payload (add missing padding if needed)
        def b64_decode(data: str) -> str:
            # Add padding
            rem = len(data) % 4
            if rem > 0:
                data += '=' * (4 - rem)
            return base64.urlsafe_b64decode(data).decode('utf-8')

        header_json = b64_decode(token_parts[0])
        payload_json = b64_decode(token_parts[1])

        header = json.loads(header_json)
        body = json.loads(payload_json)

        return {"header": header, "body": body}

    except Exception as e:
        raise ValueError(f"Failed to decode JWT: {e}")

@router.post("/apple/receipt-notification")
async def receipt_notification(
    request: Request,
    db: AsyncSession = Depends(get_db),
):
    logger.info("Received request for /apple/receipt-notification endpoint")
    try:
        raw_data = await request.json()
        logger.debug(f"Raw request data: {raw_data}")

        # Validate payload schema
        try:
            payload = ReceiptNotificationRequest.model_validate(raw_data)
        except ValidationError as ve:
            logger.warning(f"Validation failed: {ve.errors()}")
            return custom_response(422, data=ve.errors(), message="Validation failed")

        token = payload.signedPayload
        decoded_token = jwt_decode(token)
        decoded_body = decoded_token.get("body", {})
        decoded_data = decoded_body.get("data", {})

        logger.info(f"Notification type: {decoded_body.get('notificationType')}")

        transactions = jwt_decode(decoded_data.get("signedTransactionInfo", ""))
        transactions_data = transactions.get("body", {})

        renewals_data = {}
        is_expired = ""
        if decoded_data.get("signedRenewalInfo"):
            renewals = jwt_decode(decoded_data["signedRenewalInfo"])
            renewals_data = renewals.get("body", {})

        if transactions_data.get("expiresDate"):
            is_expired = 0 if transactions_data["expiresDate"] > time.time() else 1

        # Check existing subscription
        result = await db.execute(
            select(WebhookSubscriptions)
            .filter(WebhookSubscriptions.transaction_id == transactions_data["transactionId"])
        )
        webhook_subscription = result.scalar_one_or_none()
        if not webhook_subscription:
            webhook_subscription = WebhookSubscriptions()

        # Fill subscription fields
        webhook_subscription.notification_store = "apple"
        webhook_subscription.notification_type = decoded_body.get("notificationType")
        webhook_subscription.environment = decoded_data.get("environment")
        webhook_subscription.auto_renew_product_id = renewals_data.get("autoRenewProductId", "")
        webhook_subscription.auto_renew_status = renewals_data.get("autoRenewStatus", 0)
        webhook_subscription.auto_renew_status_change_date_ms = renewals_data.get("signedDate", 0)
        webhook_subscription.bundle_id = decoded_data.get("bundleId", "")
        webhook_subscription.bundle_version = decoded_data.get("bundleVersion", "")
        webhook_subscription.in_app_ownership_type = transactions_data.get("inAppOwnershipType")
        webhook_subscription.purchase_date_ms = transactions_data.get("purchaseDate")
        webhook_subscription.original_purchase_date_ms = transactions_data.get("originalPurchaseDate")
        webhook_subscription.transaction_id = transactions_data.get("transactionId")
        webhook_subscription.original_transaction_id = transactions_data.get("originalTransactionId")
        webhook_subscription.quantity = transactions_data.get("quantity", 1)
        webhook_subscription.expires_date_ms = transactions_data.get("expiresDate", 0)
        webhook_subscription.is_expired = is_expired
        webhook_subscription.product_id = transactions_data.get("productId")
        webhook_subscription.is_trial_period = 0
        webhook_subscription.is_in_intro_offer_period = 0
        webhook_subscription.expiration_intent = get_expiration_intent_info(
            renewals_data.get("expirationIntent", "")
        )
        webhook_subscription.cancellation_date_ms = transactions_data.get("cancellationDate", 0)
        webhook_subscription.created_at = datetime.utcnow()


        db.add(webhook_subscription)

        await db.commit()
        await db.refresh(webhook_subscription)

        return custom_response(code=200, data="Success")

    except Exception as e:
        logger.error(f"Error in receipt_notification: {e}", exc_info=True)
        return custom_response(code=500, data=str(e), message="Internal server error")
