from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from sqlalchemy import desc
from datetime import datetime
from typing import List, Optional

from ..database import get_db
from ..models import User, Notification
from ..schemas.notification import (
    NotificationCreate, NotificationResponse,
    NotificationListResponse, NotificationMarkRead
)
from .auth import get_current_user

router = APIRouter(prefix="/notifications", tags=["notifications"])


# =====================
# Helper Functions
# =====================

def create_notification(
    db: Session,
    user_id: int,
    notification_type: str,
    title: str,
    message: str,
    link: Optional[str] = None,
    related_id: Optional[int] = None,
    related_type: Optional[str] = None
) -> Notification:
    """Create a new notification"""
    notification = Notification(
        user_id=user_id,
        notification_type=notification_type,
        title=title,
        message=message,
        link=link,
        related_id=related_id,
        related_type=related_type
    )
    db.add(notification)
    db.commit()
    db.refresh(notification)
    return notification


def notify_vehicle_recommended(db: Session, user_id: int, request_id: int, vehicle_count: int):
    """Notify user when vehicles are recommended for their request"""
    return create_notification(
        db=db,
        user_id=user_id,
        notification_type="vehicle_recommended",
        title="차량 추천 완료",
        message=f"{vehicle_count}대의 차량이 추천되었습니다. 지금 확인해보세요!",
        link=f"/my-request",
        related_id=request_id,
        related_type="vehicle_request"
    )


def notify_shipping_update(db: Session, user_id: int, vehicle_id: int, status: int, car_name: str):
    """Notify user when shipping status changes"""
    status_names = {
        1: "구매완료",
        2: "인천항 도착",
        3: "텐진항 도착",
        4: "자먼우드 도착",
        5: "울란바토르 도착",
        6: "통관 진행중",
        7: "배송완료"
    }
    status_name = status_names.get(status, f"상태 {status}")

    return create_notification(
        db=db,
        user_id=user_id,
        notification_type="shipping_update",
        title="배송 상태 업데이트",
        message=f"{car_name}: {status_name}",
        link=f"/find-my-car",
        related_id=vehicle_id,
        related_type="purchased_vehicle"
    )


def notify_withdrawal_processed(db: Session, user_id: int, withdrawal_id: int, status: str, amount: float):
    """Notify user when withdrawal request is processed"""
    status_messages = {
        "approved": f"출금 신청이 승인되었습니다. {amount:,.0f}원이 곧 입금됩니다.",
        "completed": f"출금 완료! {amount:,.0f}원이 입금되었습니다.",
        "rejected": "출금 신청이 거부되었습니다. 관리자에게 문의해주세요."
    }

    return create_notification(
        db=db,
        user_id=user_id,
        notification_type="withdrawal_processed",
        title="출금 처리 알림",
        message=status_messages.get(status, "출금 상태가 변경되었습니다."),
        link="/withdrawal",
        related_id=withdrawal_id,
        related_type="withdrawal"
    )


def notify_referral_reward(db: Session, user_id: int, reward_amount: float, referred_name: str):
    """Notify user when they receive referral reward"""
    return create_notification(
        db=db,
        user_id=user_id,
        notification_type="referral_reward",
        title="레퍼럴 보상 적립",
        message=f"{referred_name}님의 충전으로 {reward_amount:,.0f}원이 적립되었습니다!",
        link="/withdrawal",
        related_type="referral"
    )


def notify_dealer_approved(db: Session, user_id: int, dealer_code: str):
    """Notify user when dealer application is approved"""
    return create_notification(
        db=db,
        user_id=user_id,
        notification_type="dealer_approved",
        title="딜러 승인 완료",
        message=f"딜러 승인이 완료되었습니다! 딜러 코드: {dealer_code}",
        link="/dealer/my-card",
        related_type="dealer"
    )


def notify_dealer_rejected(db: Session, user_id: int, reason: str):
    """Notify user when dealer application is rejected"""
    return create_notification(
        db=db,
        user_id=user_id,
        notification_type="dealer_rejected",
        title="딜러 신청 거부",
        message=f"딜러 신청이 거부되었습니다. 사유: {reason}",
        link="/dealer/apply",
        related_type="dealer"
    )


def notify_share_purchased(db: Session, user_id: int, share_id: int, reward_amount: float, car_name: str):
    """Notify user when their shared vehicle is purchased"""
    return create_notification(
        db=db,
        user_id=user_id,
        notification_type="share_purchased",
        title="공유 차량 판매 완료",
        message=f"{car_name} 판매 완료! 리워드 {reward_amount:,.0f}원이 적립되었습니다.",
        link="/withdrawal",
        related_id=share_id,
        related_type="vehicle_share"
    )


