from fastapi import APIRouter, Request, Form, HTTPException, Query, Depends
from fastapi.responses import HTMLResponse, RedirectResponse, JSONResponse
from typing import Optional, List
import json
import os
import uuid
from pathlib import Path
from fastapi import UploadFile, File
from sqlalchemy.orm import Session

from ..database import templates
from ..auth.deps import current_user, require_admin, require_docente_or_admin
from ..models.base import get_db
from ..models import academy_crud as crud
from .models import (
    CourseCreate, CourseUpdate, LessonCreate, LessonUpdate,
    ProgressUpdate, EnrollmentCreate, SectionCreate, SectionUpdate
)

router = APIRouter()

# Upload configuration
UPLOAD_DIR = Path("app/static/uploads/miniaturas_cursos")
UPLOAD_DIR.mkdir(parents=True, exist_ok=True)
ALLOWED_EXTENSIONS = {".jpg", ".jpeg", ".png", ".gif", ".webp"}

# ============= STUDENT ROUTES =============

@router.get("/academia", response_class=HTMLResponse, name="academia_home")
async def academia_home(request: Request, db: Session = Depends(get_db)):
    """Main academia page for students"""
    user = current_user(request)
    if not user:
        return RedirectResponse(url="/login", status_code=303)
    
    # MVP-90 access control: only admin, docente or MVP-90 alumnos can access
    user_role = str(user['role'] if 'role' in user else '').lower()
    try:
        is_mvp = user['is_mvp90']
    except (KeyError, IndexError):
        is_mvp = False
    if user_role not in ('admin', 'docente') and not is_mvp:
        return templates.TemplateResponse(
            "academia/academia_locked.html",
            {"request": request, "user": user}
        )
    
    # Get courses based on role
    if user['role'] == 'admin':
        courses = crud.get_all_courses(db)
    else:
        courses = crud.get_all_courses(db, status='published')
    
    # Enrich with progress data for this user
    courses_data = []
    for course in courses:
        course_dict = {
            'id': course.id,
            'title': course.title,
            'description': course.description,
            'thumbnail': course.thumbnail,
            'status': course.status,
            'created_at': course.created_at,
            'updated_at': course.updated_at,
            'order_index': course.order_index
        }
        
        # Check if enrolled
        enrolled = crud.is_user_enrolled(db, int(user['id']), course.id)
        course_dict['enrolled'] = enrolled
        
        # Get progress stats
        if enrolled:
            progress_records = crud.get_user_progress_for_course(db, int(user['id']), course.id)
            lessons = crud.get_lessons_by_course(db, course.id)
            total = len(lessons)
            completed = sum(1 for p in progress_records if p.completed)
            percentage = (completed / total * 100) if total > 0 else 0
            course_dict['progress'] = {'total': total, 'completed': completed, 'percentage': percentage}
        else:
            course_dict['progress'] = {'total': 0, 'completed': 0, 'percentage': 0}
        
        courses_data.append(course_dict)
    
    return templates.TemplateResponse(
        "academia/academia.html",
        {"request": request, "user": user, "courses": courses_data}
    )

@router.get("/academia/curso/{course_id}", response_class=HTMLResponse, name="academia_course")
async def academia_course(request: Request, course_id: int, db: Session = Depends(get_db)):
    """View course details and lessons"""
    user = current_user(request)
    if not user:
        return RedirectResponse(url="/login", status_code=303)
    
    # MVP-90 access control
    user_role = str(user['role'] if 'role' in user else '').lower()
    try:
        is_mvp = user['is_mvp90']
    except (KeyError, IndexError):
        is_mvp = False
    if user_role not in ('admin', 'docente') and not is_mvp:
        return templates.TemplateResponse(
            "academia/academia_locked.html",
            {"request": request, "user": user}
        )
    
    course = crud.get_course_by_id(db, course_id)
    if not course:
        raise HTTPException(status_code=404, detail="Curso no encontrado")
    
    # Only show published courses to non-admins
    if course.status != 'published' and user['role'] != 'admin':
        raise HTTPException(status_code=403, detail="Este curso aún no está disponible")
    
    # Get lessons (published only for students)
    if user['role'] == 'admin':
        lessons = crud.get_lessons_by_course(db, course_id)
    else:
        lessons = crud.get_lessons_by_course(db, course_id, status='published')
    
    # Get user's progress for this course
    user_progress = crud.get_user_progress(db, int(user['id']), course_id)
    progress_map = {p.lesson_id: bool(p.completed) for p in user_progress}
    
    # Enrich lessons with completion status
    lessons_data = []
    for lesson in lessons:
        lesson_dict = {
            'id': lesson.id,
            'title': lesson.title,
            'description': lesson.description,
            'duration_minutes': lesson.duration_minutes,
            'status': lesson.status,
            'completed': progress_map.get(lesson.id, False)
        }
        lessons_data.append(lesson_dict)
    
    # Check if enrolled
    enrolled = crud.is_user_enrolled(db, int(user['id']), course_id)
    
    # Get progress stats
    stats = crud.get_course_progress_stats(db, int(user['id']), course_id)
    
    return templates.TemplateResponse(
        "academia/curso.html",
        {
            "request": request,
            "user": user,
            "course": crud.course_to_dict(course),
            "lessons": lessons_data,
            "enrolled": enrolled,
            "progress": stats
        }
    )

