"""
Enrollment and Coupon Management Routes
Handles course enrollments, coupon validation, and payment processing
"""
from flask import Blueprint, request, jsonify, g
from utils import require_api_key, format_api_response, create_error_response
from auth.jwt_manager import require_auth
from database import get_cached_connection
import logging
import json
from datetime import datetime, timedelta
from decimal import Decimal
import uuid

logger = logging.getLogger(__name__)

enrollment_bp = Blueprint('enrollment', __name__, url_prefix='/api/enrollment')

@enrollment_bp.route('/enroll', methods=['POST'])
@require_api_key
@require_auth
def enroll_in_course():
    """
    Enroll user in a course (free or paid with coupon)
    """
    conn = None
    cursor = None
    try:
        user_id = g.current_user_id
        data = request.get_json()
        
        if not data:
            return create_error_response("Request data is required", 400)
        
        course_id = data.get('course_id')
        coupon_code = data.get('coupon_code')  # Optional for paid courses
        payment_method = data.get('payment_method', 'free')  # 'free', 'coupon', 'whatsapp'
        
        if not course_id:
            return create_error_response("Course ID is required", 400)
        
        conn = get_cached_connection()
        if not conn:
            return create_error_response("Database connection failed", 500)
        
        cursor = conn.cursor(dictionary=True)
        
        # Check if user is already enrolled
        cursor.execute("""
            SELECT id FROM enrollments 
            WHERE user_id = %s AND course_id = %s
        """, (user_id, course_id))
        
        existing_enrollment = cursor.fetchone()
        if existing_enrollment:
            return create_error_response("You are already enrolled in this course", 409)
        
        # Get course details
        cursor.execute("""
            SELECT c.id, c.title, c.price, c.final_price, c.instructor_name, i.name AS institute_name
            FROM courses c
            LEFT JOIN institutes i ON c.institute_id = i.id
            WHERE c.id = %s
        """, (course_id,))
        
        course = cursor.fetchone()
        if not course:
            return create_error_response("Course not found", 404)
        
        original_price = float(course['final_price'])
        final_price = original_price
        discount_applied = 0.0
        coupon_id = None
        payment_status = 'free' if original_price == 0 else 'pending'
        
        # Handle coupon application globally
        if coupon_code:
            # Validate and apply coupon
            coupon_result = _validate_and_apply_coupon(
                cursor, user_id, course_id, coupon_code, original_price
            )
            
            if coupon_result['success']:
                coupon_id = coupon_result['coupon_id']
                discount_applied = coupon_result['discount_applied']
                final_price = coupon_result['final_price']
                
                if final_price <= 0:
                    # Course is free after coupon discount
                    payment_status = 'free'
                    final_price = 0.0
                else:
                    # Still need payment after coupon, status depends on payment_method logic below
                    # (it essentially stays 'pending' unless method is 'free' which is handled next)
                    pass
            else:
                return create_error_response(coupon_result['message'], 400)
        
        # Handle free courses (either originally free or made free by coupon)
        if final_price == 0:
            payment_status = 'free'
            # Direct enrollment for free courses
            enrollment_id = _create_enrollment(
                cursor, user_id, course_id, 0.0, 'free', 
                coupon_id, discount_applied
            )
            
            # Record coupon usage if coupon was used
            if coupon_id:
                _record_coupon_usage(
                    cursor, coupon_id, user_id, course_id, enrollment_id,
                    discount_applied, original_price, final_price
                )
            
            conn.commit()
            
            enrollment_data = {
                'enrollment_id': enrollment_id,
                'course_title': course['title'],
                'payment_status': 'free',
                'amount_paid': 0.0,
                'original_price': original_price,
                'final_price': 0.0,
                'discount_applied': discount_applied,
                'coupon_used': coupon_code if coupon_id else None
            }
            return format_api_response(
                data=enrollment_data,
                message='Successfully enrolled in course!',
                include_legacy_fields=enrollment_data
            )
        
        # Handle paid courses - WhatsApp method
        if payment_method == 'whatsapp':
            enrollment_id = _create_enrollment(
                cursor, user_id, course_id, final_price, 'pending',
                coupon_id, discount_applied
            )
            
            # Record coupon usage if coupon was used
            if coupon_id:
                _record_coupon_usage(
                    cursor, coupon_id, user_id, course_id, enrollment_id,
                    discount_applied, original_price, final_price
                )
            
            conn.commit()
            
            # Generate WhatsApp payment message
            whatsapp_message = _generate_whatsapp_payment_message(
                course, final_price, enrollment_id, coupon_code
            )
            
            enrollment_data = {
                'enrollment_id': enrollment_id,
                'course_title': course['title'],
                'payment_status': 'pending',
                'original_price': original_price,
                'final_price': final_price,
                'discount_applied': discount_applied,
                'coupon_used': coupon_code if coupon_id else None,
                'whatsapp_message': whatsapp_message,
                'whatsapp_number': '+977-9766992935'
            }
            return format_api_response(
                data=enrollment_data,
                message='Enrollment created. Please complete payment via WhatsApp.',
                include_legacy_fields=enrollment_data
            )
            
        # Handle paid courses - Generic/QR/Pending method 
        # (Default fall-through for any payment method that isn't 'free' or 'whatsapp')
        # This covers 'pending', 'coupon' (legacy), or specific payment method IDs passed as strings
        else:
            # Create pending enrollment for payment verification
            enrollment_id = _create_enrollment(
                cursor, user_id, course_id, final_price, 'pending',
                coupon_id, discount_applied
            )
            
            # Record coupon usage if coupon was used
            if coupon_id:
                _record_coupon_usage(
                    cursor, coupon_id, user_id, course_id, enrollment_id,
                    discount_applied, original_price, final_price
                )
            
            conn.commit()
            
            enrollment_data = {
                'enrollment_id': enrollment_id,
                'course_title': course['title'],
                'payment_status': 'pending',
                'original_price': original_price,
                'final_price': final_price,
                'discount_applied': discount_applied,
                'coupon_used': coupon_code if coupon_id else None,
                'message': 'Enrollment created. Please complete payment and submit screenshot.'
            }
            return format_api_response(
                data=enrollment_data,
                message='Enrollment created. Please complete payment and submit screenshot.',
                include_legacy_fields=enrollment_data
            )
            
    except Exception as e:
        if conn:
            conn.rollback()
        logger.error(f"Error in enroll_in_course: {str(e)}")
        return create_error_response(f"Failed to enroll in course: {str(e)}", 500)
    finally:
        if cursor:
            cursor.close()
        if conn:
            conn.close()

