import logging
import json
import pdfkit
import statistics
from datetime import datetime, timedelta
from flask import render_template, request, make_response, jsonify, current_app, flash, redirect, url_for
from flask_login import login_required, current_user
from app import db
from app.models.user import User
from app.models.topic import Topic
from app.models.progress import Progress, Submission
from app.models.course import ShortCourse, LearningCourse
from app.utils.decorators import teacher_required
from app.routes.teacher import bp

# Configure logger for teacher routes
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
handler = logging.StreamHandler()
handler.setFormatter(logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
logger.addHandler(handler)

@bp.route('/dashboard')
@login_required
@teacher_required
def dashboard():
    # Get topic stats with realtime data
    topics = Topic.query.filter_by(teacher_id=current_user.id).all()
    
    # Count topics by type
    reading_topics = sum(1 for t in topics if t.reading_content)
    writing_topics = sum(1 for t in topics if t.writing_prompt)
    speaking_topics = sum(1 for t in topics if t.speaking_prompt)

    # Get active students (with progress in last 30 days)
    thirty_days_ago = datetime.utcnow() - timedelta(days=30)
    
    active_students_count = db.session.query(Progress.student_id.distinct())\
        .join(Topic)\
        .filter(Topic.teacher_id == current_user.id)\
        .filter(Progress.started_at >= thirty_days_ago)\
        .count()
    
    # Get submissions by status
    pending_submissions_count = Submission.query\
        .join(Progress)\
        .join(Topic)\
        .filter(Topic.teacher_id == current_user.id)\
        .filter(Submission.status == 'pending')\
        .count()
        
    reviewed_submissions_count = Submission.query\
        .join(Progress)\
        .join(Topic)\
        .filter(Topic.teacher_id == current_user.id)\
        .filter(Submission.status != 'pending')\
        .count()
    
    # Calculate completed topics percentage
    try:
        # Get all student-topic combinations for this teacher's topics
        student_topic_count = db.session.query(db.func.count(Progress.id))\
            .join(Topic)\
            .filter(Topic.teacher_id == current_user.id)\
            .scalar() or 0
        
        # Count how many of those have been fully completed
        completed_count = db.session.query(db.func.count(Progress.id))\
            .join(Topic)\
            .filter(Topic.teacher_id == current_user.id)\
            .filter(Progress.completed_at.isnot(None))\
            .scalar() or 0
        
        # Log the raw values for debugging
        logger.info(f"Raw completion data: {completed_count} completed out of {student_topic_count} total")
        
        # Calculate percentage with proper handling for zero division
        if student_topic_count > 0:
            # Use float for precise calculation without premature rounding
            completion_percentage = int((completed_count / student_topic_count) * 100)
        else:
            completion_percentage = 0
        
        logger.info(f"Final completion stats: {completed_count}/{student_topic_count} = {completion_percentage}%")
    except Exception as e:
        logger.error(f"Error calculating completion rate: {str(e)}")
        completed_count = 0
        student_topic_count = 0
        completion_percentage = 0

    stats = {
        'total_students': current_user.students.count(),
        'active_students': active_students_count,
        'total_topics': len(topics),
        'pending_submissions': pending_submissions_count,
        'reviewed_submissions': reviewed_submissions_count,
        'reading_topics': reading_topics,
        'writing_topics': writing_topics,
        'speaking_topics': speaking_topics,
        'completion_percentage': completion_percentage,
        'completed_topics': completed_count,
        'total_assigned_topics': student_topic_count,
        'last_updated': datetime.utcnow().strftime('%H:%M:%S')
    }
    
    # Get recent submissions with safer parsing
    try:
        submissions = Submission.query\
            .join(Progress)\
            .join(Topic)\
            .filter(Topic.teacher_id == current_user.id)\
            .filter(Submission.status == 'pending')\
            .order_by(Submission.created_at.desc())\
            .limit(5)\
            .all()

        recent_submissions = []
        for submission in submissions:
            try:
                # Try to use feedback_json first, fall back to parsing feedback if needed
                if hasattr(submission, 'feedback_json') and submission.feedback_json:
                    if isinstance(submission.feedback_json, str):
                        submission.parsed_feedback = json.loads(submission.feedback_json)
                    else:
                        # Already a dict/list
                        submission.parsed_feedback = submission.feedback_json
                elif submission.feedback:
                    submission.parsed_feedback = json.loads(submission.feedback)
                else:
                    submission.parsed_feedback = []
                    
                # Process content if it exists
                if submission.content and isinstance(submission.content, str):
                    try:
                        submission.parsed_content = json.loads(submission.content)
                    except:
                        submission.parsed_content = {"raw": submission.content}
                else:
                    submission.parsed_content = {}
                    
                # Add student name for easy access in template
                submission.student_name = submission.progress.student.username if submission.progress and submission.progress.student else "Unknown"
                submission.topic_title = submission.progress.topic.title if submission.progress and submission.progress.topic else "Unknown Topic"
                
                recent_submissions.append(submission)
            except Exception as e:
                logger.error(f"Error processing submission {submission.id}: {str(e)}")
                # Still add the submission even if we can't parse the feedback
                submission.parsed_feedback = []
                submission.parsed_content = {}
                submission.student_name = submission.progress.student.username if submission.progress and submission.progress.student else "Unknown" 
                submission.topic_title = submission.progress.topic.title if submission.progress and submission.progress.topic else "Unknown Topic"
                recent_submissions.append(submission)
    except Exception as e:
        logger.error(f"Error retrieving submissions: {str(e)}")
        recent_submissions = []
    
    # Get pending student approvals
    pending_approvals = User.query.filter_by(
        role='student',
        is_approved=False,
        teacher_id=None
    ).all()

    # Set greeting based on time of day
    now = datetime.now()
    hour = now.hour
    if 5 <= hour < 12:
        greeting = 'Good morning'
    elif 12 <= hour < 17:
        greeting = 'Good afternoon'
    elif 17 <= hour < 21:
        greeting = 'Good evening'
    else:
        greeting = 'Good night'

    return render_template('teacher/dashboard.html', 
                         stats=stats, 
                         recent_submissions=recent_submissions,
                         topics=topics,
                         pending_approvals=pending_approvals,
                         greeting=greeting)

@bp.route('/topic-scores')
@login_required
@teacher_required
def topic_scores():
    """Display topic-wise scores for all students"""
    from flask import request
    
    # Get filtering parameters
    topic_id = request.args.get('topic_id', type=int)
    content_type = request.args.get('content_type', 'all')
    
    # Get all topics for this teacher
    topics = Topic.query.filter_by(teacher_id=current_user.id).order_by(Topic.title).all()
    
    # Build query for submissions
    query = db.session.query(
        Submission,
        Progress,
        Topic,
        User
    ).join(Progress, Submission.progress_id == Progress.id)\
     .join(Topic, Progress.topic_id == Topic.id)\
     .join(User, Progress.student_id == User.id)\
     .filter(Topic.teacher_id == current_user.id)\
     .filter(Submission.status == 'reviewed')
    
    # Apply filters
    if topic_id:
        query = query.filter(Topic.id == topic_id)
    
    if content_type != 'all':
        query = query.filter(Submission.content_type == content_type)
    
    # Get submissions ordered by student name, then topic
    submissions = query.order_by(User.username, Topic.title).all()
    
    # Organize data by student and topic
    student_scores = {}
    for submission, progress, topic, student in submissions:
        if student.id not in student_scores:
            student_scores[student.id] = {
                'student': student,
                'topics': {},
                'total_score': 0,
                'total_submissions': 0
            }
        
        if topic.id not in student_scores[student.id]['topics']:
            student_scores[student.id]['topics'][topic.id] = {
                'topic': topic,
                'submissions': [],
                'avg_score': 0
            }
        
        student_scores[student.id]['topics'][topic.id]['submissions'].append({
            'submission': submission,
            'content_type': submission.content_type,
            'grade': submission.grade or 0,
            'submitted_at': submission.created_at
        })
    
    # Calculate averages
    for student_id, student_data in student_scores.items():
        total_score = 0
        total_count = 0
        
        for topic_id, topic_data in student_data['topics'].items():
            topic_total = sum(sub['grade'] for sub in topic_data['submissions'])
            topic_count = len(topic_data['submissions'])
            
            if topic_count > 0:
                topic_data['avg_score'] = round(topic_total / topic_count, 2)
                total_score += topic_total
                total_count += topic_count
        
        if total_count > 0:
            student_data['total_score'] = round(total_score / total_count, 2)
            student_data['total_submissions'] = total_count
    
    return render_template('teacher/topic_scores.html',
                         student_scores=student_scores,
                         topics=topics,
                         selected_topic_id=topic_id,
                         selected_content_type=content_type)

@bp.route('/export-scores-pdf')
@login_required
@teacher_required
def export_scores_pdf():
    """Export topic scores to PDF"""
    # Get filtering parameters
    topic_id = request.args.get('topic_id', type=int)
    content_type = request.args.get('content_type', 'all')
    
    # Get all topics for this teacher
    topics = Topic.query.filter_by(teacher_id=current_user.id).order_by(Topic.title).all()
    
    # Build query for submissions (same as topic_scores route)
    query = db.session.query(
        Submission,
        Progress,
        Topic,
        User
    ).join(Progress, Submission.progress_id == Progress.id)\
     .join(Topic, Progress.topic_id == Topic.id)\
     .join(User, Progress.student_id == User.id)\
     .filter(Topic.teacher_id == current_user.id)\
     .filter(Submission.status == 'reviewed')
    
    # Apply filters
    if topic_id:
        query = query.filter(Topic.id == topic_id)
    
    if content_type != 'all':
        query = query.filter(Submission.content_type == content_type)
    
    # Get submissions ordered by student name, then topic
    submissions = query.order_by(User.username, Topic.title).all()
    
    # Organize data by student and topic (same logic as topic_scores route)
    student_scores = {}
    for submission, progress, topic, student in submissions:
        if student.id not in student_scores:
            student_scores[student.id] = {
                'student': student,
                'topics': {},
                'total_score': 0,
                'total_submissions': 0
            }
        
        if topic.id not in student_scores[student.id]['topics']:
            student_scores[student.id]['topics'][topic.id] = {
                'topic': topic,
                'submissions': [],
                'avg_score': 0
            }
        
        student_scores[student.id]['topics'][topic.id]['submissions'].append({
            'submission': submission,
            'content_type': submission.content_type,
            'grade': submission.grade or 0,
            'submitted_at': submission.created_at
        })
    
    # Calculate averages
    for student_id, student_data in student_scores.items():
        total_score = 0
        total_count = 0
        
        for topic_id, topic_data in student_data['topics'].items():
            topic_total = sum(sub['grade'] for sub in topic_data['submissions'])
            topic_count = len(topic_data['submissions'])
            
            if topic_count > 0:
                topic_data['avg_score'] = round(topic_total / topic_count, 2)
                total_score += topic_total
                total_count += topic_count
        
        if total_count > 0:
            student_data['total_score'] = round(total_score / total_count, 2)
            student_data['total_submissions'] = total_count
    
    # Render HTML template for PDF
    html = render_template('teacher/scores_pdf.html',
                         student_scores=student_scores,
                         topics=topics,
                         selected_topic_id=topic_id,
                         selected_content_type=content_type,
                         generated_date=datetime.now(),
                         teacher_name=current_user.username)
    
    # Generate PDF
    options = {
        'page-size': 'A4',
        'margin-top': '0.75in',
        'margin-right': '0.75in',
        'margin-bottom': '0.75in',
        'margin-left': '0.75in',
        'encoding': "UTF-8",
        'no-outline': None
    }
    
    # Configure wkhtmltopdf path
    config = None
    if current_app.config.get('WKHTMLTOPDF_PATH'):
        config = pdfkit.configuration(wkhtmltopdf=current_app.config['WKHTMLTOPDF_PATH'])
    
    try:
        pdf = pdfkit.from_string(html, False, options=options, configuration=config)
        
        response = make_response(pdf)
        response.headers['Content-Type'] = 'application/pdf'
        response.headers['Content-Disposition'] = f'attachment; filename=topic_scores_report_{datetime.now().strftime("%Y%m%d_%H%M%S")}.pdf'
        
        return response
    except Exception as e:
        logger.error(f"Error generating PDF: {str(e)}")
        return jsonify({'error': 'Failed to generate PDF'}), 500

@bp.route('/student-details/<int:student_id>')
@login_required
@teacher_required
def student_details_modal(student_id):
    """Get detailed student performance data for modal"""
    student = User.query.get_or_404(student_id)
    
    # Get all progress for this student across all topics
    progress_entries = db.session.query(
        Progress,
        Topic
    ).join(Topic, Progress.topic_id == Topic.id)\
     .filter(Topic.teacher_id == current_user.id)\
     .filter(Progress.student_id == student_id)\
     .order_by(Topic.title).all()
    
    # Get all submissions for this student in teacher's topics
    submissions = db.session.query(
        Submission,
        Progress,
        Topic
    ).join(Progress, Submission.progress_id == Progress.id)\
     .join(Topic, Progress.topic_id == Topic.id)\
     .filter(Topic.teacher_id == current_user.id)\
     .filter(Progress.student_id == student_id)\
     .filter(Submission.status == 'reviewed')\
     .order_by(Topic.title, Submission.created_at).all()
    
    # Organize by topic
    topics_data = {}
    
    # First add all progress entries
    for progress, topic in progress_entries:
        if topic.id not in topics_data:
            topics_data[topic.id] = {
                'topic': topic,
                'progress': progress,
                'submissions': [],
                'has_reading': progress.reading_completed is not None,
                'has_speaking': progress.speaking_completed is not None,
                'has_comprehension': progress.comprehension_completed is not None,
                'reading_date': progress.reading_completed,
                'speaking_date': progress.speaking_completed,
                'comprehension_date': progress.comprehension_completed,
                'speaking_score': progress.speaking_scores.get('overall', 0) if progress.speaking_scores else 0,
                'comprehension_score': progress.comprehension_score if progress.comprehension_completed else 0
            }
    
    # Then add submission data
    for submission, progress, topic in submissions:
        if topic.id not in topics_data:
            topics_data[topic.id] = {
                'topic': topic,
                'progress': progress,
                'submissions': [],
                'has_reading': progress.reading_completed is not None,
                'has_speaking': progress.speaking_completed is not None,
                'has_comprehension': progress.comprehension_completed is not None,
                'reading_date': progress.reading_completed,
                'speaking_date': progress.speaking_completed,
                'comprehension_date': progress.comprehension_completed,
                'speaking_score': progress.speaking_scores.get('overall', 0) if progress.speaking_scores else 0,
                'comprehension_score': progress.comprehension_score if progress.comprehension_completed else 0
            }
        
        topics_data[topic.id]['submissions'].append({
            'submission': submission,
            'content_type': submission.content_type,
            'grade': submission.grade or 0,
            'submitted_at': submission.created_at
        })
    
    html = render_template('teacher/student_details_modal.html',
                         student=student,
                         topics_data=topics_data)
    
    return jsonify({'html': html})

@bp.route('/students/details/<int:student_id>')
@login_required
@teacher_required
def student_details(student_id):
    """Detailed view of a student's progress"""
    # Get student
    student = User.query.get_or_404(student_id)
    
    # Check if student belongs to this teacher
    if student.teacher_id != current_user.id:
        flash('You are not authorized to view this student\'s details', 'error')
        return redirect(url_for('teacher.manage_students'))
    
    # Get all topics
    all_topics = Topic.query.all()
    
    # Get all progress for this student
    progress_dict = {p.topic_id: p for p in Progress.query.filter_by(student_id=student_id).all()}
    
    # Create comprehensive topic progress list
    topics_progress = []
    for topic in all_topics:
        progress = progress_dict.get(topic.id)
        if progress:
            # Enhance existing progress record with scores
            overall_score = 0
            if progress.speaking_scores:
                # Get the most recent submission (assuming the last key is the most recent)
                submission_ids = list(progress.speaking_scores.keys())
                if submission_ids:
                    last_submission = submission_ids[-1]
                    scores = progress.speaking_scores.get(last_submission, {})
                    overall_score = scores.get('overall', 0) if isinstance(scores, dict) else 0
                    
            progress.overall_speaking_score = overall_score
            topics_progress.append(progress)
        else:
            # Create a mock progress record for topics not started
            mock_progress = type('MockProgress', (), {
                'topic_id': topic.id,
                'reading_completed': None,
                'reading_started': False,
                'reading_time': None,
                'speaking_completed': None,
                'speaking_started': False,
                'comprehension_completed': None,
                'comprehension_started': False,
                'comprehension_score': None,
                'speaking_scores': None,
                'overall_speaking_score': None,
                'completed_at': None,
                'started_at': None,
                'submissions': []
            })()
            topics_progress.append(mock_progress)
    
    # Calculate statistics
    comprehension_scores = []
    speaking_scores = []
    
    for p in topics_progress:
        if hasattr(p, 'comprehension_completed') and p.comprehension_completed and getattr(p, 'comprehension_score', None) is not None:
            comprehension_scores.append(p.comprehension_score)
        
        # Handle nested speaking scores structure - scores are stored by submission ID
        if hasattr(p, 'speaking_completed') and p.speaking_completed and getattr(p, 'speaking_scores', None):
            # Each key in speaking_scores is a submission ID
            for submission_id, scores in p.speaking_scores.items():
                if isinstance(scores, dict) and 'overall' in scores:
                    speaking_scores.append(scores['overall'])
    
    stats = {
        'avg_comprehension': statistics.mean(comprehension_scores) if comprehension_scores else 0,
        'avg_speaking': statistics.mean(speaking_scores) if speaking_scores else 0
    }
    
    # Create topics dict for template
    topics = {t.id: t for t in all_topics}
    
    # Create a response with explicit content type
    from flask import Response
    html_content = render_template('teacher/student_details.html',
                                  student=student,
                                  all_topics=topics,
                                  progress_records=topics_progress,
                                  real_progress_count=len([p for p in topics_progress if hasattr(p, 'id')]),  # Count only real progress records
                                  stats=stats)
    return Response(html_content, mimetype='text/html')

@bp.route('/reset-student-progress/<int:student_id>', methods=['POST'])
@login_required
@teacher_required
def reset_student_progress(student_id):
    """Reset all progress for a specific student"""
    student = User.query.get_or_404(student_id)
    
    # Check if student belongs to this teacher
    if student.teacher_id != current_user.id:
        flash('You are not authorized to reset this student\'s progress', 'error')
        return redirect(url_for('teacher.manage_students'))
    
    try:
        # Get all progress records for this student
        progress_records = Progress.query.filter_by(student_id=student_id).all()
        
        # Delete all submissions associated with these progress records
        for progress in progress_records:
            submissions = Submission.query.filter_by(progress_id=progress.id).all()
            for submission in submissions:
                db.session.delete(submission)
            
            # Reset progress fields
            progress.reading_completed = None
            progress.comprehension_completed = None
            progress.speaking_completed = None
            progress.comprehension_score = None
            progress.speaking_scores = None
        
        db.session.commit()
        flash(f'All progress for {student.username} has been reset successfully', 'success')
    except Exception as e:
        db.session.rollback()
        flash(f'An error occurred: {str(e)}', 'error')
    
    return redirect(url_for('teacher.student_details', student_id=student_id))

@bp.route('/export-student-pdf/<int:student_id>')
@login_required
@teacher_required
def export_student_pdf(student_id):
    """Export detailed PDF report for a specific student"""
    try:
        student = User.query.get_or_404(student_id)
        
        # Get all submissions for this student in teacher's topics
        submissions = db.session.query(
            Submission,
            Progress,
            Topic
        ).join(Progress, Submission.progress_id == Progress.id)\
         .join(Topic, Progress.topic_id == Topic.id)\
         .filter(Topic.teacher_id == current_user.id)\
         .filter(Progress.student_id == student_id)\
         .filter(Submission.status == 'reviewed')\
         .order_by(Topic.title, Submission.created_at).all()
        
        # Organize by topic
        topics_data = {}
        total_score = 0
        total_submissions = 0
        
        for submission, progress, topic in submissions:
            if topic.id not in topics_data:
                topics_data[topic.id] = {
                    'topic': topic,
                    'submissions': [],
                    'avg_score': 0
                }
            
            topics_data[topic.id]['submissions'].append({
                'submission': submission,
                'content_type': submission.content_type,
                'grade': submission.grade or 0,
                'submitted_at': submission.created_at
            })
            
            if submission.grade:
                total_score += submission.grade
                total_submissions += 1
        
        # Calculate averages
        for topic_id, topic_data in topics_data.items():
            if topic_data['submissions']:
                topic_avg = sum(sub['grade'] for sub in topic_data['submissions']) / len(topic_data['submissions'])
                topic_data['avg_score'] = round(topic_avg, 2)
        
        overall_avg = round(total_score / total_submissions, 2) if total_submissions > 0 else 0
        
        # Render the student PDF template
        html = render_template('teacher/student_report_pdf.html',
                             student=student,
                             topics_data=topics_data,
                             overall_avg=overall_avg,
                             total_submissions=total_submissions,
                             teacher_name=current_user.username,
                             generated_date=datetime.now())
        
        # Generate PDF
        options = {
            'page-size': 'A4',
            'margin-top': '0.75in',
            'margin-right': '0.75in',
            'margin-bottom': '0.75in',
            'margin-left': '0.75in',
            'encoding': "UTF-8",
            'no-outline': None
        }
        
        # Configure wkhtmltopdf path
        config = None
        if current_app.config.get('WKHTMLTOPDF_PATH'):
            config = pdfkit.configuration(wkhtmltopdf=current_app.config['WKHTMLTOPDF_PATH'])
        
        pdf = pdfkit.from_string(html, False, options=options, configuration=config)
        
        # Create response
        response = make_response(pdf)
        response.headers['Content-Type'] = 'application/pdf'
        response.headers['Content-Disposition'] = f'attachment; filename={student.username}_detailed_report_{datetime.now().strftime("%Y%m%d")}.pdf'
        
        return response
        
    except Exception as e:
        logger.error(f"Error generating student PDF: {str(e)}")
        flash(f'Error generating student PDF: {str(e)}', 'error')
        return redirect(url_for('teacher.topic_scores'))