@router.get("/academia/leccion/{lesson_id}", response_class=HTMLResponse, name="academia_lesson")
async def academia_lesson(request: Request, lesson_id: int, db: Session = Depends(get_db)):
    """View a lesson"""
    user = current_user(request)
    if not user:
        return RedirectResponse(url="/login", status_code=303)
    
    # MVP-90 access control
    user_role = str(user['role'] if 'role' in user else '').lower()
    try:
        is_mvp = user['is_mvp90']
    except (KeyError, IndexError):
        is_mvp = False
    if user_role not in ('admin', 'docente') and not is_mvp:
        return templates.TemplateResponse(
            "academia/academia_locked.html",
            {"request": request, "user": user}
        )
    
    lesson = crud.get_lesson_by_id(db, lesson_id)
    if not lesson:
        raise HTTPException(status_code=404, detail="Lección no encontrada")
    
    # Only show published lessons to non-admins
    if lesson.status != 'published' and user['role'] != 'admin':
        raise HTTPException(status_code=403, detail="Esta lección aún no está disponible")
    
    course = crud.get_course_by_id(db, int(lesson.course_id))
    if not course:
        raise HTTPException(status_code=404, detail="Curso no encontrado")
    
    # Get all lessons in this course for navigation
    if user['role'] == 'admin':
        all_lessons = crud.get_lessons_by_course(db, int(lesson.course_id))
    else:
        all_lessons = crud.get_lessons_by_course(db, int(lesson.course_id), status='published')
    
    # Find prev/next
    lesson_ids = [int(l.id) for l in all_lessons]
    current_idx = lesson_ids.index(int(lesson_id)) if int(lesson_id) in lesson_ids else -1
    
    prev_lesson_id = lesson_ids[current_idx - 1] if current_idx > 0 else None
    next_lesson_id = lesson_ids[current_idx + 1] if current_idx < len(lesson_ids) - 1 else None
    
    # Get completion status
    user_progress = crud.get_user_progress(db, int(user['id']), int(lesson.course_id))
    progress_map = {p.lesson_id: bool(p.completed) for p in user_progress}
    completed = progress_map.get(int(lesson_id), False)
    
    # Parse content_data
    try:
        content_data = json.loads(lesson.content_data) if lesson.content_data else {}
    except:
        content_data = {}
    
    return templates.TemplateResponse(
        "academia/leccion.html",
        {
            "request": request,
            "user": user,
            "lesson": crud.lesson_to_dict(lesson),
            "course": crud.course_to_dict(course),
            "content_data": content_data,
            "completed": completed,
            "prev_lesson_id": prev_lesson_id,
            "next_lesson_id": next_lesson_id
        }
    )

# ============= API ROUTES (Students) =============

@router.post("/api/academia/enroll", response_class=JSONResponse)
async def api_enroll(request: Request, payload: EnrollmentCreate, db: Session = Depends(get_db)):
    """Enroll in a course"""
    user = current_user(request)
    if not user:
        raise HTTPException(status_code=401, detail="No autenticado")
    
    course = crud.get_course_by_id(db, payload.course_id)
    if not course or course.status != 'published':
        raise HTTPException(status_code=404, detail="Curso no encontrado")
    
    enrollment_id = crud.enroll_user(db, int(user['id']), payload.course_id)
    return {"ok": True, "enrollment_id": enrollment_id}

