from django.contrib import messages
from django.contrib.auth import get_user_model
from django.contrib.auth.decorators import user_passes_test
from django.db.models import Count, Q
from django.shortcuts import get_object_or_404, redirect, render
from django.utils.text import slugify

from users.models import UserProfile
from courses.models import Category, Course, Module, Lesson, Evaluation
from campus.models import Enrollment
from certificates.models import Certificate, DigitalSignature
from certificates.utils import create_institutional_p12_certificate


def is_studio_staff(user):
    """
    Verifica que el usuario tenga rol de Docente, Coordinador o Administrador en su perfil.
    """
    if not user.is_authenticated:
        return False
    if user.is_superuser:
        return True
    if hasattr(user, 'profile'):
        return user.profile.role in ['INSTRUCTOR', 'MANAGER', 'ADMIN']
    return False


@user_passes_test(is_studio_staff, login_url="users:login")
def studio_dashboard_view(request):
    """
    Dashboard ejecutivo del LMS Studio.
    """
    User = get_user_model()
    is_instructor_only = request.user.profile.role == 'INSTRUCTOR' and not request.user.is_superuser

    if is_instructor_only:
        my_courses = Course.objects.filter(instructor=request.user)
        total_courses = my_courses.count()
        total_enrollments = Enrollment.objects.filter(course__in=my_courses).count()
        total_certificates = Certificate.objects.filter(enrollment__course__in=my_courses).count()
        recent_enrollments = Enrollment.objects.filter(course__in=my_courses).select_related('user', 'course', 'user__profile').order_by('-enrolled_at')[:8]
    else:
        total_courses = Course.objects.count()
        total_enrollments = Enrollment.objects.count()
        total_certificates = Certificate.objects.count()
        recent_enrollments = Enrollment.objects.select_related('user', 'course', 'user__profile').order_by('-enrolled_at')[:8]

    total_students = UserProfile.objects.filter(role='STUDENT').count()

    courses_stats = Course.objects.annotate(enrollment_count=Count('enrollments')).order_by('-created_at')
    if is_instructor_only:
        courses_stats = courses_stats.filter(instructor=request.user)
    courses_stats = courses_stats[:6]

    context = {
        "total_courses": total_courses,
        "total_enrollments": total_enrollments,
        "total_certificates": total_certificates,
        "total_students": total_students,
        "recent_enrollments": recent_enrollments,
        "courses_stats": courses_stats,
        "user_profile": request.user.profile,
    }
    return render(request, "pages/studio/dashboard.html", context)


@user_passes_test(is_studio_staff, login_url="users:login")
def studio_courses_view(request):
    is_instructor_only = request.user.profile.role == 'INSTRUCTOR' and not request.user.is_superuser
    if is_instructor_only:
        courses = Course.objects.filter(instructor=request.user).select_related('category', 'instructor').order_by('-created_at')
    else:
        courses = Course.objects.select_related('category', 'instructor').order_by('-created_at')

    categories = Category.objects.all()
    context = {
        "courses": courses,
        "categories": categories,
        "user_profile": request.user.profile,
    }
    return render(request, "pages/studio/courses.html", context)


@user_passes_test(is_studio_staff, login_url="users:login")
def studio_course_create_view(request):
    if request.method == "POST":
        title = request.POST.get("title", "").strip()
        category_id = request.POST.get("category_id")
        short_description = request.POST.get("short_description", "").strip()
        description = request.POST.get("description", "").strip()
        iso_standard = request.POST.get("iso_standard", "ISO/IEC 17025").strip()

        if not title or not category_id:
            messages.error(request, "El Título y la Categoría son obligatorios para crear un curso.")
            return redirect("studio:studio_courses")

        category = get_object_or_404(Category, id=category_id)
        base_slug = slugify(title) or "nuevo-curso"
        slug = base_slug
        counter = 1
        while Course.objects.filter(slug=slug).exists():
            slug = f"{base_slug}-{counter}"
            counter += 1

        course = Course.objects.create(
            title=title,
            slug=slug,
            category=category,
            instructor=request.user,
            short_description=short_description,
            description=description,
            iso_standard=iso_standard,
            is_published=False
        )
        messages.success(request, f"¡Curso '{course.title}' creado exitosamente! Ahora puedes estructurar el temario.")
        return redirect("studio:studio_course_curriculum", slug=course.slug)

    return redirect("studio:studio_courses")


