"""
QI Projects Console UI views

Provides full CRUD functionality for Quality Improvement projects,
task management, and template handling.
"""

from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.core.paginator import Paginator
from django.db.models import Q
from django.shortcuts import get_object_or_404, redirect, render
from django.utils.translation import gettext_lazy as _

from apps.core.decorators import block_source_user
from apps.core.models import StatusChoices
from apps.organizations.models import Hospital
from apps.px_action_center.models import PXAction

from .forms import ConvertToProjectForm, QIProjectForm, QIProjectTaskForm, QIProjectTemplateForm, TaskTemplateFormSet
from .models import QIProject, QIProjectTask, PDCAPhase, PDCAPhaseChoices, FOCUSPhase, FOCUSPhaseChoices


@block_source_user
@login_required
def project_list(request):
    """QI Projects list view with filtering and pagination"""
    # Exclude templates from the list
    queryset = (
        QIProject.objects.filter(is_template=False)
        .select_related("hospital", "department", "project_lead")
        .prefetch_related("team_members", "related_actions")
    )

    # Apply RBAC filters
    user = request.user
    # Get selected hospital for PX Admins (from middleware)
    selected_hospital = getattr(request, "tenant_hospital", None)

    if user.is_px_admin():
        # PX Admins see all, but filter by selected hospital if set
        if selected_hospital:
            queryset = queryset.filter(hospital=selected_hospital)
    elif user.hospital:
        queryset = queryset.filter(hospital=user.hospital)

    # Apply filters
    status_filter = request.GET.get("status")
    if status_filter:
        queryset = queryset.filter(status=status_filter)

    hospital_filter = request.GET.get("hospital")
    if hospital_filter:
        queryset = queryset.filter(hospital_id=hospital_filter)

    # Search
    search_query = request.GET.get("search")
    if search_query:
        queryset = queryset.filter(
            Q(name__icontains=search_query)
            | Q(description__icontains=search_query)
            | Q(name_ar__icontains=search_query)
        )

    # Ordering
    queryset = queryset.order_by("-created_at")

    # Pagination
    page_size = int(request.GET.get("page_size", 25))
    paginator = Paginator(queryset, page_size)
    page_number = request.GET.get("page", 1)
    page_obj = paginator.get_page(page_number)

    # Get hospitals for filter
    hospitals = Hospital.objects.filter(status="active")
    if not user.is_px_admin() and user.hospital:
        hospitals = hospitals.filter(id=user.hospital.id)

    # Statistics
    stats = {
        "total": queryset.count(),
        "active": queryset.filter(status="active").count(),
        "completed": queryset.filter(status="completed").count(),
        "pending": queryset.filter(status="pending").count(),
    }

    context = {
        "page_obj": page_obj,
        "projects": page_obj.object_list,
        "stats": stats,
        "filters": request.GET,
    }

    return render(request, "projects/project_list.html", context)


@block_source_user
@login_required
def project_detail(request, pk):
    """QI Project detail view with kanban board"""
    from django.utils import timezone

    project = get_object_or_404(
        QIProject.objects.filter(is_template=False)
        .select_related("hospital", "department", "project_lead")
        .prefetch_related("team_members", "related_actions", "tasks", "pdca_phases", "focus_phases"),
        pk=pk,
    )

    # Check permission
    user = request.user
    if not user.is_px_admin() and user.hospital and project.hospital != user.hospital:
        messages.error(request, _("You don't have permission to view this project."))
        return redirect("projects:project_list")

    # Get related actions
    related_actions = project.related_actions.all()

    # Get PDCA phases (auto-create if missing)
    pdca_phases = {}
    pdca_tasks = {}
    for phase_key, phase_label in PDCAPhaseChoices.choices:
        phase_obj, _ = PDCAPhase.objects.get_or_create(
            project=project,
            phase=phase_key,
            defaults={"title": phase_label},
        )
        pdca_phases[phase_key] = phase_obj
        pdca_tasks[phase_key] = phase_obj.tasks.all().order_by("order", "created_at")

    # Get FOCUS phases (auto-create if missing)
    focus_phases = {}
    focus_tasks = {}
    for phase_key, phase_label in FOCUSPhaseChoices.choices:
        phase_obj, _ = FOCUSPhase.objects.get_or_create(
            project=project,
            phase=phase_key,
            defaults={"title": phase_label},
        )
        focus_phases[phase_key] = phase_obj
        focus_tasks[phase_key] = phase_obj.tasks.all().order_by("order", "created_at")

    can_edit = user.is_px_admin() or user.is_hospital_admin() or user.is_department_manager
    today = timezone.now().date()

    context = {
        "project": project,
        "related_actions": related_actions,
        "pdca_phases": pdca_phases,
        "pdca_phase_choices": PDCAPhaseChoices.choices,
        "pdca_tasks": pdca_tasks,
        "focus_phases": focus_phases,
        "focus_phase_choices": FOCUSPhaseChoices.choices,
        "focus_tasks": focus_tasks,
        "can_edit": can_edit,
        "today": today,
    }

    return render(request, "projects/project_detail.html", context)