@enrollment_bp.route('/validate-coupon', methods=['POST'])
@require_api_key
@require_auth
def validate_coupon():
    """
    Validate a coupon code for a specific course
    """
    conn = None
    cursor = None
    try:
        user_id = g.current_user_id
        
        # Debug: Log the request headers and content type
        logger.info(f"Request Content-Type: {request.content_type}")
        logger.info(f"Request headers: {dict(request.headers)}")
        
        data = request.get_json()
        
        if not data:
            return create_error_response("Request data is required", 400)
        
        coupon_code = data.get('coupon_code')
        course_id = data.get('course_id')
        
        if not coupon_code or not course_id:
            return create_error_response("Coupon code and course ID are required", 400)
        
        conn = get_cached_connection()
        cursor = conn.cursor(dictionary=True)
        
        # Get course price
        cursor.execute("SELECT final_price FROM courses WHERE id = %s", (course_id,))
        course = cursor.fetchone()
        if not course:
            return create_error_response("Course not found", 404)
        
        original_price = float(course['final_price'])
        
        # Validate coupon
        coupon_result = _validate_and_apply_coupon(
            cursor, user_id, course_id, coupon_code, original_price, validate_only=True
        )
        
        if coupon_result['success']:
            coupon_data = {
                'valid': True,
                'coupon_code': coupon_code,
                'original_price': original_price,
                'discount_applied': coupon_result['discount_applied'],
                'final_price': coupon_result['final_price'],
                'coupon_type': coupon_result['coupon_type']
            }
            return format_api_response(
                data=coupon_data,
                message=coupon_result['message'],
                include_legacy_fields=coupon_data
            )
        else:
            return format_api_response(
                data={'valid': False},
                message=coupon_result['message'],
                include_legacy_fields={'valid': False, 'message': coupon_result['message']}
            )
            
    except Exception as e:
        logger.error(f"Error in validate_coupon: {str(e)}")
        return create_error_response(f"Failed to validate coupon: {str(e)}", 500)
    finally:
        if cursor:
            cursor.close()
        if conn:
            conn.close()

