"""
Messages Routes
===============

Private messages and notifications API.
"""

from datetime import datetime

from flask import render_template, request, redirect, url_for, flash, jsonify
from flask_login import login_required, current_user

from . import bp
from database import SessionLocal, User, PrivateMessage, UserNotification, UserBlock, Classified
from utils.helpers import sanitize_input
from utils.decorators import member_required


# ============================================================
# PRIVATE MESSAGES ROUTES
# ============================================================

@bp.route('/wiadomosci')
@login_required
@member_required
def messages_inbox():
    """Skrzynka odbiorcza"""
    page = request.args.get('page', 1, type=int)
    per_page = 20

    db = SessionLocal()
    try:
        query = db.query(PrivateMessage).filter(
            PrivateMessage.recipient_id == current_user.id
        ).order_by(PrivateMessage.created_at.desc())

        total = query.count()
        messages = query.limit(per_page).offset((page - 1) * per_page).all()

        unread_count = db.query(PrivateMessage).filter(
            PrivateMessage.recipient_id == current_user.id,
            PrivateMessage.is_read == False
        ).count()

        return render_template('messages/inbox.html',
            messages=messages,
            page=page,
            total_pages=(total + per_page - 1) // per_page,
            unread_count=unread_count
        )
    finally:
        db.close()


@bp.route('/wiadomosci/wyslane')
@login_required
@member_required
def messages_sent():
    """Wysłane wiadomości"""
    page = request.args.get('page', 1, type=int)
    per_page = 20

    db = SessionLocal()
    try:
        query = db.query(PrivateMessage).filter(
            PrivateMessage.sender_id == current_user.id
        ).order_by(PrivateMessage.created_at.desc())

        total = query.count()
        messages = query.limit(per_page).offset((page - 1) * per_page).all()

        return render_template('messages/sent.html',
            messages=messages,
            page=page,
            total_pages=(total + per_page - 1) // per_page
        )
    finally:
        db.close()


@bp.route('/wiadomosci/nowa')
@login_required
@member_required
def messages_new():
    """Formularz nowej wiadomości"""
    recipient_id = request.args.get('to', type=int)
    context_type = request.args.get('context_type')
    context_id = request.args.get('context_id', type=int)

    db = SessionLocal()
    try:
        # Lista użytkowników do wyboru
        users = db.query(User).filter(
            User.is_active == True,
            User.is_verified == True,
            User.id != current_user.id
        ).order_by(User.name).all()

        recipient = None
        if recipient_id:
            recipient = db.query(User).filter(User.id == recipient_id).first()

        # Pobierz kontekst (np. ogłoszenie B2B)
        context = None
        context_subject = None
        if context_type == 'classified' and context_id:
            classified = db.query(Classified).filter(Classified.id == context_id).first()
            if classified:
                context = {
                    'type': 'classified',
                    'id': classified.id,
                    'title': classified.title,
                    'url': url_for('classifieds.classifieds_view', classified_id=classified.id)
                }
                context_subject = f"Dotyczy: {classified.title}"

        return render_template('messages/compose.html',
            users=users,
            recipient=recipient,
            context=context,
            context_type=context_type,
            context_id=context_id,
            context_subject=context_subject
        )
    finally:
        db.close()


@bp.route('/wiadomosci/wyslij', methods=['POST'])
@login_required
@member_required
def messages_send():
    """Wyślij wiadomość"""
    recipient_id = request.form.get('recipient_id', type=int)
    subject = sanitize_input(request.form.get('subject', ''), 255)
    content = request.form.get('content', '').strip()
    context_type = request.form.get('context_type')
    context_id = request.form.get('context_id', type=int)

    if not recipient_id or not content:
        flash('Odbiorca i treść są wymagane.', 'error')
        return redirect(url_for('.messages_new'))

    db = SessionLocal()
    try:
        recipient = db.query(User).filter(User.id == recipient_id).first()
        if not recipient:
            flash('Odbiorca nie istnieje.', 'error')
            return redirect(url_for('.messages_new'))

        # Check if either user has blocked the other
        block_exists = db.query(UserBlock).filter(
            ((UserBlock.user_id == current_user.id) & (UserBlock.blocked_user_id == recipient_id)) |
            ((UserBlock.user_id == recipient_id) & (UserBlock.blocked_user_id == current_user.id))
        ).first()
        if block_exists:
            flash('Nie można wysłać wiadomości do tego użytkownika.', 'error')
            return redirect(url_for('.messages_new'))

        message = PrivateMessage(
            sender_id=current_user.id,
            recipient_id=recipient_id,
            subject=subject,
            content=content,
            context_type=context_type if context_type else None,
            context_id=context_id if context_id else None
        )
        db.add(message)
        db.commit()

        flash('Wiadomość wysłana.', 'success')
        return redirect(url_for('.messages_sent'))
    finally:
        db.close()


@bp.route('/wiadomosci/<int:message_id>')
@login_required
@member_required
def messages_view(message_id):
    """Czytaj wiadomość"""
    db = SessionLocal()
    try:
        message = db.query(PrivateMessage).filter(
            PrivateMessage.id == message_id
        ).first()

        if not message:
            flash('Wiadomość nie istnieje.', 'error')
            return redirect(url_for('.messages_inbox'))

        # Sprawdź dostęp
        if message.recipient_id != current_user.id and message.sender_id != current_user.id:
            flash('Brak dostępu do tej wiadomości.', 'error')
            return redirect(url_for('.messages_inbox'))

        # Oznacz jako przeczytaną
        if message.recipient_id == current_user.id and not message.is_read:
            message.is_read = True
            message.read_at = datetime.now()
            db.commit()

        # Pobierz kontekst (np. ogłoszenie B2B)
        context = None
        if message.context_type == 'classified' and message.context_id:
            classified = db.query(Classified).filter(Classified.id == message.context_id).first()
            if classified:
                context = {
                    'type': 'classified',
                    'id': classified.id,
                    'title': classified.title,
                    'url': url_for('classifieds.classifieds_view', classified_id=classified.id),
                    'is_active': classified.is_active
                }

        return render_template('messages/view.html', message=message, context=context)
    finally:
        db.close()