@block_source_user
@login_required
def project_create(request, template_pk=None):
    """Create a new QI Project"""
    user = request.user

    # Check permission (PX Admin, Hospital Admin, or Department Manager)
    if not (user.is_px_admin() or user.is_hospital_admin() or user.is_department_manager()):
        messages.error(request, _("You don't have permission to create projects."))
        return redirect("projects:project_list")

    # Check for template parameter (from URL or GET)
    template_id = template_pk or request.GET.get("template")
    initial_data = {}
    template = None

    if template_id:
        try:
            template = QIProject.objects.get(pk=template_id, is_template=True)
            initial_data = {
                "name": template.name,
                "name_ar": template.name_ar,
                "description": template.description,
                "department": template.department,
                "target_completion_date": template.target_completion_date,
            }
            if not user.is_px_admin() and user.hospital:
                initial_data["hospital"] = user.hospital
        except QIProject.DoesNotExist:
            pass

    # Check for PX Action parameter (convert action to project)
    action_id = request.GET.get("action")

    # Check for related model (from complaint/observation/feedback/inquiry)
    related_model = request.GET.get("related_model")
    related_id = request.GET.get("related_id")

    if action_id:
        try:
            action = PXAction.objects.get(pk=action_id)
            initial_data["name"] = f"QI Project: {action.title}"
            initial_data["description"] = action.description
            if not user.is_px_admin() and user.hospital:
                initial_data["hospital"] = user.hospital
            else:
                initial_data["hospital"] = action.hospital
        except PXAction.DoesNotExist:
            pass
    elif related_model and related_id:
        try:
            from django.contrib.contenttypes.models import ContentType
            ct = ContentType.objects.get(model=related_model)
            model_class = ct.model_class()
            if model_class:
                obj = model_class.objects.filter(pk=related_id).first()
                if obj:
                    title = getattr(obj, "title", None) or getattr(obj, "subject", None) or ""
                    initial_data["name"] = f"QI Project: {title}" if title else ""
                    initial_data["description"] = getattr(obj, "description", "") or ""
                    if hasattr(obj, "hospital_id") and obj.hospital_id:
                        if user.is_px_admin():
                            initial_data["hospital"] = obj.hospital_id
                    if hasattr(obj, "department_id") and obj.department_id:
                        initial_data["department"] = obj.department_id
        except Exception:
            pass

    if request.method == "POST":
        form = QIProjectForm(request.POST, request=request)

        # Check for template in POST data (hidden field)
        template_id_post = request.POST.get("template_id")
        if template_id_post:
            try:
                template = QIProject.objects.get(pk=template_id_post, is_template=True)
            except QIProject.DoesNotExist:
                template = None

        if form.is_valid():
            project = form.save(commit=False)
            project.created_by = user
            project.save()
            form.save_m2m()  # Save many-to-many relationships

            # If created from template, copy tasks
            task_count = 0
            if template:
                for template_task in template.tasks.all():
                    QIProjectTask.objects.create(
                        project=project,
                        title=template_task.title,
                        description=template_task.description,
                        order=template_task.order,
                        status="pending",
                    )
                    task_count += 1

            # If created from action, link it
            if action_id:
                try:
                    action = PXAction.objects.get(pk=action_id)
                    project.related_actions.add(action)
                except PXAction.DoesNotExist:
                    pass

            # If created from related model, store link in metadata
            related_model_post = request.POST.get("related_model") or related_model
            related_id_post = request.POST.get("related_id") or related_id
            if related_model_post and related_id_post:
                project.metadata = project.metadata or {}
                project.metadata["related_model"] = related_model_post
                project.metadata["related_id"] = related_id_post
                project.save(update_fields=["metadata"])

            if template and task_count > 0:
                messages.success(
                    request,
                    _("QI Project created successfully with %(count)d task(s) from template.") % {"count": task_count},
                )
            else:
                messages.success(request, _("QI Project created successfully."))
            return redirect("projects:project_detail", pk=project.pk)
    else:
        form = QIProjectForm(request=request, initial=initial_data)

    context = {
        "form": form,
        "is_create": True,
        "template": template,
        "related_model": related_model,
        "related_id": related_id,
    }

    return render(request, "projects/project_form.html", context)


@block_source_user
@login_required
def project_edit(request, pk):
    """Edit an existing QI Project"""
    user = request.user
    project = get_object_or_404(QIProject, pk=pk, is_template=False)

    # Check permission
    if not user.is_px_admin() and user.hospital and project.hospital != user.hospital:
        messages.error(request, _("You don't have permission to edit this project."))
        return redirect("projects:project_list")

    # Check edit permission (PX Admin, Hospital Admin, or Department Manager)
    if not (user.is_px_admin() or user.is_hospital_admin() or user.is_department_manager()):
        messages.error(request, _("You don't have permission to edit projects."))
        return redirect("projects:project_detail", pk=project.pk)

    if request.method == "POST":
        form = QIProjectForm(request.POST, instance=project, request=request)
        if form.is_valid():
            form.save()
            messages.success(request, _("QI Project updated successfully."))
            return redirect("projects:project_detail", pk=project.pk)
    else:
        form = QIProjectForm(instance=project, request=request)

    context = {
        "form": form,
        "project": project,
        "is_create": False,
    }

    return render(request, "projects/project_form.html", context)


@block_source_user
@login_required
def project_delete(request, pk):
    """Delete a QI Project"""
    user = request.user
    project = get_object_or_404(QIProject, pk=pk, is_template=False)

    # Check permission (only PX Admin or Hospital Admin can delete)
    if not (user.is_px_admin() or user.is_hospital_admin):
        messages.error(request, _("You don't have permission to delete projects."))
        return redirect("projects:project_detail", pk=project.pk)

    if not user.is_px_admin() and user.hospital and project.hospital != user.hospital:
        messages.error(request, _("You don't have permission to delete this project."))
        return redirect("projects:project_list")

    if request.method == "POST":
        project_name = project.name
        project.delete()
        messages.success(request, _('Project "%(name)s" deleted successfully.') % {"name": project_name})
        return redirect("projects:project_list")

    context = {
        "project": project,
    }

    return render(request, "projects/project_delete_confirm.html", context)