@user_passes_test(is_studio_staff, login_url="users:login")
def studio_course_edit_view(request, slug):
    course = get_object_or_404(Course, slug=slug)
    is_instructor_only = request.user.profile.role == 'INSTRUCTOR' and not request.user.is_superuser
    if is_instructor_only and course.instructor != request.user:
        messages.error(request, "No tienes permisos para editar este curso.")
        return redirect("studio:studio_courses")

    if request.method == "POST":
        title = request.POST.get("title", "").strip()
        category_id = request.POST.get("category_id")
        short_description = request.POST.get("short_description", "").strip()
        description = request.POST.get("description", "").strip()
        iso_standard = request.POST.get("iso_standard", "").strip()
        is_published = request.POST.get("is_published") == "on"

        if title: course.title = title
        if category_id: course.category = get_object_or_404(Category, id=category_id)
        if short_description: course.short_description = short_description
        if description: course.description = description
        if iso_standard: course.iso_standard = iso_standard
        course.is_published = is_published
        course.save()

        messages.success(request, f"Los cambios de '{course.title}' se guardaron correctamente.")
        return redirect("studio:studio_courses")

    categories = Category.objects.all()
    return render(request, "pages/studio/course_edit.html", {"course": course, "categories": categories})


@user_passes_test(is_studio_staff, login_url="users:login")
def studio_course_curriculum_view(request, slug):
    course = get_object_or_404(Course, slug=slug)
    is_instructor_only = request.user.profile.role == 'INSTRUCTOR' and not request.user.is_superuser
    if is_instructor_only and course.instructor != request.user:
        messages.error(request, "No tienes permisos para gestionar el temario de este curso.")
        return redirect("studio:studio_courses")

    evaluation, _ = Evaluation.objects.get_or_create(
        course=course,
        defaults={"title": f"Examen de Certificación: {course.title}", "passing_score": 75, "questions": []}
    )

    if request.method == "POST":
        action = request.POST.get("action")
        if action == "add_module":
            title = request.POST.get("module_title", "").strip()
            if title:
                order = course.modules.count() + 1
                Module.objects.create(course=course, title=title, order=order)
                messages.success(request, f"Módulo '{title}' agregado.")
        elif action == "add_lesson":
            module_id = request.POST.get("module_id")
            title = request.POST.get("lesson_title", "").strip()
            video_url = request.POST.get("video_url", "").strip()
            content = request.POST.get("content", "").strip()
            if module_id and title:
                module = get_object_or_404(Module, id=module_id, course=course)
                order = module.lessons.count() + 1
                base_slug = slugify(title) or "leccion"
                l_slug = f"{base_slug}-{course.id}-{module.id}-{order}"
                Lesson.objects.create(
                    module=module,
                    title=title,
                    slug=l_slug,
                    video_url=video_url,
                    content=content,
                    order=order
                )
                messages.success(request, f"Lección '{title}' agregada al módulo '{module.title}'.")
        elif action == "delete_module":
            module_id = request.POST.get("module_id")
            if module_id:
                Module.objects.filter(id=module_id, course=course).delete()
                messages.success(request, "Módulo eliminado.")
        elif action == "delete_lesson":
            lesson_id = request.POST.get("lesson_id")
            if lesson_id:
                Lesson.objects.filter(id=lesson_id, module__course=course).delete()
                messages.success(request, "Lección eliminada.")
        elif action == "add_question":
            q_text = request.POST.get("question_text", "").strip()
            opt_a = request.POST.get("option_a", "").strip()
            opt_b = request.POST.get("option_b", "").strip()
            opt_c = request.POST.get("option_c", "").strip()
            opt_d = request.POST.get("option_d", "").strip()
            correct = int(request.POST.get("correct_option", 0))

            options = [opt for opt in [opt_a, opt_b, opt_c, opt_d] if opt]
            if q_text and len(options) >= 2:
                q_list = list(evaluation.questions or [])
                new_id = max([q.get("id", 0) for q in q_list] + [0]) + 1
                q_list.append({
                    "id": new_id,
                    "text": q_text,
                    "options": options,
                    "correct": min(correct, len(options) - 1)
                })
                evaluation.questions = q_list
                evaluation.save()
                messages.success(request, "Pregunta agregada a la evaluación exitosamente.")
            else:
                messages.error(request, "La pregunta debe tener enunciado y al menos 2 opciones de respuesta.")
        elif action == "delete_question":
            q_id = int(request.POST.get("question_id", 0))
            q_list = [q for q in (evaluation.questions or []) if q.get("id") != q_id]
            evaluation.questions = q_list
            evaluation.save()
            messages.success(request, "Pregunta eliminada de la evaluación.")
        elif action == "save_evaluation_meta":
            title = request.POST.get("eval_title", "").strip()
            score = int(request.POST.get("passing_score", 75))
            if title:
                evaluation.title = title
                evaluation.passing_score = score
                evaluation.save()
                messages.success(request, "Ajustes de la evaluación guardados.")

        return redirect("studio:studio_course_curriculum", slug=course.slug)

    modules = course.modules.prefetch_related("lessons").order_by("order")
    return render(request, "pages/studio/curriculum.html", {
        "course": course,
        "modules": modules,
        "evaluation": evaluation
    })