def notify_payment_confirmed(db: Session, user_id: int, charge_id: int, amount: float, cc_amount: int):
    """Notify user when payment is confirmed"""
    return create_notification(
        db=db,
        user_id=user_id,
        notification_type="payment_confirmed",
        title="결제 확인 완료",
        message=f"결제가 확인되었습니다! ${amount:.2f} → {cc_amount} CC가 충전되었습니다.",
        link="/charge",
        related_id=charge_id,
        related_type="charge"
    )


def notify_inquiry_reply(db: Session, user_id: int, inquiry_id: int, subject: str = None):
    """Notify user when admin replies to their inquiry"""
    return create_notification(
        db=db,
        user_id=user_id,
        notification_type="inquiry_reply",
        title="문의 답변 등록",
        message=f"문의에 답변이 등록되었습니다." + (f" ({subject})" if subject else ""),
        link=f"/my-inquiries/{inquiry_id}",
        related_id=inquiry_id,
        related_type="inquiry"
    )


def notify_system(db: Session, user_id: int, title: str, message: str, link: Optional[str] = None):
    """Send a general system notification to a user"""
    return create_notification(
        db=db,
        user_id=user_id,
        notification_type="system",
        title=title,
        message=message,
        link=link
    )


# =====================
# User Endpoints
# =====================

@router.get("/", response_model=NotificationListResponse)
def get_notifications(
    page: int = 1,
    page_size: int = 20,
    unread_only: bool = False,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """Get user's notifications"""
    query = db.query(Notification).filter(Notification.user_id == current_user.id)

    if unread_only:
        query = query.filter(Notification.is_read == False)

    total = query.count()
    unread_count = db.query(Notification).filter(
        Notification.user_id == current_user.id,
        Notification.is_read == False
    ).count()

    notifications = query.order_by(desc(Notification.created_at)) \
        .offset((page - 1) * page_size) \
        .limit(page_size) \
        .all()

    return NotificationListResponse(
        notifications=[NotificationResponse.model_validate(n) for n in notifications],
        unread_count=unread_count,
        total=total
    )


@router.get("/unread-count")
def get_unread_count(
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """Get count of unread notifications"""
    count = db.query(Notification).filter(
        Notification.user_id == current_user.id,
        Notification.is_read == False
    ).count()

    return {"unread_count": count}


@router.post("/mark-read")
def mark_as_read(
    data: NotificationMarkRead,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """Mark notifications as read"""
    notifications = db.query(Notification).filter(
        Notification.id.in_(data.notification_ids),
        Notification.user_id == current_user.id
    ).all()

    for notification in notifications:
        notification.is_read = True
        notification.read_at = datetime.utcnow()

    db.commit()

    return {"message": f"Marked {len(notifications)} notifications as read"}


@router.post("/mark-all-read")
def mark_all_as_read(
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """Mark all notifications as read"""
    count = db.query(Notification).filter(
        Notification.user_id == current_user.id,
        Notification.is_read == False
    ).update({
        "is_read": True,
        "read_at": datetime.utcnow()
    })

    db.commit()

    return {"message": f"Marked {count} notifications as read"}


@router.delete("/{notification_id}")
def delete_notification(
    notification_id: int,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """Delete a notification"""
    notification = db.query(Notification).filter(
        Notification.id == notification_id,
        Notification.user_id == current_user.id
    ).first()

    if not notification:
        raise HTTPException(status_code=404, detail="Notification not found")

    db.delete(notification)
    db.commit()

    return {"message": "Notification deleted"}


# =====================
# Admin Endpoints
# =====================

@router.post("/admin/send")
def admin_send_notification(
    notification_data: NotificationCreate,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """[Admin] Send notification to a user"""
    if not current_user.is_admin:
        raise HTTPException(status_code=403, detail="Admin access required")

    notification = create_notification(
        db=db,
        user_id=notification_data.user_id,
        notification_type=notification_data.notification_type,
        title=notification_data.title,
        message=notification_data.message,
        link=notification_data.link,
        related_id=notification_data.related_id,
        related_type=notification_data.related_type
    )

    return NotificationResponse.model_validate(notification)


@router.post("/admin/send-all")
def admin_send_to_all(
    title: str,
    message: str,
    link: Optional[str] = None,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """[Admin] Send notification to all users"""
    if not current_user.is_admin:
        raise HTTPException(status_code=403, detail="Admin access required")

    users = db.query(User).filter(User.is_active == True).all()

    for user in users:
        create_notification(
            db=db,
            user_id=user.id,
            notification_type="system",
            title=title,
            message=message,
            link=link
        )

    return {"message": f"Sent notification to {len(users)} users"}