@router.post("/api/academia/progress", response_class=JSONResponse)
async def api_update_progress(request: Request, payload: ProgressUpdate, db: Session = Depends(get_db)):
    """Update lesson progress"""
    user = current_user(request)
    if not user:
        raise HTTPException(status_code=401, detail="No autenticado")
    
    lesson = crud.get_lesson_by_id(db, payload.lesson_id)
    if not lesson:
        raise HTTPException(status_code=404, detail="Lección no encontrada")
    
    progress_id = crud.update_progress(db, int(user['id']), payload.lesson_id, payload.completed)
    
    # Check if course is completed
    lesson = crud.get_lesson_by_id(db, payload.lesson_id)
    stats = crud.get_course_progress_stats(db, int(user['id']), lesson.course_id)
    course_completed = stats['percentage'] == 100
    
    return {
        "ok": True, 
        "progress_id": progress_id, 
        "completed": payload.completed,
        "course_completed": course_completed,
        "percentage": stats['percentage']
    }

@router.get("/api/academia/my-courses", response_class=JSONResponse)
async def api_my_courses(request: Request, db: Session = Depends(get_db)):
    """Get user's enrolled courses"""
    user = current_user(request)
    if not user:
        raise HTTPException(status_code=401, detail="No autenticado")
    
    enrollments = crud.get_user_enrollments(db, int(user['id']))
    
    courses_data = []
    for enrollment in enrollments:
        # Enrollment object has .course relationship eagerly loaded in crud
        if not enrollment.course:
            continue
            
        course = enrollment.course
        course_dict = crud.course_to_dict(course)
        # Add enrollment specific fields if needed, like enrolled_at
        course_dict['enrolled_at'] = enrollment.enrolled_at
        
        stats = crud.get_course_progress_stats(db, int(user['id']), int(course.id))
        course_dict['progress'] = stats
        courses_data.append(course_dict)
    
    return courses_data

# ============= ADMIN ROUTES =============

@router.get("/gestion-academia", response_class=HTMLResponse, name="gestion_academia")
async def gestion_academia(request: Request, db: Session = Depends(get_db)):
    """Admin panel for managing academy content"""
    user = require_docente_or_admin(request)
    
    # Get all courses
    courses = crud.get_all_courses(db)
    
    return templates.TemplateResponse(
        "academia/gestion-academia.html",
        {"request": request, "user": user, "courses": [crud.course_to_dict(c) for c in courses]}
    )

@router.get("/gestion-academia/curso/nuevo", response_class=HTMLResponse, name="gestion_academia_nuevo_curso")
async def gestion_academia_nuevo_curso(request: Request, db: Session = Depends(get_db)):
    """New course creation page"""
    user = require_docente_or_admin(request)

    return templates.TemplateResponse(
        "academia/editar-curso.html",
        {"request": request, "user": user, "course": None}
    )

@router.get("/gestion-academia/curso/{course_id}/editar", response_class=HTMLResponse, name="gestion_academia_editar_curso")
async def gestion_academia_editar_curso(request: Request, course_id: int, db: Session = Depends(get_db)):
    """Course edit page"""
    user = require_docente_or_admin(request)

    course = crud.get_course_by_id(db, course_id)
    if not course:
        raise HTTPException(status_code=404, detail="Curso no encontrado")

    return templates.TemplateResponse(
        "academia/editar-curso.html",
        {"request": request, "user": user, "course": crud.course_to_dict(course)}
    )


# ============= API ROUTES (Admin & Docente) =============

@router.post("/api/academia/upload-thumbnail", response_class=JSONResponse)
async def upload_thumbnail(request: Request, file: UploadFile = File(...)):
    """Upload course thumbnail image"""
    require_docente_or_admin(request)
    
    # Validate file extension
    file_ext = Path(file.filename).suffix.lower()
    if file_ext not in ALLOWED_EXTENSIONS:
        raise HTTPException(
            status_code=400, 
            detail=f"Formato no permitido. Use: {', '.join(ALLOWED_EXTENSIONS)}"
        )
    
    # Generate unique filename
    unique_filename = f"{uuid.uuid4()}{file_ext}"
    file_path = UPLOAD_DIR / unique_filename
    
    # Save file
    try:
        content = await file.read()
        with open(file_path, "wb") as f:
            f.write(content)
        
        # Return the relative URL
        return {"ok": True, "url": f"/static/uploads/miniaturas_cursos/{unique_filename}"}
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Error al subir archivo: {str(e)}")