@user_passes_test(is_studio_staff, login_url="users:login")
def studio_students_view(request):
    query = request.GET.get("q", "").strip()
    User = get_user_model()

    students = User.objects.filter(profile__role='STUDENT').select_related('profile')
    if query:
        students = students.filter(
            Q(first_name__icontains=query) |
            Q(last_name__icontains=query) |
            Q(email__icontains=query) |
            Q(profile__rut__icontains=query) |
            Q(profile__company__icontains=query)
        )

    enrollments = Enrollment.objects.select_related('user', 'course', 'user__profile').order_by('-enrolled_at')
    courses = Course.objects.filter(is_published=True)

    context = {
        "students": students,
        "enrollments": enrollments[:50],
        "courses": courses,
        "query": query,
    }
    return render(request, "pages/studio/students.html", context)


@user_passes_test(is_studio_staff, login_url="users:login")
def studio_enroll_student_view(request):
    if request.method == "POST":
        user_id = request.POST.get("user_id")
        course_id = request.POST.get("course_id")
        if user_id and course_id:
            User = get_user_model()
            student = get_object_or_404(User, id=user_id)
            course = get_object_or_404(Course, id=course_id)
            enrollment, created = Enrollment.objects.get_or_create(user=student, course=course)
            if created:
                messages.success(request, f"¡Alumno '{student.get_full_name() or student.username}' matriculado exitosamente en '{course.title}'!")
            else:
                messages.info(request, "El alumno ya se encontraba matriculado en este curso.")
    return redirect("studio:studio_students")


