from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy import func
from sqlalchemy.orm import Session

from app.database import get_db
from app.dependencies import require_user_token
from app.models import User
from app.models_admin import MemberNotification, MemberNotificationType, MemberSessionProgress
from app.schemas import (
    MemberNotificationIdRequest,
    MemberNotificationListResponse,
    MemberNotificationUnreadCountResponse,
    Message,
)
from app.member_feedback import is_coach_feedback_text
from app.services.admin_service import serialize_member_notification

router = APIRouter(tags=["user-member-notifications"])


def _feedback_message(row: MemberSessionProgress) -> str:
    feedback = (row.feedback or "").strip()
    session_label = (row.session_name or "").strip()
    if not session_label and row.session_number is not None:
        session_label = f"Session {row.session_number}"
    if not session_label:
        session_label = (row.week_name or "").strip() or "your session"
    return f"You received feedback for {session_label}: {feedback}"


def _sync_feedback_notifications(db: Session, user: User) -> None:
    feedback_rows = (
        db.query(MemberSessionProgress)
        .filter(
            MemberSessionProgress.user_id == user.id,
            MemberSessionProgress.feedback.isnot(None),
            func.length(func.trim(MemberSessionProgress.feedback)) > 0,
            MemberSessionProgress.feedback_notified.is_(False),
        )
        .order_by(MemberSessionProgress.updated_at.asc(), MemberSessionProgress.id.asc())
        .all()
    )

    added = False
    for row in feedback_rows:
        if not is_coach_feedback_text(row.feedback):
            row.feedback_notified = True
            added = True
            continue

        title = "Feedback received"
        message = _feedback_message(row)
        exists = (
            db.query(MemberNotification.id)
            .filter(
                MemberNotification.user_id == user.id,
                MemberNotification.notification_type == MemberNotificationType.feedback.value,
                MemberNotification.title == title,
                MemberNotification.message == message,
            )
            .first()
        )
        if exists:
            continue

        db.add(
            MemberNotification(
                user_id=user.id,
                notification_type=MemberNotificationType.feedback.value,
                title=title,
                message=message,
                sent_by_id=row.assigned_by_id,
            )
        )
        row.feedback_notified = True
        added = True

    if added:
        db.commit()


@router.post(
    "/clear-all-member-notifications",
    response_model=Message,
    summary="Delete all logged-in user notifications (including feedback), without re-creating them",
)
def clear_all_my_member_notifications(
    db: Session = Depends(get_db),
    user: User = Depends(require_user_token),
):
    # Prevent feedback notifications from being re-generated after clearing.
    (
        db.query(MemberSessionProgress)
        .filter(
            MemberSessionProgress.user_id == user.id,
            MemberSessionProgress.feedback.isnot(None),
            func.length(func.trim(MemberSessionProgress.feedback)) > 0,
        )
        .update({MemberSessionProgress.feedback_notified: True}, synchronize_session=False)
    )

    deleted = (
        db.query(MemberNotification)
        .filter(MemberNotification.user_id == user.id)
        .delete(synchronize_session=False)
    )
    db.commit()
    return Message(message=f"Cleared {deleted} notification(s)")


@router.get(
    "/list-my-notifications",
    response_model=MemberNotificationListResponse,
    summary="List notifications for the logged-in user, including admin feedback",
)
def list_my_notifications(
    db: Session = Depends(get_db),
    user: User = Depends(require_user_token),
):
    _sync_feedback_notifications(db, user)
    rows = (
        db.query(MemberNotification)
        .filter(MemberNotification.user_id == user.id)
        .order_by(MemberNotification.created_at.desc(), MemberNotification.id.desc())
        .all()
    )
    serialized = [serialize_member_notification(row) for row in rows]
    return MemberNotificationListResponse(total=len(serialized), notifications=serialized)


@router.get(
    "/member-notifications-unread-count",
    response_model=MemberNotificationUnreadCountResponse,
    summary="Unread notification count for the logged-in user",
)
def my_member_notifications_unread_count(
    db: Session = Depends(get_db),
    user: User = Depends(require_user_token),
):
    _sync_feedback_notifications(db, user)
    unread_count = (
        db.query(MemberNotification)
        .filter(
            MemberNotification.user_id == user.id,
            MemberNotification.is_read.is_(False),
        )
        .count()
    )
    return MemberNotificationUnreadCountResponse(unread_count=unread_count)


@router.post(
    "/mark-member-notification-read",
    response_model=Message,
    summary="Mark one user notification as read",
)
def mark_my_member_notification_read(
    body: MemberNotificationIdRequest,
    db: Session = Depends(get_db),
    user: User = Depends(require_user_token),
):
    row = (
        db.query(MemberNotification)
        .filter(
            MemberNotification.id == body.notification_id,
            MemberNotification.user_id == user.id,
        )
        .first()
    )
    if row is None:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Notification not found")

    row.is_read = True
    db.commit()
    return Message(message="Notification marked as read")


@router.post(
    "/mark-all-member-notifications-read",
    response_model=Message,
    summary="Mark all logged-in user notifications as read",
)
def mark_all_my_member_notifications_read(
    db: Session = Depends(get_db),
    user: User = Depends(require_user_token),
):
    _sync_feedback_notifications(db, user)
    count = (
        db.query(MemberNotification)
        .filter(
            MemberNotification.user_id == user.id,
            MemberNotification.is_read.is_(False),
        )
        .update({MemberNotification.is_read: True}, synchronize_session=False)
    )
    db.commit()
    return Message(message=f"Marked {count} notification(s) as read")


@router.post(
    "/delete-my-member-notification",
    response_model=Message,
    summary="Delete one logged-in user notification",
)
def delete_my_member_notification(
    body: MemberNotificationIdRequest,
    db: Session = Depends(get_db),
    user: User = Depends(require_user_token),
):
    row = (
        db.query(MemberNotification)
        .filter(
            MemberNotification.id == body.notification_id,
            MemberNotification.user_id == user.id,
        )
        .first()
    )
    if row is None:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Notification not found")

    db.delete(row)
    db.commit()
    return Message(message="Notification deleted")