@enrollment_bp.route('/my-coupons', methods=['GET'])
@require_api_key
@require_auth
def get_my_coupons():
    """
    Get user's available coupons
    """
    conn = None
    cursor = None
    try:
        user_id = g.current_user_id
        
        conn = get_cached_connection()
        cursor = conn.cursor(dictionary=True)
        
        # Get user's assigned coupons and general coupons
        cursor.execute("""
            SELECT DISTINCT
                c.id,
                c.code,
                c.name,
                c.description,
                c.balance,
                c.coupon_type,
                c.discount_value,
                c.min_purchase_amount,
                c.max_discount_amount,
                c.valid_from,
                c.valid_until,
                c.usage_limit,
                c.used_count,
                uca.is_used as assigned_used,
                CASE 
                    WHEN uca.id IS NOT NULL THEN 'assigned'
                    ELSE 'general'
                END as coupon_source
            FROM coupons c
            LEFT JOIN user_coupon_assignments uca ON c.id = uca.coupon_id AND uca.user_id = %s
            WHERE c.is_active = 1 
            AND (c.valid_until IS NULL OR c.valid_until > NOW())
            AND (
                uca.id IS NOT NULL  -- User has this coupon assigned
                OR (
                    c.usage_limit IS NULL  -- No usage limit
                    OR c.used_count < c.usage_limit  -- Usage limit not reached
                )
            )
            ORDER BY 
                CASE WHEN uca.id IS NOT NULL THEN 1 ELSE 2 END,  -- Assigned coupons first
                c.created_at DESC
        """, (user_id,))
        
        coupons = cursor.fetchall()
        
        # Format coupons for response
        formatted_coupons = []
        for coupon in coupons:
            # Check if coupon is usable
            is_usable = True
            reason = ""
            
            if coupon['coupon_source'] == 'assigned' and coupon['assigned_used']:
                is_usable = False
                reason = "Already used"
            elif coupon['coupon_type'] == 'balance' and coupon['balance'] <= 0:
                is_usable = False
                reason = "No balance remaining"
            
            formatted_coupons.append({
                'id': coupon['id'],
                'code': coupon['code'],
                'name': coupon['name'],
                'description': coupon['description'],
                'coupon_type': coupon['coupon_type'],
                'balance': float(coupon['balance']) if coupon['balance'] else 0.0,
                'discount_value': float(coupon['discount_value']) if coupon['discount_value'] else 0.0,
                'min_purchase_amount': float(coupon['min_purchase_amount']) if coupon['min_purchase_amount'] else 0.0,
                'max_discount_amount': float(coupon['max_discount_amount']) if coupon['max_discount_amount'] else None,
                'valid_from': coupon['valid_from'].isoformat() if coupon['valid_from'] else None,
                'valid_until': coupon['valid_until'].isoformat() if coupon['valid_until'] else None,
                'source': coupon['coupon_source'],
                'is_usable': is_usable,
                'reason': reason if not is_usable else None
            })
        
        coupon_list_data = {
            'coupons': formatted_coupons,
            'total_count': len(formatted_coupons)
        }
        return format_api_response(
            data=coupon_list_data,
            message="Coupons retrieved successfully",
            include_legacy_fields=coupon_list_data
        )
        
    except Exception as e:
        logger.error(f"Error in get_my_coupons: {str(e)}")
        return create_error_response(f"Failed to fetch coupons: {str(e)}", 500)
    finally:
        if cursor:
            cursor.close()
        if conn:
            conn.close()