@bp.route('/wiadomosci/<int:message_id>/odpowiedz', methods=['POST'])
@login_required
@member_required
def messages_reply(message_id):
    """Odpowiedz na wiadomość"""
    content = request.form.get('content', '').strip()

    if not content:
        flash('Treść jest wymagana.', 'error')
        return redirect(url_for('.messages_view', message_id=message_id))

    db = SessionLocal()
    try:
        original = db.query(PrivateMessage).filter(
            PrivateMessage.id == message_id
        ).first()

        if not original:
            flash('Wiadomość nie istnieje.', 'error')
            return redirect(url_for('.messages_inbox'))

        # Odpowiedz do nadawcy oryginalnej wiadomości
        recipient_id = original.sender_id if original.sender_id != current_user.id else original.recipient_id

        # Check if either user has blocked the other
        block_exists = db.query(UserBlock).filter(
            ((UserBlock.user_id == current_user.id) & (UserBlock.blocked_user_id == recipient_id)) |
            ((UserBlock.user_id == recipient_id) & (UserBlock.blocked_user_id == current_user.id))
        ).first()
        if block_exists:
            flash('Nie można wysłać wiadomości do tego użytkownika.', 'error')
            return redirect(url_for('.messages_inbox'))

        reply = PrivateMessage(
            sender_id=current_user.id,
            recipient_id=recipient_id,
            subject=f"Re: {original.subject}" if original.subject else None,
            content=content,
            parent_id=message_id
        )
        db.add(reply)
        db.commit()

        flash('Odpowiedź wysłana.', 'success')
        return redirect(url_for('.messages_view', message_id=message_id))
    finally:
        db.close()


@bp.route('/api/messages/unread-count')
@login_required
@member_required
def api_unread_count():
    """API: Liczba nieprzeczytanych wiadomości"""
    db = SessionLocal()
    try:
        count = db.query(PrivateMessage).filter(
            PrivateMessage.recipient_id == current_user.id,
            PrivateMessage.is_read == False
        ).count()
        return jsonify({'count': count})
    finally:
        db.close()


# ============================================================
# NOTIFICATIONS API ROUTES
# ============================================================

@bp.route('/api/notifications')
@login_required
@member_required
def api_notifications():
    """API: Get user notifications"""
    limit = request.args.get('limit', 20, type=int)
    offset = request.args.get('offset', 0, type=int)
    unread_only = request.args.get('unread_only', 'false').lower() == 'true'

    db = SessionLocal()
    try:
        query = db.query(UserNotification).filter(
            UserNotification.user_id == current_user.id
        )

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

        # Order by most recent first
        query = query.order_by(UserNotification.created_at.desc())

        total = query.count()
        notifications = query.limit(limit).offset(offset).all()

        return jsonify({
            'success': True,
            'notifications': [
                {
                    'id': n.id,
                    'title': n.title,
                    'message': n.message,
                    'notification_type': n.notification_type,
                    'related_type': n.related_type,
                    'related_id': n.related_id,
                    'action_url': n.action_url,
                    'is_read': n.is_read,
                    'created_at': n.created_at.isoformat() if n.created_at else None
                }
                for n in notifications
            ],
            'total': total,
            'unread_count': db.query(UserNotification).filter(
                UserNotification.user_id == current_user.id,
                UserNotification.is_read == False
            ).count()
        })
    finally:
        db.close()


@bp.route('/api/notifications/<int:notification_id>/read', methods=['POST'])
@login_required
@member_required
def api_notification_mark_read(notification_id):
    """API: Mark notification as read"""
    db = SessionLocal()
    try:
        notification = db.query(UserNotification).filter(
            UserNotification.id == notification_id,
            UserNotification.user_id == current_user.id
        ).first()

        if not notification:
            return jsonify({'success': False, 'error': 'Powiadomienie nie znalezione'}), 404

        notification.mark_as_read()
        db.commit()

        return jsonify({
            'success': True,
            'message': 'Oznaczono jako przeczytane'
        })
    finally:
        db.close()


@bp.route('/api/notifications/read-all', methods=['POST'])
@login_required
@member_required
def api_notifications_mark_all_read():
    """API: Mark all notifications as read"""
    db = SessionLocal()
    try:
        updated = db.query(UserNotification).filter(
            UserNotification.user_id == current_user.id,
            UserNotification.is_read == False
        ).update({
            UserNotification.is_read: True,
            UserNotification.read_at: datetime.now()
        })
        db.commit()

        return jsonify({
            'success': True,
            'message': f'Oznaczono {updated} powiadomien jako przeczytane',
            'count': updated
        })
    finally:
        db.close()


@bp.route('/api/notifications/unread-count')
@login_required
@member_required
def api_notifications_unread_count():
    """API: Get unread notifications count"""
    db = SessionLocal()
    try:
        count = db.query(UserNotification).filter(
            UserNotification.user_id == current_user.id,
            UserNotification.is_read == False
        ).count()
        return jsonify({'count': count})
    finally:
        db.close()
