from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from typing import Optional
from pydantic import BaseModel
from datetime import datetime
from ..database import get_db
from ..models import User, PushSubscription, UserNotificationPreference
from .auth import get_current_user, get_current_admin_user

router = APIRouter(prefix="/push", tags=["Push Notifications"])


# VAPID keys for web push (in production, store these securely)
# Generate these using: npx web-push generate-vapid-keys
VAPID_PUBLIC_KEY = "BMjR7pDj6PUjFo8VkA4f1BYhOAzGhJPcVnT7mJ6Bq8jG9yYKvN8dZ5jT3pQ2sL9wR0xF4bM1nK3vH5uC7yX2aE0"


class PushSubscriptionCreate(BaseModel):
    endpoint: str
    p256dh_key: str
    auth_key: str
    device_info: Optional[str] = None


class NotificationPreferenceUpdate(BaseModel):
    vehicle_recommended: Optional[bool] = None
    shipping_update: Optional[bool] = None
    payment_confirmed: Optional[bool] = None
    withdrawal_processed: Optional[bool] = None
    dealer_status: Optional[bool] = None
    share_purchased: Optional[bool] = None
    referral_reward: Optional[bool] = None
    inquiry_reply: Optional[bool] = None
    system_announcements: Optional[bool] = None
    push_enabled: Optional[bool] = None
    email_enabled: Optional[bool] = None


@router.get("/vapid-key")
def get_vapid_public_key():
    """Get VAPID public key for push subscription"""
    return {"public_key": VAPID_PUBLIC_KEY}