@enrollment_bp.route('/enrollment-status/<int:course_id>', methods=['GET'])
@require_api_key
@require_auth
def get_enrollment_status(course_id):
    """
    Check if user is enrolled in a specific course
    """
    conn = None
    cursor = None
    try:
        user_id = g.current_user_id
        
        conn = get_cached_connection()
        cursor = conn.cursor(dictionary=True)
        
        cursor.execute("""
            SELECT 
                e.id,
                e.enrolled_at,
                e.progress,
                e.is_completed,
                e.payment_status,
                e.payment_amount,
                e.discount_applied,
                c.code as coupon_code
            FROM enrollments e
            LEFT JOIN coupons c ON e.coupon_id = c.id
            WHERE e.user_id = %s AND e.course_id = %s
        """, (user_id, course_id))
        
        enrollment = cursor.fetchone()
        
        if enrollment:
            enrollment_status = {
                'enrolled': True,
                'enrollment_id': enrollment['id'],
                'enrolled_at': enrollment['enrolled_at'].isoformat(),
                'progress': enrollment['progress'],
                'is_completed': bool(enrollment['is_completed']),
                'payment_status': enrollment['payment_status'],
                'payment_amount': float(enrollment['payment_amount']) if enrollment['payment_amount'] else 0.0,
                'discount_applied': float(enrollment['discount_applied']) if enrollment['discount_applied'] else 0.0,
                'coupon_used': enrollment['coupon_code']
            }
            return format_api_response(
                data=enrollment_status,
                message="Enrollment status retrieved",
                include_legacy_fields=enrollment_status
            )
        else:
            return format_api_response(
                data={'enrolled': False},
                message="Not enrolled in this course",
                include_legacy_fields={'enrolled': False}
            )
            
    except Exception as e:
        logger.error(f"Error in get_enrollment_status: {str(e)}")
        return create_error_response(f"Failed to check enrollment status: {str(e)}", 500)
    finally:
        if cursor:
            cursor.close()
        if conn:
            conn.close()

# Helper functions

def _create_enrollment(cursor, user_id, course_id, amount, payment_status, coupon_id=None, discount_applied=0.0):
    """Create a new enrollment record"""
    enrollment_data = {
        'user_id': user_id,
        'course_id': course_id,
        'payment_amount': amount,
        'payment_status': payment_status,
        'coupon_id': coupon_id,
        'discount_applied': discount_applied,
        'expiry_date': datetime.now() + timedelta(days=365)  # 1 year access
    }
    
    cursor.execute("""
        INSERT INTO enrollments 
        (user_id, course_id, payment_amount, payment_status, coupon_id, discount_applied, expiry_date)
        VALUES (%(user_id)s, %(course_id)s, %(payment_amount)s, %(payment_status)s, %(coupon_id)s, %(discount_applied)s, %(expiry_date)s)
    """, enrollment_data)
    
    return cursor.lastrowid