@block_source_user
@login_required
def project_save_as_template(request, pk):
    """Save an existing project and its tasks as a template"""
    user = request.user
    project = get_object_or_404(QIProject, pk=pk, is_template=False)

    # Check permission (only PX Admin or Hospital Admin can create templates)
    if not (user.is_px_admin() or user.is_hospital_admin):
        messages.error(request, _("You don't have permission to create templates."))
        return redirect("projects:project_detail", pk=project.pk)

    # Check hospital access
    if not user.is_px_admin() and user.hospital and project.hospital != user.hospital:
        messages.error(request, _("You don't have permission to create templates from this project."))
        return redirect("projects:project_list")

    if request.method == "POST":
        template_name = request.POST.get("template_name", "").strip()
        template_description = request.POST.get("template_description", "").strip()
        make_global = request.POST.get("make_global") == "on"

        if not template_name:
            messages.error(request, _("Please provide a template name."))
            return redirect("projects:project_save_as_template", pk=project.pk)

        # Create template from project
        template = QIProject.objects.create(
            name=template_name,
            name_ar=template_name,  # Can be edited later
            description=template_description or project.description,
            is_template=True,
            # If global, hospital is None; otherwise use project's hospital
            hospital=None if make_global else project.hospital,
            department=project.department,
            status="pending",  # Default status for templates
            created_by=user,
        )

        # Copy tasks from project to template
        for task in project.tasks.all():
            QIProjectTask.objects.create(
                project=template,
                title=task.title,
                description=task.description,
                order=task.order,
                status="pending",  # Reset status for template
            )

        messages.success(
            request,
            _('Template "%(name)s" created successfully with %(count)d task(s).')
            % {"name": template_name, "count": project.tasks.count()},
        )
        return redirect("projects:template_list")

    context = {
        "project": project,
        "suggested_name": f"Template: {project.name}",
    }

    return render(request, "projects/project_save_as_template.html", context)


# =============================================================================
# Task Management Views
# =============================================================================


def _task_redirect(project, task):
    """Helper to redirect to phase detail if task belongs to a phase, else project detail."""
    if task and task.pdca_phase:
        return redirect("projects:pdca_phase_detail", pk=project.pk, phase=task.pdca_phase.phase)
    if task and task.focus_phase:
        return redirect("projects:focus_phase_detail", pk=project.pk, phase=task.focus_phase.phase)
    return redirect("projects:project_detail", pk=project.pk)


@block_source_user
@login_required
def task_create(request, project_pk, phase=None):
    """Add a new task to a project (optionally within a PDCA or FOCUS phase)"""
    user = request.user
    project = get_object_or_404(QIProject, pk=project_pk, is_template=False)
    current_phase = None
    phase_type = None
    if phase and phase in [c[0] for c in PDCAPhaseChoices.choices]:
        current_phase = get_object_or_404(PDCAPhase, phase=phase, project=project)
        phase_type = "pdca"
    elif phase and phase in [c[0] for c in FOCUSPhaseChoices.choices]:
        current_phase = get_object_or_404(FOCUSPhase, phase=phase, project=project)
        phase_type = "focus"

    # Check permission
    if not user.is_px_admin() and user.hospital and project.hospital != user.hospital:
        messages.error(request, _("You don't have permission to add tasks to this project."))
        return redirect("projects:project_detail", pk=project.pk)

    if request.method == "POST":
        form = QIProjectTaskForm(request.POST, project=project, current_phase=current_phase, phase_type=phase_type)
        if form.is_valid():
            task = form.save(commit=False)
            task.project = project
            task.save()
            messages.success(request, _("Task added successfully."))
            return _task_redirect(project, task)
    else:
        form = QIProjectTaskForm(project=project, current_phase=current_phase, phase_type=phase_type)

    context = {
        "form": form,
        "project": project,
        "pdca_phase": current_phase if phase_type == "pdca" else None,
        "focus_phase": current_phase if phase_type == "focus" else None,
        "is_create": True,
    }

    return render(request, "projects/task_form.html", context)


@block_source_user
@login_required
def task_edit(request, project_pk, task_pk, phase=None):
    """Edit an existing task"""
    user = request.user
    project = get_object_or_404(QIProject, pk=project_pk, is_template=False)
    task = get_object_or_404(QIProjectTask, pk=task_pk, project=project)
    current_phase = None
    phase_type = None
    if phase and phase in [c[0] for c in PDCAPhaseChoices.choices]:
        current_phase = get_object_or_404(PDCAPhase, phase=phase, project=project)
        phase_type = "pdca"
    elif phase and phase in [c[0] for c in FOCUSPhaseChoices.choices]:
        current_phase = get_object_or_404(FOCUSPhase, phase=phase, project=project)
        phase_type = "focus"

    # Check permission
    if not user.is_px_admin() and user.hospital and project.hospital != user.hospital:
        messages.error(request, _("You don't have permission to edit tasks in this project."))
        return redirect("projects:project_detail", pk=project.pk)

    if request.method == "POST":
        form = QIProjectTaskForm(request.POST, instance=task, project=project, current_phase=current_phase, phase_type=phase_type)
        if form.is_valid():
            task = form.save()
            # If status changed to completed, set completed_date
            if task.status == "completed" and not task.completed_date:
                from django.utils import timezone

                task.completed_date = timezone.now().date()
                task.save()
            messages.success(request, _("Task updated successfully."))
            return _task_redirect(project, task)
    else:
        form = QIProjectTaskForm(instance=task, project=project, current_phase=current_phase, phase_type=phase_type)

    context = {
        "form": form,
        "project": project,
        "task": task,
        "pdca_phase": current_phase if phase_type == "pdca" else None,
        "focus_phase": current_phase if phase_type == "focus" else None,
        "is_create": False,
    }

    return render(request, "projects/task_form.html", context)


@block_source_user
@login_required
def task_delete(request, project_pk, task_pk, phase=None):
    """Delete a task"""
    user = request.user
    project = get_object_or_404(QIProject, pk=project_pk, is_template=False)
    task = get_object_or_404(QIProjectTask, pk=task_pk, project=project)

    # Check permission
    if not user.is_px_admin() and user.hospital and project.hospital != user.hospital:
        messages.error(request, _("You don't have permission to delete tasks in this project."))
        return redirect("projects:project_detail", pk=project.pk)

    redirect_target = _task_redirect(project, task)

    if request.method == "POST":
        task.delete()
        messages.success(request, _("Task deleted successfully."))
        return redirect_target

    context = {
        "project": project,
        "task": task,
        "pdca_phase": task.pdca_phase,
        "focus_phase": task.focus_phase,
    }

    return render(request, "projects/task_delete_confirm.html", context)