@user_passes_test(is_studio_staff, login_url="users:login")
def studio_certificates_view(request):
    if request.method == "POST":
        action = request.POST.get("action")
        if action == "upload_signature":
            pfx_file = request.FILES.get("pfx_file")
            p12_password = request.POST.get("p12_password", "").strip()
            signer_name = request.POST.get("signer_name", "Director Técnico & Calidad").strip()
            signer_role = request.POST.get("signer_role", "Supervisor de Laboratorio").strip()
            if pfx_file:
                DigitalSignature.objects.update(is_active=False)
                sig = DigitalSignature.objects.create(
                    name=pfx_file.name,
                    pfx_file=pfx_file,
                    p12_password=p12_password,
                    signer_name=signer_name,
                    signer_role=signer_role,
                    is_active=True
                )
                messages.success(request, f"Certificado digital '{sig.name}' cargado y activado para firmas PAdES.")
            else:
                messages.error(request, "Debes adjuntar un archivo .p12 o .pfx.")
        elif action == "generate_demo_signature":
            import os
            from django.conf import settings
            from django.core.files import File
            cert_dir = os.path.join(str(settings.MEDIA_ROOT), "certificates", "signatures")
            os.makedirs(cert_dir, exist_ok=True)
            cert_path = os.path.join(cert_dir, "certificado_institucional_lojusto.p12")
            create_institutional_p12_certificate(cert_path, password="lojusto_cert_2026")

            DigitalSignature.objects.update(is_active=False)
            with open(cert_path, "rb") as f:
                sig = DigitalSignature.objects.create(
                    name="Certificado Institucional Lo Justo (Autofirmado)",
                    p12_password="lojusto_cert_2026",
                    signer_name="Director Técnico & Calidad",
                    signer_role="Autoridad de Certificación Lo Justo",
                    is_active=True
                )
                sig.pfx_file.save("certificado_institucional_lojusto.p12", File(f), save=True)
            messages.success(request, "Certificado digital institucional generado y activado exitosamente.")
        elif action == "toggle_signature":
            sig_id = request.POST.get("signature_id")
            sig = get_object_or_404(DigitalSignature, id=sig_id)
            DigitalSignature.objects.update(is_active=False)
            sig.is_active = True
            sig.save()
            messages.success(request, f"Firma '{sig.name}' marcada como activa.")

        return redirect("studio:studio_certificates")

    query = request.GET.get("q", "").strip()
    certificates = Certificate.objects.select_related('enrollment__user', 'enrollment__course', 'enrollment__user__profile').order_by('-issued_at')
    if query:
        certificates = certificates.filter(
            Q(certificate_code__icontains=query) |
            Q(enrollment__user__first_name__icontains=query) |
            Q(enrollment__user__last_name__icontains=query) |
            Q(enrollment__course__title__icontains=query)
        )

    active_signature = DigitalSignature.objects.filter(is_active=True).first()
    signatures = DigitalSignature.objects.all()

    return render(request, "pages/studio/certificates.html", {
        "certificates": certificates,
        "query": query,
        "active_signature": active_signature,
        "signatures": signatures
    })


@user_passes_test(is_studio_staff, login_url="users:login")
def studio_categories_view(request):
    categories = Category.objects.annotate(courses_count=Count('courses')).order_by('title')
    return render(request, "pages/studio/categories.html", {"categories": categories})


@user_passes_test(is_studio_staff, login_url="users:login")
def studio_category_create_view(request):
    if request.method == "POST":
        title = request.POST.get("title", "").strip()
        description = request.POST.get("description", "").strip()
        icon = request.POST.get("icon", "rmx.book-open").strip()

        if not title:
            messages.error(request, "El título de la especialidad es obligatorio.")
            return redirect("studio:studio_categories")

        base_slug = slugify(title)
        slug = base_slug
        counter = 1
        while Category.objects.filter(slug=slug).exists():
            slug = f"{base_slug}-{counter}"
            counter += 1

        category = Category.objects.create(
            title=title,
            slug=slug,
            description=description,
            icon=icon
        )
        messages.success(request, f"Especialidad '{category.title}' creada exitosamente.")
    return redirect("studio:studio_categories")


@user_passes_test(is_studio_staff, login_url="users:login")
def studio_category_delete_view(request, category_id):
    if request.method == "POST":
        category = get_object_or_404(Category, id=category_id)
        if category.courses.exists():
            messages.error(request, f"No puedes eliminar '{category.title}' porque tiene cursos asignados.")
        else:
            category.delete()
            messages.success(request, f"Especialidad eliminada correctamente.")
    return redirect("studio:studio_categories")