def _validate_and_apply_coupon(cursor, user_id, course_id, coupon_code, original_price, validate_only=False):
    """Validate and calculate coupon discount"""
    try:
        # Get coupon details
        cursor.execute("""
            SELECT 
                id, name, balance, coupon_type, discount_value, 
                min_purchase_amount, max_discount_amount, usage_limit, used_count,
                valid_from, valid_until, applicable_courses, applicable_institutes
            FROM coupons 
            WHERE code = %s AND is_active = 1
        """, (coupon_code,))
        
        coupon = cursor.fetchone()
        if not coupon:
            return {'success': False, 'message': 'Invalid coupon code'}
        
        # Check validity dates
        now = datetime.now()
        if coupon['valid_from'] and coupon['valid_from'] > now:
            return {'success': False, 'message': 'Coupon is not yet valid'}
        
        if coupon['valid_until'] and coupon['valid_until'] < now:
            return {'success': False, 'message': 'Coupon has expired'}
        
        # Check usage limit
        if coupon['usage_limit'] and coupon['used_count'] >= coupon['usage_limit']:
            return {'success': False, 'message': 'Coupon usage limit reached'}
        
        # Check minimum purchase amount
        if coupon['min_purchase_amount'] and original_price < float(coupon['min_purchase_amount']):
            return {'success': False, 'message': f'Minimum purchase amount is NPR {coupon["min_purchase_amount"]}'}
        
        # Check if user has already used this coupon (for assigned coupons)
        cursor.execute("""
            SELECT is_used FROM user_coupon_assignments 
            WHERE user_id = %s AND coupon_id = %s
        """, (user_id, coupon['id']))
        
        assignment = cursor.fetchone()
        if assignment and assignment['is_used']:
            return {'success': False, 'message': 'You have already used this coupon'}
        
        # Check course/institute applicability
        if coupon['applicable_courses']:
            applicable_courses = json.loads(coupon['applicable_courses'])
            if course_id not in applicable_courses:
                return {'success': False, 'message': 'Coupon is not applicable to this course'}
        
        # Calculate discount
        discount_applied = 0.0
        coupon_type = coupon['coupon_type']
        
        if coupon_type == 'balance':
            # Use balance from coupon
            available_balance = float(coupon['balance'])
            discount_applied = min(available_balance, original_price)
        
        elif coupon_type == 'percentage':
            # Percentage discount
            discount_percentage = float(coupon['discount_value'])
            discount_applied = (original_price * discount_percentage) / 100
            
            # Apply maximum discount limit if set
            if coupon['max_discount_amount']:
                discount_applied = min(discount_applied, float(coupon['max_discount_amount']))
        
        elif coupon_type == 'fixed':
            # Fixed amount discount
            discount_applied = min(float(coupon['discount_value']), original_price)
        
        final_price = max(0, original_price - discount_applied)
        
        return {
            'success': True,
            'coupon_id': coupon['id'],
            'coupon_type': coupon_type,
            'discount_applied': discount_applied,
            'final_price': final_price,
            'message': f'Coupon applied! You saved NPR {discount_applied:.2f}'
        }
        
    except Exception as e:
        logger.error(f"Error validating coupon: {str(e)}")
        return {'success': False, 'message': 'Error validating coupon'}

def _record_coupon_usage(cursor, coupon_id, user_id, course_id, enrollment_id, amount_used, original_price, final_price):
    """Record coupon usage in history"""
    cursor.execute("""
        INSERT INTO coupon_usage_history 
        (coupon_id, user_id, course_id, enrollment_id, amount_used, original_price, final_price, discount_applied)
        VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
    """, (coupon_id, user_id, course_id, enrollment_id, amount_used, original_price, final_price, amount_used))

def _generate_whatsapp_payment_message(course, amount, enrollment_id, coupon_code=None):
    """Generate WhatsApp payment message"""
    message = f"""🎓 Course Enrollment Payment

📚 Course: {course['title']}
👨‍🏫 Instructor: {course['instructor_name']}
🏢 Institute: {course['institute_name']}
💰 Amount: NPR {amount:.2f}
🆔 Enrollment ID: {enrollment_id}"""
    
    if coupon_code:
        message += f"\n🎟️ Coupon Applied: {coupon_code}"
    
    message += f"""

Please send this message along with your payment confirmation to complete your enrollment.

Payment Methods:
• eSewa: [Your eSewa Number]
• Khalti: [Your Khalti Number]
• Bank Transfer: [Your Bank Details]

Thank you for choosing Ashlya Academy! 🚀"""
    
    return message
