"""Notification center API routes for RateRight Australian Construction Marketplace"""
import logging
from flask import Blueprint, request, jsonify, current_app
from flask_login import login_required, current_user
from datetime import datetime

from ...services.notification_service import notification_service
from ...models.notification import NotificationType, NotificationFrequency, DeliveryChannel
from ...models import User
from ...extensions import limiter

logger = logging.getLogger(__name__)

notifications_bp = Blueprint('notifications', __name__, url_prefix='/api/notifications')


@notifications_bp.route('/', methods=['GET'])
@login_required
def get_notifications():
    """Get user's notifications with pagination and filtering"""
    try:
        # Get query parameters
        limit = min(int(request.args.get('limit', 20)), 100)  # Max 100 per page
        offset = int(request.args.get('offset', 0))
        unread_only = request.args.get('unread_only', 'false').lower() == 'true'
        category = request.args.get('category')
        
        # Get notifications
        notifications = notification_service.get_user_notifications(
            user_id=current_user.id,
            limit=limit,
            offset=offset,
            unread_only=unread_only
        )
        
        # Filter by category if provided
        if category:
            notifications = [n for n in notifications if n.category == category]
        
        # Convert to dict format
        result = {
            'notifications': [n.to_dict() for n in notifications],
            'has_more': len(notifications) == limit,
            'unread_count': notification_service.get_unread_count(current_user.id)
        }
        
        return jsonify(result), 200
        
    except Exception as e:
        logger.error(f"Error getting notifications: {e}")
        return jsonify({'error': 'Failed to retrieve notifications'}), 500


@notifications_bp.route('/unread-count', methods=['GET'])
@limiter.exempt  # Exempt from rate limiting - read-only endpoint polled every 30s
@login_required
def get_unread_count():
    """Get count of unread notifications"""
    try:
        count = notification_service.get_unread_count(current_user.id)
        return jsonify({'unread_count': count}), 200
        
    except Exception as e:
        logger.error(f"Error getting unread count: {e}")
        return jsonify({'error': 'Failed to get unread count'}), 500


@notifications_bp.route('/<int:notification_id>/mark-read', methods=['POST'])
@login_required
def mark_notification_read(notification_id):
    """Mark specific notification as read"""
    try:
        success = notification_service.mark_as_read(notification_id, current_user.id)
        
        if success:
            return jsonify({'message': 'Notification marked as read'}), 200
        else:
            return jsonify({'error': 'Notification not found or already read'}), 404
            
    except Exception as e:
        logger.error(f"Error marking notification as read: {e}")
        return jsonify({'error': 'Failed to mark notification as read'}), 500


@notifications_bp.route('/mark-all-read', methods=['POST'])
@login_required
def mark_all_read():
    """Mark all notifications as read for user"""
    try:
        count = notification_service.mark_all_as_read(current_user.id)
        return jsonify({
            'message': f'Marked {count} notifications as read',
            'marked_count': count
        }), 200
        
    except Exception as e:
        logger.error(f"Error marking all notifications as read: {e}")
        return jsonify({'error': 'Failed to mark notifications as read'}), 500


@notifications_bp.route('/preferences', methods=['GET'])
@login_required
def get_preferences():
    """Get user's notification preferences"""
    try:
        from ...models.notification import NotificationPreference
        
        # Get all preferences for user
        preferences = NotificationPreference.query.filter_by(user_id=current_user.id).all()
        
        # Convert to structured format
        result = {}
        for pref in preferences:
            result[pref.notification_type.value] = {
                'email_enabled': pref.email_enabled,
                'email_frequency': pref.email_frequency.value,
                'sms_enabled': pref.sms_enabled,
                'sms_frequency': pref.sms_frequency.value,
                'push_web_enabled': pref.push_web_enabled,
                'push_mobile_enabled': pref.push_mobile_enabled,
                'in_app_enabled': pref.in_app_enabled,
                'quiet_hours_start': pref.quiet_hours_start.strftime('%H:%M') if pref.quiet_hours_start else None,
                'quiet_hours_end': pref.quiet_hours_end.strftime('%H:%M') if pref.quiet_hours_end else None,
                'respect_weekends': pref.respect_weekends,
                'consent_given': pref.consent_given,
                'consent_date': pref.consent_date.isoformat() if pref.consent_date else None
            }
        
        # Add metadata about notification types
        notification_types = {}
        for nt in NotificationType:
            notification_types[nt.value] = {
                'name': nt.value.replace('_', ' ').title(),
                'description': get_notification_description(nt),
                'category': get_notification_category(nt)
            }
        
        return jsonify({
            'preferences': result,
            'notification_types': notification_types,
            'available_frequencies': [f.value for f in NotificationFrequency],
            'available_channels': [c.value for c in DeliveryChannel]
        }), 200
        
    except Exception as e:
        logger.error(f"Error getting preferences: {e}")
        return jsonify({'error': 'Failed to get preferences'}), 500