@block_source_user
@login_required
def task_toggle_status(request, project_pk, task_pk, phase=None):
    """Quick toggle task status between pending and completed"""
    user = request.user
    project = get_object_or_404(QIProject, pk=project_pk, is_template=False)
    task = get_object_or_404(QIProjectTask, pk=task_pk, project=project)

    if not (user.is_px_admin() or user.is_hospital_admin() or user.is_department_manager()):
        messages.error(request, _("You don't have permission to update task status."))
        return redirect("projects:project_detail", pk=project.pk)

    # Check permission
    if not user.is_px_admin() and user.hospital and project.hospital != user.hospital:
        messages.error(request, _("You don't have permission to update tasks in this project."))
        return redirect("projects:project_detail", pk=project.pk)

    from django.utils import timezone

    if task.status == "completed":
        task.status = "pending"
        task.completed_date = None
    else:
        task.status = "completed"
        task.completed_date = timezone.now().date()

    task.save()
    messages.success(request, _("Task status updated."))
    return _task_redirect(project, task)


# =============================================================================
# Template Management Views
# =============================================================================


@block_source_user
@login_required
def template_list(request):
    """List QI Project templates"""
    user = request.user

    # Only admins can manage templates
    if not (user.is_px_admin() or user.is_hospital_admin):
        messages.error(request, _("You don't have permission to view templates."))
        return redirect("projects:project_list")

    queryset = QIProject.objects.filter(is_template=True).select_related("hospital", "department")

    # Apply RBAC filters
    if not user.is_px_admin():
        from django.db.models import Q

        queryset = queryset.filter(Q(hospital=user.hospital) | Q(hospital__isnull=True))

    # Search
    search_query = request.GET.get("search")
    if search_query:
        queryset = queryset.filter(
            Q(name__icontains=search_query)
            | Q(description__icontains=search_query)
            | Q(name_ar__icontains=search_query)
        )

    queryset = queryset.order_by("name")

    context = {
        "templates": queryset,
        "can_create": user.is_px_admin() or user.is_hospital_admin,
        "can_edit": user.is_px_admin() or user.is_hospital_admin,
    }

    return render(request, "projects/template_list.html", context)


@block_source_user
@login_required
def template_detail(request, pk):
    """View template details with tasks"""
    user = request.user

    # Only admins can view templates
    if not (user.is_px_admin() or user.is_hospital_admin):
        messages.error(request, _("You don't have permission to view templates."))
        return redirect("projects:project_list")

    template = get_object_or_404(
        QIProject.objects.filter(is_template=True).select_related("hospital", "department"), pk=pk
    )

    # Check permission for hospital-specific templates
    if not user.is_px_admin():
        from django.db.models import Q

        if template.hospital and template.hospital != user.hospital:
            messages.error(request, _("You don't have permission to view this template."))
            return redirect("projects:template_list")

    # Get tasks
    tasks = template.tasks.all().order_by("order", "created_at")

    context = {
        "template": template,
        "tasks": tasks,
    }

    return render(request, "projects/template_detail.html", context)


@block_source_user
@login_required
def template_create(request):
    """Create a new project template"""
    user = request.user

    # Only admins can create templates
    if not (user.is_px_admin() or user.is_hospital_admin):
        messages.error(request, _("You don't have permission to create templates."))
        return redirect("projects:project_list")

    if request.method == "POST":
        form = QIProjectTemplateForm(request.POST, request=request)
        if form.is_valid():
            template = form.save(commit=False)
            template.is_template = True
            template.created_by = user
            template.save()

            # Save task templates formset
            formset = TaskTemplateFormSet(request.POST, instance=template, prefix="tasktemplate_set")
            if formset.is_valid():
                formset.save()

            messages.success(request, _("Project template created successfully."))
            return redirect("projects:template_list")
        else:
            # Form is invalid, show formset with errors
            formset = TaskTemplateFormSet(request.POST, prefix="tasktemplate_set")
    else:
        form = QIProjectTemplateForm(request=request)
        formset = TaskTemplateFormSet(prefix="tasktemplate_set")

    context = {
        "form": form,
        "formset": formset,
        "is_create": True,
    }

    return render(request, "projects/template_form.html", context)


@block_source_user
@login_required
def template_edit(request, pk):
    """Edit an existing project template"""
    user = request.user
    template = get_object_or_404(QIProject, pk=pk, is_template=True)

    # Check permission
    if not user.is_px_admin():
        if template.hospital and template.hospital != user.hospital:
            messages.error(request, _("You don't have permission to edit this template."))
            return redirect("projects:template_list")

    if request.method == "POST":
        form = QIProjectTemplateForm(request.POST, instance=template, request=request)
        formset = TaskTemplateFormSet(request.POST, instance=template, prefix="tasktemplate_set")
        if form.is_valid() and formset.is_valid():
            form.save()
            formset.save()
            messages.success(request, _("Project template updated successfully."))
            return redirect("projects:template_list")
    else:
        form = QIProjectTemplateForm(instance=template, request=request)
        formset = TaskTemplateFormSet(instance=template, prefix="tasktemplate_set")

    context = {
        "form": form,
        "formset": formset,
        "template": template,
        "is_create": False,
    }

    return render(request, "projects/template_form.html", context)


@block_source_user
@login_required
def template_delete(request, pk):
    """Delete a project template"""
    user = request.user
    template = get_object_or_404(QIProject, pk=pk, is_template=True)

    # Check permission
    if not user.is_px_admin():
        if template.hospital and template.hospital != user.hospital:
            messages.error(request, _("You don't have permission to delete this template."))
            return redirect("projects:template_list")

    if request.method == "POST":
        template_name = template.name
        template.delete()
        messages.success(request, _('Template "%(name)s" deleted successfully.') % {"name": template_name})
        return redirect("projects:template_list")

    context = {
        "template": template,
    }

    return render(request, "projects/template_delete_confirm.html", context)


# =============================================================================
# PX Action Conversion View
# =============================================================================