# Attachment configuration
UPLOAD_ATTACHMENTS_DIR = Path("app/static/uploads/adjuntos-cursos")
UPLOAD_ATTACHMENTS_DIR.mkdir(parents=True, exist_ok=True)
# Allow a wide range of document and file types
ALLOWED_ATTACHMENT_EXTENSIONS = {
    ".pdf", ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", 
    ".txt", ".zip", ".rar", ".7z", ".jpg", ".jpeg", ".png", 
    ".mp3", ".mp4", ".mov", ".avi"
}

@router.post("/api/academia/upload-attachment", response_class=JSONResponse)
async def upload_attachment(request: Request, file: UploadFile = File(...)):
    """Upload course attachment file"""
    require_docente_or_admin(request)
    
    # Validate file extension
    file_ext = Path(file.filename).suffix.lower()
    if file_ext not in ALLOWED_ATTACHMENT_EXTENSIONS:
        # If not in the explicit list, maybe just allow it if it's not .exe/.bat/.sh? 
        # For now, let's keep it restrictive but broad enough.
        # Or easier: just warn but allow for now if user insists, but typically whitelist is safer.
        pass # Let's stick to the whitelist for now, can be expanded.
    
    # Generate unique filename to avoid collisions but keep original name part for reference if needed
    # Better: uuid + extension
    unique_filename = f"{uuid.uuid4()}{file_ext}"
    file_path = UPLOAD_ATTACHMENTS_DIR / unique_filename
    
    # Save file
    try:
        content = await file.read()
        with open(file_path, "wb") as f:
            f.write(content)
        
        # Return the relative URL and original filename
        return {
            "ok": True, 
            "url": f"/static/uploads/adjuntos-cursos/{unique_filename}",
            "filename": file.filename
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Error al subir archivo: {str(e)}")

@router.get("/api/academia/courses", response_class=JSONResponse)
async def api_get_courses(request: Request, db: Session = Depends(get_db), status: Optional[str] = None):
    """Get all courses (admin)"""
    require_docente_or_admin(request)
    courses = crud.get_all_courses(db, status=status)
    return [{"id": c.id, "title": c.title, "description": c.description, "thumbnail": c.thumbnail, "status": c.status, "created_at": c.created_at, "updated_at": c.updated_at, "order_index": c.order_index, "resource_url": c.resource_url, "resource_name": c.resource_name} for c in courses]

@router.post("/api/academia/courses", response_class=JSONResponse)
async def api_create_course(request: Request, payload: CourseCreate, db: Session = Depends(get_db)):
    """Create a course (admin)"""
    user = require_docente_or_admin(request)
    
    course_id = crud.create_course(
        db=db,
        title=payload.title,
        created_by=int(user['id']),
        description=payload.description,
        thumbnail=payload.thumbnail,
        status=payload.status
    )
    return {"ok": True, "course_id": course_id}

@router.put("/api/academia/courses/{course_id}", response_class=JSONResponse)
async def api_update_course(request: Request, course_id: int, payload: CourseUpdate, db: Session = Depends(get_db)):
    """Update a course (admin)"""
    require_docente_or_admin(request)
    
    updates = payload.dict(exclude_unset=True)
    success = crud.update_course(db, course_id, **updates)
    
    if not success:
        raise HTTPException(status_code=404, detail="Curso no encontrado")
    
    return {"ok": True, "course_id": course_id}

@router.delete("/api/academia/courses/{course_id}", response_class=JSONResponse)
async def api_delete_course(request: Request, course_id: int, db: Session = Depends(get_db)):
    """Delete a course (admin)"""
    require_docente_or_admin(request)
    crud.delete_course(db, course_id)
    return {"ok": True}

# ============= API ROUTES (Sections - Admin & Docente) =============

@router.get("/api/academia/sections", response_class=JSONResponse)
async def api_get_sections(request: Request, course_id: int, db: Session = Depends(get_db)):
    """Get sections for a course (admin)"""
    require_docente_or_admin(request)
    sections = crud.get_sections_by_course(db, course_id)
    return [{"id": s.id, "course_id": s.course_id, "title": s.title, "description": s.description, "order_index": s.order_index, "created_at": s.created_at, "updated_at": s.updated_at} for s in sections]

@router.post("/api/academia/sections", response_class=JSONResponse)
async def api_create_section(request: Request, payload: SectionCreate, db: Session = Depends(get_db)):
    """Create a section (admin)"""
    require_docente_or_admin(request)
    
    section_id = crud.create_section(
        db=db,
        course_id=payload.course_id,
        title=payload.title,
        description=payload.description,
        order_index=payload.order_index or 0
    )
    return {"ok": True, "section_id": section_id}

@router.put("/api/academia/sections/{section_id}", response_class=JSONResponse)
async def api_update_section(request: Request, section_id: int, payload: SectionUpdate, db: Session = Depends(get_db)):
    """Update a section (admin)"""
    require_docente_or_admin(request)
    
    updates = payload.dict(exclude_unset=True)
    success = crud.update_section(db, section_id, **updates)
    
    if not success:
        raise HTTPException(status_code=404, detail="Sección no encontrada")
    
    return {"ok": True, "section_id": section_id}

@router.delete("/api/academia/sections/{section_id}", response_class=JSONResponse)
async def api_delete_section(request: Request, section_id: int, db: Session = Depends(get_db)):
    """Delete a section (admin)"""
    require_docente_or_admin(request)
    crud.delete_section(db, section_id)
    return {"ok": True}

# ============= API ROUTES (Lessons - Admin & Docente) =============

@router.get("/api/academia/lessons", response_class=JSONResponse)
async def api_get_lessons(request: Request, course_id: int, db: Session = Depends(get_db)):
    """Get lessons for a course (admin)"""
    require_docente_or_admin(request)
    lessons = crud.get_lessons_by_course(db, course_id)
    return [{"id": l.id, "course_id": l.course_id, "section_id": l.section_id, "title": l.title, "description": l.description, "content_type": l.content_type, "content_data": l.content_data, "duration_minutes": l.duration_minutes, "order_index": l.order_index, "status": l.status, "created_at": l.created_at, "updated_at": l.updated_at, "attachment_url": l.attachment_url, "attachment_name": l.attachment_name} for l in lessons]

@router.post("/api/academia/lessons", response_class=JSONResponse)
async def api_create_lesson(request: Request, payload: LessonCreate, db: Session = Depends(get_db)):
    """Create a lesson (admin)"""
    require_docente_or_admin(request)
    
    lesson_id = crud.create_lesson(
        db=db,
        course_id=payload.course_id,
        section_id=payload.section_id,
        title=payload.title,
        description=payload.description,
        content_type=payload.content_type,
        content_data=payload.content_data,
        duration_minutes=payload.duration_minutes,
        order_index=payload.order_index or 0,
        status=payload.status or 'published',
        attachment_url=payload.attachment_url,
        attachment_name=payload.attachment_name
    )
    return {"ok": True, "lesson_id": lesson_id}

@router.put("/api/academia/lessons/{lesson_id}", response_class=JSONResponse)
async def api_update_lesson(request: Request, lesson_id: int, payload: LessonUpdate, db: Session = Depends(get_db)):
    """Update a lesson (admin)"""
    require_docente_or_admin(request)
    
    updates = payload.dict(exclude_unset=True)
    success = crud.update_lesson(db, lesson_id, **updates)
    
    if not success:
        raise HTTPException(status_code=404, detail="Lección no encontrada")
    
    return {"ok": True, "lesson_id": lesson_id}

@router.delete("/api/academia/lessons/{lesson_id}", response_class=JSONResponse)
async def api_delete_lesson(request: Request, lesson_id: int, db: Session = Depends(get_db)):
    """Delete a lesson (admin)"""
    try:
        require_docente_or_admin(request)
        crud.delete_lesson(db, lesson_id)
        return {"ok": True}
    except Exception as e:
        print(f"Error deleting lesson {lesson_id}: {e}")
        return JSONResponse(
            status_code=500,
            content={"ok": False, "error": str(e)}
        )