@notifications_bp.route('/preferences', methods=['PUT'])
@login_required
def update_preferences():
    """Update user's notification preferences"""
    try:
        data = request.get_json()
        if not data:
            return jsonify({'error': 'No data provided'}), 400
        
        updated_count = 0
        errors = []
        
        for notification_type_str, preferences in data.items():
            try:
                # Validate notification type
                notification_type = NotificationType(notification_type_str)
                
                # Validate preferences format
                valid_keys = {
                    'email_enabled', 'email_frequency', 'sms_enabled', 'sms_frequency',
                    'push_web_enabled', 'push_mobile_enabled', 'in_app_enabled',
                    'quiet_hours_start', 'quiet_hours_end', 'respect_weekends',
                    'consent_given'
                }
                
                filtered_prefs = {k: v for k, v in preferences.items() if k in valid_keys}
                
                # Update preferences
                success = notification_service.update_user_preferences(
                    user_id=current_user.id,
                    notification_type=notification_type,
                    preferences=filtered_prefs
                )
                
                if success:
                    updated_count += 1
                else:
                    errors.append(f"Failed to update {notification_type_str}")
                    
            except ValueError:
                errors.append(f"Invalid notification type: {notification_type_str}")
            except Exception as e:
                errors.append(f"Error updating {notification_type_str}: {str(e)}")
        
        if errors:
            return jsonify({
                'message': f'Updated {updated_count} preferences with {len(errors)} errors',
                'updated_count': updated_count,
                'errors': errors
            }), 207  # Multi-status
        else:
            return jsonify({
                'message': f'Successfully updated {updated_count} preferences',
                'updated_count': updated_count
            }), 200
            
    except Exception as e:
        logger.error(f"Error updating preferences: {e}")
        return jsonify({'error': 'Failed to update preferences'}), 500


@notifications_bp.route('/preferences/reset', methods=['POST'])
@login_required
def reset_preferences():
    """Reset user preferences to defaults"""
    try:
        notification_service.create_default_preferences(current_user.id)
        return jsonify({'message': 'Preferences reset to defaults'}), 200
        
    except Exception as e:
        logger.error(f"Error resetting preferences: {e}")
        return jsonify({'error': 'Failed to reset preferences'}), 500


@notifications_bp.route('/test', methods=['POST'])
@login_required
def send_test_notification():
    """Send test notification to user (for testing purposes)"""
    try:
        # Only allow in development/testing
        if not current_app.config.get('DEBUG') and not current_app.config.get('TESTING'):
            return jsonify({'error': 'Test notifications only available in development'}), 403
        
        data = request.get_json() or {}
        
        # Get notification type from request or default
        notification_type_str = data.get('type', 'system_announcement')
        try:
            notification_type = NotificationType(notification_type_str)
        except ValueError:
            return jsonify({'error': f'Invalid notification type: {notification_type_str}'}), 400
        
        # Send test notification
        notification = notification_service.send_notification(
            user_id=current_user.id,
            notification_type=notification_type,
            title=data.get('title', 'Test Notification'),
            content=data.get('content', 'This is a test notification from RateRight notification system.'),
            priority=data.get('priority', 5),
            category='test',
            force_send=True  # Override quiet hours for testing
        )
        
        if notification:
            return jsonify({
                'message': 'Test notification sent',
                'notification': notification.to_dict()
            }), 200
        else:
            return jsonify({'error': 'Failed to send test notification'}), 500
            
    except Exception as e:
        logger.error(f"Error sending test notification: {e}")
        return jsonify({'error': 'Failed to send test notification'}), 500