@block_source_user
@login_required
def convert_action_to_project(request, action_pk):
    """Convert a PX Action to a QI Project"""
    user = request.user

    # Check permission
    if not (user.is_px_admin() or user.is_hospital_admin() or user.is_department_manager()):
        messages.error(request, _("You don't have permission to create projects."))
        return redirect("px_action_center:action_detail", pk=action_pk)

    action = get_object_or_404(PXAction, pk=action_pk)

    # Check hospital access
    if not user.is_px_admin() and user.hospital and action.hospital != user.hospital:
        messages.error(request, _("You don't have permission to convert this action."))
        return redirect("px_action_center:action_detail", pk=action_pk)

    if request.method == "POST":
        form = ConvertToProjectForm(request.POST, request=request, action=action)
        if form.is_valid():
            # Create project from template or blank
            template = form.cleaned_data.get("template")

            if template:
                # Copy from template
                project = QIProject.objects.create(
                    name=form.cleaned_data["project_name"],
                    name_ar=template.name_ar,
                    description=template.description,
                    hospital=action.hospital,
                    department=template.department,
                    project_lead=form.cleaned_data["project_lead"],
                    target_completion_date=form.cleaned_data["target_completion_date"],
                    status="pending",
                    created_by=user,
                )
                # Copy tasks from template
                for template_task in template.tasks.all():
                    QIProjectTask.objects.create(
                        project=project,
                        title=template_task.title,
                        description=template_task.description,
                        order=template_task.order,
                        status="pending",
                    )
            else:
                # Create blank project
                project = QIProject.objects.create(
                    name=form.cleaned_data["project_name"],
                    description=action.description,
                    hospital=action.hospital,
                    project_lead=form.cleaned_data["project_lead"],
                    target_completion_date=form.cleaned_data["target_completion_date"],
                    status="pending",
                    created_by=user,
                )

            # Link to the action
            project.related_actions.add(action)

            messages.success(request, _("PX Action converted to QI Project successfully."))
            return redirect("projects:project_detail", pk=project.pk)
    else:
        initial_data = {
            "project_name": f"QI Project: {action.title}",
        }
        form = ConvertToProjectForm(request=request, action=action, initial=initial_data)

    context = {
        "form": form,
        "action": action,
    }

    return render(request, "projects/convert_action.html", context)


@block_source_user
@login_required
def pdca_phase_detail(request, pk, phase):
    """Detail view for a PDCA phase, showing phase info and its tasks"""
    if phase not in [c[0] for c in PDCAPhaseChoices.choices]:
        messages.error(request, _("Invalid PDCA phase."))
        return redirect("projects:project_detail", pk=pk)

    project = get_object_or_404(QIProject, pk=pk, is_template=False)
    user = request.user

    if not user.is_px_admin() and user.hospital and project.hospital != user.hospital:
        messages.error(request, _("You don't have permission."))
        return redirect("projects:project_list")

    pdca_phase, created = PDCAPhase.objects.get_or_create(
        project=project,
        phase=phase,
        defaults={"title": PDCAPhaseChoices(phase).label},
    )

    tasks = pdca_phase.tasks.all().order_by("order", "created_at")
    can_edit = user.is_px_admin() or user.is_hospital_admin() or user.is_department_manager

    from django.utils import timezone

    phase_task_counts = {p.phase: p.tasks.count() for p in project.pdca_phases.prefetch_related("tasks").all()}

    context = {
        "project": project,
        "pdca_phase": pdca_phase,
        "phase_key": phase,
        "phase_label": PDCAPhaseChoices(phase).label,
        "tasks": tasks,
        "can_edit": can_edit,
        "today": timezone.now().date(),
        "pdca_phase_choices": PDCAPhaseChoices.choices,
        "phase_task_counts": phase_task_counts,
    }

    return render(request, "projects/pdca_phase_detail.html", context)


@block_source_user
@login_required
def pdca_phase_edit(request, pk, phase):
    """Edit a PDCA phase for a QI project"""
    if phase not in [c[0] for c in PDCAPhaseChoices.choices]:
        messages.error(request, _("Invalid PDCA phase."))
        return redirect("projects:project_detail", pk=pk)

    project = get_object_or_404(QIProject, pk=pk, is_template=False)
    user = request.user

    if not user.is_px_admin() and user.hospital and project.hospital != user.hospital:
        messages.error(request, _("You don't have permission."))
        return redirect("projects:project_list")

    can_edit = user.is_px_admin() or user.is_hospital_admin() or user.is_department_manager
    if not can_edit:
        messages.error(request, _("You don't have permission to edit this project."))
        return redirect("projects:pdca_phase_detail", pk=project.pk, phase=phase)

    pdca_phase, created = PDCAPhase.objects.get_or_create(
        project=project,
        phase=phase,
        defaults={"title": PDCAPhaseChoices(phase).label},
    )

    if request.method == "POST":
        pdca_phase.title = request.POST.get("title", pdca_phase.title)
        pdca_phase.description = request.POST.get("description", "")
        pdca_phase.findings = request.POST.get("findings", "")
        pdca_phase.status = request.POST.get("status", StatusChoices.PENDING)
        pdca_phase.start_date = request.POST.get("start_date") or None
        pdca_phase.due_date = request.POST.get("due_date") or None

        owner_id = request.POST.get("owner")
        if owner_id:
            from apps.accounts.models import User

            try:
                pdca_phase.owner = User.objects.get(pk=owner_id)
            except User.DoesNotExist:
                pass
        else:
            pdca_phase.owner = None

        pdca_phase.save()
        messages.success(request, _("%(phase)s phase updated successfully.") % {"phase": PDCAPhaseChoices(phase).label})
        return redirect("projects:pdca_phase_detail", pk=project.pk, phase=phase)

    from apps.accounts.models import User

    team_members = project.team_members.all()
    if project.project_lead:
        team_members = team_members | User.objects.filter(pk=project.project_lead.pk)

    context = {
        "project": project,
        "pdca_phase": pdca_phase,
        "phase_key": phase,
        "phase_label": PDCAPhaseChoices(phase).label,
        "team_members": team_members.distinct(),
        "status_choices": StatusChoices.choices,
    }

    return render(request, "projects/pdca_phase_form.html", context)