@router.post("/subscribe")
def subscribe_push(
    subscription: PushSubscriptionCreate,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """Subscribe to push notifications"""
    # Check if subscription already exists
    existing = db.query(PushSubscription).filter(
        PushSubscription.user_id == current_user.id,
        PushSubscription.endpoint == subscription.endpoint
    ).first()

    if existing:
        # Update existing subscription
        existing.p256dh_key = subscription.p256dh_key
        existing.auth_key = subscription.auth_key
        existing.device_info = subscription.device_info
        existing.is_active = True
        existing.last_used_at = datetime.utcnow()
    else:
        # Create new subscription
        new_sub = PushSubscription(
            user_id=current_user.id,
            endpoint=subscription.endpoint,
            p256dh_key=subscription.p256dh_key,
            auth_key=subscription.auth_key,
            device_info=subscription.device_info,
            is_active=True
        )
        db.add(new_sub)

    db.commit()
    return {"message": "Push subscription saved successfully"}


@router.delete("/unsubscribe")
def unsubscribe_push(
    endpoint: str,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """Unsubscribe from push notifications"""
    subscription = db.query(PushSubscription).filter(
        PushSubscription.user_id == current_user.id,
        PushSubscription.endpoint == endpoint
    ).first()

    if subscription:
        subscription.is_active = False
        db.commit()

    return {"message": "Push subscription removed"}


@router.get("/subscriptions")
def get_my_subscriptions(
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """Get user's active push subscriptions"""
    subscriptions = db.query(PushSubscription).filter(
        PushSubscription.user_id == current_user.id,
        PushSubscription.is_active == True
    ).all()

    return [
        {
            "id": sub.id,
            "endpoint": sub.endpoint[:50] + "..." if len(sub.endpoint) > 50 else sub.endpoint,
            "device_info": sub.device_info,
            "created_at": sub.created_at.isoformat() if sub.created_at else None,
            "last_used_at": sub.last_used_at.isoformat() if sub.last_used_at else None
        }
        for sub in subscriptions
    ]


@router.get("/preferences")
def get_notification_preferences(
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """Get user's notification preferences"""
    prefs = db.query(UserNotificationPreference).filter(
        UserNotificationPreference.user_id == current_user.id
    ).first()

    if not prefs:
        # Create default preferences
        prefs = UserNotificationPreference(user_id=current_user.id)
        db.add(prefs)
        db.commit()
        db.refresh(prefs)

    return {
        "vehicle_recommended": prefs.vehicle_recommended,
        "shipping_update": prefs.shipping_update,
        "payment_confirmed": prefs.payment_confirmed,
        "withdrawal_processed": prefs.withdrawal_processed,
        "dealer_status": prefs.dealer_status,
        "share_purchased": prefs.share_purchased,
        "referral_reward": prefs.referral_reward,
        "inquiry_reply": prefs.inquiry_reply,
        "system_announcements": prefs.system_announcements,
        "push_enabled": prefs.push_enabled,
        "email_enabled": prefs.email_enabled,
    }


@router.put("/preferences")
def update_notification_preferences(
    preferences: NotificationPreferenceUpdate,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """Update user's notification preferences"""
    prefs = db.query(UserNotificationPreference).filter(
        UserNotificationPreference.user_id == current_user.id
    ).first()

    if not prefs:
        prefs = UserNotificationPreference(user_id=current_user.id)
        db.add(prefs)

    # Update preferences
    for field, value in preferences.dict(exclude_none=True).items():
        setattr(prefs, field, value)

    db.commit()
    db.refresh(prefs)

    return {"message": "Preferences updated successfully"}


# Admin endpoints
@router.get("/admin/stats")
def admin_get_push_stats(
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_admin_user)
):
    """Get push notification statistics (Admin only)"""
    total_subscriptions = db.query(PushSubscription).filter(
        PushSubscription.is_active == True
    ).count()

    users_with_push = db.query(PushSubscription.user_id).filter(
        PushSubscription.is_active == True
    ).distinct().count()

    return {
        "total_subscriptions": total_subscriptions,
        "users_with_push": users_with_push
    }


# Helper function to send push notification (called from other modules)
def send_push_notification(
    db: Session,
    user_id: int,
    title: str,
    body: str,
    url: str = None,
    notification_type: str = "system"
):
    """
    Send push notification to a user.
    In production, this would use pywebpush to actually send the notification.
    """
    # Check user preferences
    prefs = db.query(UserNotificationPreference).filter(
        UserNotificationPreference.user_id == user_id
    ).first()

    if prefs and not prefs.push_enabled:
        return False

    # Check specific notification type preference
    if prefs:
        type_pref_map = {
            "vehicle_recommended": prefs.vehicle_recommended,
            "shipping_update": prefs.shipping_update,
            "payment_confirmed": prefs.payment_confirmed,
            "withdrawal_processed": prefs.withdrawal_processed,
            "dealer_approved": prefs.dealer_status,
            "dealer_rejected": prefs.dealer_status,
            "share_purchased": prefs.share_purchased,
            "referral_reward": prefs.referral_reward,
            "inquiry_reply": prefs.inquiry_reply,
            "system": prefs.system_announcements,
        }
        if notification_type in type_pref_map and not type_pref_map[notification_type]:
            return False

    # Get user's active subscriptions
    subscriptions = db.query(PushSubscription).filter(
        PushSubscription.user_id == user_id,
        PushSubscription.is_active == True
    ).all()

    if not subscriptions:
        return False

    # In production, use pywebpush to send notifications
    # For now, we just log and return success
    # Example with pywebpush:
    # from pywebpush import webpush, WebPushException
    # for sub in subscriptions:
    #     try:
    #         webpush(
    #             subscription_info={
    #                 "endpoint": sub.endpoint,
    #                 "keys": {
    #                     "p256dh": sub.p256dh_key,
    #                     "auth": sub.auth_key
    #                 }
    #             },
    #             data=json.dumps({
    #                 "title": title,
    #                 "body": body,
    #                 "url": url
    #             }),
    #             vapid_private_key=VAPID_PRIVATE_KEY,
    #             vapid_claims={"sub": "mailto:admin@autosellcar.com"}
    #         )
    #         sub.last_used_at = datetime.utcnow()
    #     except WebPushException as ex:
    #         if ex.response and ex.response.status_code == 410:
    #             sub.is_active = False
    # db.commit()

    return True