@notifications_bp.route('/categories', methods=['GET'])
@login_required
def get_categories():
    """Get available notification categories and types"""
    categories = {
        'job_alerts': [
            NotificationType.JOB_MATCH,
            NotificationType.JOB_APPLICATION_UPDATE,
            NotificationType.CONTRACT_AWARDED
        ],
        'financial': [
            NotificationType.PAYMENT_RECEIVED,
            NotificationType.PAYMENT_DUE,
            NotificationType.INVOICE_GENERATED
        ],
        'social': [
            NotificationType.RATING_RECEIVED,
            NotificationType.REVIEW_REQUEST,
            NotificationType.ACHIEVEMENT_UNLOCKED,
            NotificationType.MESSAGE_RECEIVED,
            NotificationType.CHAT_NOTIFICATION
        ],
        'compliance': [
            NotificationType.INSURANCE_EXPIRY,
            NotificationType.CERTIFICATION_RENEWAL,
            NotificationType.WHS_COMPLIANCE,
            NotificationType.TAX_OBLIGATION
        ],
        'system': [
            NotificationType.SYSTEM_ANNOUNCEMENT,
            NotificationType.SECURITY_ALERT,
            NotificationType.DEADLINE_REMINDER
        ]
    }
    
    result = {}
    for category, types in categories.items():
        result[category] = {
            'name': category.replace('_', ' ').title(),
            'types': [
                {
                    'value': nt.value,
                    'name': nt.value.replace('_', ' ').title(),
                    'description': get_notification_description(nt)
                }
                for nt in types
            ]
        }
    
    return jsonify({'categories': result}), 200


def get_notification_description(notification_type: NotificationType) -> str:
    """Get human-readable description for notification type"""
    descriptions = {
        NotificationType.JOB_MATCH: "New jobs matching your skills and location",
        NotificationType.JOB_APPLICATION_UPDATE: "Updates on your job applications",
        NotificationType.CONTRACT_AWARDED: "Notification when you're awarded a contract",
        NotificationType.PAYMENT_RECEIVED: "Confirmation when payments are received",
        NotificationType.PAYMENT_DUE: "Reminders for upcoming payments",
        NotificationType.INVOICE_GENERATED: "Notifications when invoices are created",
        NotificationType.RATING_RECEIVED: "When you receive a new rating or review",
        NotificationType.REVIEW_REQUEST: "Requests to review completed work",
        NotificationType.ACHIEVEMENT_UNLOCKED: "Gamification achievements and level ups",
        NotificationType.MESSAGE_RECEIVED: "New private messages",
        NotificationType.CHAT_NOTIFICATION: "Chat and communication alerts",
        NotificationType.DEADLINE_REMINDER: "Project and task deadline reminders",
        NotificationType.INSURANCE_EXPIRY: "Insurance policy expiry warnings",
        NotificationType.CERTIFICATION_RENEWAL: "Professional certification renewals",
        NotificationType.SYSTEM_ANNOUNCEMENT: "Important system updates and announcements",
        NotificationType.SECURITY_ALERT: "Account security and login alerts",
        NotificationType.WHS_COMPLIANCE: "Workplace health and safety compliance",
        NotificationType.TAX_OBLIGATION: "Tax and financial obligation reminders"
    }
    return descriptions.get(notification_type, notification_type.value.replace('_', ' ').title())


def get_notification_category(notification_type: NotificationType) -> str:
    """Get category for notification type"""
    if notification_type in [NotificationType.JOB_MATCH, NotificationType.JOB_APPLICATION_UPDATE, NotificationType.CONTRACT_AWARDED]:
        return "job_alerts"
    elif notification_type in [NotificationType.PAYMENT_RECEIVED, NotificationType.PAYMENT_DUE, NotificationType.INVOICE_GENERATED]:
        return "financial"
    elif notification_type in [NotificationType.RATING_RECEIVED, NotificationType.REVIEW_REQUEST, NotificationType.ACHIEVEMENT_UNLOCKED, NotificationType.MESSAGE_RECEIVED, NotificationType.CHAT_NOTIFICATION]:
        return "social"
    elif notification_type in [NotificationType.INSURANCE_EXPIRY, NotificationType.CERTIFICATION_RENEWAL, NotificationType.WHS_COMPLIANCE, NotificationType.TAX_OBLIGATION]:
        return "compliance"
    else:
        return "system"