@block_source_user
@login_required
def focus_phase_detail(request, pk, phase):
    if phase not in [c[0] for c in FOCUSPhaseChoices.choices]:
        messages.error(request, _("Invalid FOCUS phase."))
        return redirect("projects:project_detail", pk=pk)

    project = get_object_or_404(QIProject, pk=pk, is_template=False)
    user = request.user

    if not user.is_px_admin() and user.hospital and project.hospital != user.hospital:
        messages.error(request, _("You don't have permission."))
        return redirect("projects:project_list")

    focus_phase, created = FOCUSPhase.objects.get_or_create(
        project=project,
        phase=phase,
        defaults={"title": FOCUSPhaseChoices(phase).label},
    )

    tasks = focus_phase.tasks.all().order_by("order", "created_at")
    can_edit = user.is_px_admin() or user.is_hospital_admin() or user.is_department_manager

    from django.utils import timezone

    phase_task_counts = {
        p.phase: p.tasks.count() for p in project.focus_phases.prefetch_related("tasks").all()
    }

    context = {
        "project": project,
        "focus_phase": focus_phase,
        "phase_key": phase,
        "phase_label": FOCUSPhaseChoices(phase).label,
        "tasks": tasks,
        "can_edit": can_edit,
        "today": timezone.now().date(),
        "focus_phase_choices": FOCUSPhaseChoices.choices,
        "phase_task_counts": phase_task_counts,
    }

    return render(request, "projects/focus_phase_detail.html", context)


@block_source_user
@login_required
def focus_phase_edit(request, pk, phase):
    if phase not in [c[0] for c in FOCUSPhaseChoices.choices]:
        messages.error(request, _("Invalid FOCUS phase."))
        return redirect("projects:project_detail", pk=pk)

    project = get_object_or_404(QIProject, pk=pk, is_template=False)
    user = request.user

    if not user.is_px_admin() and user.hospital and project.hospital != user.hospital:
        messages.error(request, _("You don't have permission."))
        return redirect("projects:project_list")

    can_edit = user.is_px_admin() or user.is_hospital_admin() or user.is_department_manager
    if not can_edit:
        messages.error(request, _("You don't have permission to edit this project."))
        return redirect("projects:focus_phase_detail", pk=project.pk, phase=phase)

    focus_phase, created = FOCUSPhase.objects.get_or_create(
        project=project,
        phase=phase,
        defaults={"title": FOCUSPhaseChoices(phase).label},
    )

    if request.method == "POST":
        focus_phase.title = request.POST.get("title", focus_phase.title)
        focus_phase.description = request.POST.get("description", "")
        focus_phase.findings = request.POST.get("findings", "")
        focus_phase.status = request.POST.get("status", StatusChoices.PENDING)
        focus_phase.start_date = request.POST.get("start_date") or None
        focus_phase.due_date = request.POST.get("due_date") or None

        owner_id = request.POST.get("owner")
        if owner_id:
            from apps.accounts.models import User

            try:
                focus_phase.owner = User.objects.get(pk=owner_id)
            except User.DoesNotExist:
                pass
        else:
            focus_phase.owner = None

        focus_phase.save()
        messages.success(
            request, _("%(phase)s phase updated successfully.") % {"phase": FOCUSPhaseChoices(phase).label}
        )
        return redirect("projects:focus_phase_detail", pk=project.pk, phase=phase)

    from apps.accounts.models import User

    team_members = project.team_members.all()
    if project.project_lead:
        team_members = team_members | User.objects.filter(pk=project.project_lead.pk)

    context = {
        "project": project,
        "focus_phase": focus_phase,
        "phase_key": phase,
        "phase_label": FOCUSPhaseChoices(phase).label,
        "team_members": team_members.distinct(),
        "status_choices": StatusChoices.choices,
    }

    return render(request, "projects/focus_phase_form.html", context)


@block_source_user
@login_required
def project_export_excel(request, pk):
    """Export QI project with PDCA data as Excel"""
    from django.http import HttpResponse

    project = get_object_or_404(QIProject, pk=pk, is_template=False)
    user = request.user

    if not user.is_px_admin() and user.hospital and project.hospital != user.hospital:
        messages.error(request, _("You don't have permission."))
        return redirect("projects:project_list")

    from .export_utils import export_project_excel

    workbook = export_project_excel(project)
    response = HttpResponse(content_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
    filename = f"QI_Project_{project.name.replace(' ', '_')}_{project.pk}.xlsx"
    response["Content-Disposition"] = f'attachment; filename="{filename}"'
    workbook.save(response)
    return response


# =============================================================================
# HTMX Endpoint Views for Kanban Board
# =============================================================================


def _check_project_permission(project, user):
    """Helper to check if user can access project."""
    if not user.is_px_admin() and user.hospital and project.hospital != user.hospital:
        return False
    return True


def _get_can_edit(user):
    """Helper to check edit permissions."""
    return user.is_px_admin() or user.is_hospital_admin() or user.is_department_manager


@block_source_user
@login_required
def htmx_task_toggle_status(request, project_pk, task_pk):
    """Toggle task status via HTMX - returns updated task row"""
    from django.utils import timezone
    from django.http import HttpResponse

    project = get_object_or_404(QIProject, pk=project_pk, is_template=False)
    task = get_object_or_404(QIProjectTask, pk=task_pk, project=project)
    user = request.user

    if not _check_project_permission(project, user):
        return HttpResponse(_("Permission denied"), status=403)

    if task.status == "completed":
        task.status = "pending"
        task.completed_date = None
    else:
        task.status = "completed"
        task.completed_date = timezone.now().date()

    task.save()

    can_edit = _get_can_edit(user)
    today = timezone.now().date()

    return render(
        request,
        "projects/partials/task_row.html",
        {"task": task, "project": project, "can_edit": can_edit, "today": today},
    )


@block_source_user
@login_required
def htmx_task_delete(request, project_pk, task_pk):
    """Delete task via HTMX - returns empty with HX-Trigger"""
    from django.http import HttpResponse

    project = get_object_or_404(QIProject, pk=project_pk, is_template=False)
    task = get_object_or_404(QIProjectTask, pk=task_pk, project=project)
    user = request.user

    if not _check_project_permission(project, user):
        return HttpResponse(_("Permission denied"), status=403)

    if not _get_can_edit(user):
        return HttpResponse(_("You don't have permission to delete tasks."), status=403)

    # Determine which column to refresh
    phase_type = "pdca" if task.pdca_phase else "focus"
    phase_key = task.pdca_phase.phase if task.pdca_phase else task.focus_phase.phase

    task.delete()

    response = HttpResponse("")
    response["HX-Trigger"] = f'{{"taskDeleted": {{"phase_type": "{phase_type}", "phase": "{phase_key}"}}}}'
    return response


@block_source_user
@login_required
def htmx_task_create(request, project_pk, phase_type, phase):
    """Create task via HTMX - GET returns form, POST creates and returns column update"""
    from django.http import HttpResponse
    from django.utils import timezone

    project = get_object_or_404(QIProject, pk=project_pk, is_template=False)
    user = request.user

    if not _check_project_permission(project, user):
        return HttpResponse(_("Permission denied"), status=403)

    can_edit = _get_can_edit(user)
    if not can_edit:
        return HttpResponse(_("You don't have permission to add tasks."), status=403)

    # Get or create the phase
    current_phase = None
    if phase_type == "pdca":
        if phase not in [c[0] for c in PDCAPhaseChoices.choices]:
            return HttpResponse(_("Invalid phase"), status=400)
        current_phase, _ = PDCAPhase.objects.get_or_create(
            project=project,
            phase=phase,
            defaults={"title": PDCAPhaseChoices(phase).label},
        )
        form_phase_type = "pdca"
    elif phase_type == "focus":
        if phase not in [c[0] for c in FOCUSPhaseChoices.choices]:
            return HttpResponse(_("Invalid phase"), status=400)
        current_phase, _ = FOCUSPhase.objects.get_or_create(
            project=project,
            phase=phase,
            defaults={"title": FOCUSPhaseChoices(phase).label},
        )
        form_phase_type = "focus"
    else:
        return HttpResponse(_("Invalid phase type"), status=400)

    if request.method == "POST":
        form = QIProjectTaskForm(
            request.POST, project=project, current_phase=current_phase, phase_type=form_phase_type, allow_any_phase=True
        )
        if form.is_valid():
            task = form.save(commit=False)
            task.project = project
            task.save()

            # Determine which phase column to refresh
            target_phase_type = phase_type
            target_phase_key = phase
            if task.pdca_phase:
                target_phase_type = "pdca"
                target_phase_key = task.pdca_phase.phase
            elif task.focus_phase:
                target_phase_type = "focus"
                target_phase_key = task.focus_phase.phase

            # Return the updated task list for the target phase
            if target_phase_type == "pdca":
                target_phase = get_object_or_404(PDCAPhase, phase=target_phase_key, project=project)
            else:
                target_phase = get_object_or_404(FOCUSPhase, phase=target_phase_key, project=project)
            
            tasks = target_phase.tasks.all().order_by("order", "created_at")
            return render(
                request,
                "projects/partials/phase_task_list.html",
                {
                    "tasks": tasks,
                    "project": project,
                    "can_edit": can_edit,
                    "today": timezone.now().date(),
                    "phase_type": target_phase_type,
                    "phase_key": target_phase_key,
                },
            )
        else:
            # Return form with errors
            return render(
                request,
                "projects/partials/task_form_modal.html",
                {
                    "form": form,
                    "project": project,
                    "phase_type": phase_type,
                    "phase": current_phase,
                    "is_create": True,
                },
            )

    # GET - return form
    form = QIProjectTaskForm(project=project, current_phase=current_phase, phase_type=form_phase_type, allow_any_phase=True)
    return render(
        request,
        "projects/partials/task_form_modal.html",
        {
            "form": form,
            "project": project,
            "phase_type": phase_type,
            "phase": current_phase,
            "is_create": True,
        },
    )


@block_source_user
@login_required
def htmx_task_edit_form(request, project_pk, task_pk):
    """Edit task via HTMX - GET returns form, POST updates and returns task row"""
    from django.http import HttpResponse
    from django.utils import timezone

    project = get_object_or_404(QIProject, pk=project_pk, is_template=False)
    task = get_object_or_404(QIProjectTask, pk=task_pk, project=project)
    user = request.user

    if not _check_project_permission(project, user):
        return HttpResponse(_("Permission denied"), status=403)

    can_edit = _get_can_edit(user)
    if not can_edit:
        return HttpResponse(_("You don't have permission to edit tasks."), status=403)

    # Determine phase info
    current_phase = None
    phase_type = None
    if task.pdca_phase:
        current_phase = task.pdca_phase
        phase_type = "pdca"
    elif task.focus_phase:
        current_phase = task.focus_phase
        phase_type = "focus"

    if request.method == "POST":
        form = QIProjectTaskForm(
            request.POST, instance=task, project=project, current_phase=current_phase, phase_type=phase_type, allow_any_phase=True
        )
        if form.is_valid():
            task = form.save()
            if task.status == "completed" and not task.completed_date:
                task.completed_date = timezone.now().date()
                task.save()

            today = timezone.now().date()
            # Return updated task row
            return render(
                request,
                "projects/partials/task_row.html",
                {"task": task, "project": project, "can_edit": can_edit, "today": today},
            )
        else:
            # Return form with errors
            return render(
                request,
                "projects/partials/task_form_modal.html",
                {
                    "form": form,
                    "project": project,
                    "task": task,
                    "phase_type": phase_type,
                    "phase": current_phase,
                    "is_create": False,
                },
            )

    # GET - return form
    form = QIProjectTaskForm(instance=task, project=project, current_phase=current_phase, phase_type=phase_type, allow_any_phase=True)
    return render(
        request,
        "projects/partials/task_form_modal.html",
        {
            "form": form,
            "project": project,
            "task": task,
            "phase_type": phase_type,
            "phase": current_phase,
            "is_create": False,
        },
    )


@block_source_user
@login_required
def htmx_pdca_column(request, project_pk, phase):
    """Return PDCA column HTML for HTMX refresh"""
    from django.http import HttpResponse
    from django.utils import timezone

    if phase not in [c[0] for c in PDCAPhaseChoices.choices]:
        return HttpResponse(_("Invalid phase"), status=400)

    project = get_object_or_404(QIProject, pk=project_pk, is_template=False)
    user = request.user

    if not _check_project_permission(project, user):
        return HttpResponse(_("Permission denied"), status=403)

    can_edit = _get_can_edit(user)
    today = timezone.now().date()

    phase_obj, _ = PDCAPhase.objects.get_or_create(
        project=project,
        phase=phase,
        defaults={"title": PDCAPhaseChoices(phase).label},
    )

    tasks = phase_obj.tasks.all().order_by("order", "created_at")

    return render(
        request,
        "projects/partials/phase_column.html",
        {
            "project": project,
            "phase_obj": phase_obj,
            "phase_key": phase,
            "phase_label": PDCAPhaseChoices(phase).label,
            "tasks": tasks,
            "tasks_count": tasks.count(),
            "can_edit": can_edit,
            "today": today,
            "phase_type": "pdca",
        },
    )


@block_source_user
@login_required
def htmx_focus_column(request, project_pk, phase):
    """Return FOCUS column HTML for HTMX refresh"""
    from django.http import HttpResponse
    from django.utils import timezone

    if phase not in [c[0] for c in FOCUSPhaseChoices.choices]:
        return HttpResponse(_("Invalid phase"), status=400)

    project = get_object_or_404(QIProject, pk=project_pk, is_template=False)
    user = request.user

    if not _check_project_permission(project, user):
        return HttpResponse(_("Permission denied"), status=403)

    can_edit = _get_can_edit(user)
    today = timezone.now().date()

    phase_obj, _ = FOCUSPhase.objects.get_or_create(
        project=project,
        phase=phase,
        defaults={"title": FOCUSPhaseChoices(phase).label},
    )

    tasks = phase_obj.tasks.all().order_by("order", "created_at")

    return render(
        request,
        "projects/partials/phase_column.html",
        {
            "project": project,
            "phase_obj": phase_obj,
            "phase_key": phase,
            "phase_label": FOCUSPhaseChoices(phase).label,
            "tasks": tasks,
            "tasks_count": tasks.count(),
            "can_edit": can_edit,
            "today": today,
            "phase_type": "focus",
        },
    )


@block_source_user
@login_required
def htmx_phase_edit_form(request, project_pk, phase_type, phase):
    """Edit phase via HTMX - GET returns form, POST updates and returns header"""
    from django.http import HttpResponse
    from django.utils import timezone
    from apps.accounts.models import User

    project = get_object_or_404(QIProject, pk=project_pk, is_template=False)
    user = request.user

    if not _check_project_permission(project, user):
        return HttpResponse(_("Permission denied"), status=403)

    can_edit = _get_can_edit(user)
    if not can_edit:
        return HttpResponse(_("You don't have permission to edit phases."), status=403)

    if phase_type == "pdca":
        if phase not in [c[0] for c in PDCAPhaseChoices.choices]:
            return HttpResponse(_("Invalid phase"), status=400)
        phase_obj, created = PDCAPhase.objects.get_or_create(
            project=project,
            phase=phase,
            defaults={"title": PDCAPhaseChoices(phase).label},
        )
        phase_label = PDCAPhaseChoices(phase).label
    elif phase_type == "focus":
        if phase not in [c[0] for c in FOCUSPhaseChoices.choices]:
            return HttpResponse(_("Invalid phase"), status=400)
        phase_obj, created = FOCUSPhase.objects.get_or_create(
            project=project,
            phase=phase,
            defaults={"title": FOCUSPhaseChoices(phase).label},
        )
        phase_label = FOCUSPhaseChoices(phase).label
    else:
        return HttpResponse(_("Invalid phase type"), status=400)

    if request.method == "POST":
        phase_obj.title = request.POST.get("title", phase_obj.title)
        phase_obj.description = request.POST.get("description", "")
        phase_obj.findings = request.POST.get("findings", "")
        phase_obj.status = request.POST.get("status", StatusChoices.PENDING)
        phase_obj.start_date = request.POST.get("start_date") or None
        phase_obj.due_date = request.POST.get("due_date") or None

        owner_id = request.POST.get("owner")
        if owner_id:
            try:
                phase_obj.owner = User.objects.get(pk=owner_id)
            except User.DoesNotExist:
                pass
        else:
            phase_obj.owner = None

        phase_obj.save()

        # Return updated header
        tasks = phase_obj.tasks.all().order_by("order", "created_at")
        return render(
            request,
            "projects/partials/phase_header.html",
            {
                "project": project,
                "phase_obj": phase_obj,
                "phase_key": phase,
                "phase_label": phase_label,
                "tasks_count": tasks.count(),
                "can_edit": can_edit,
                "phase_type": phase_type,
            },
        )

    # GET - return form
    team_members = project.team_members.all()
    if project.project_lead:
        team_members = team_members | User.objects.filter(pk=project.project_lead.pk)

    return render(
        request,
        "projects/partials/phase_form_modal.html",
        {
            "project": project,
            "phase_obj": phase_obj,
            "phase_key": phase,
            "phase_label": phase_label,
            "phase_type": phase_type,
            "team_members": team_members.distinct(),
            "status_choices": StatusChoices.choices,
        },
    )
