"""
Report Builder UI Views - Simplified Version

Handles the visual report builder interface, saved reports,
and exports. No chart functionality.
"""

import json
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.http import JsonResponse, HttpResponse
from django.shortcuts import render, redirect, get_object_or_404
from django.views.decorators.http import require_POST, require_GET
from django.views.decorators.csrf import ensure_csrf_cookie
from django.utils import timezone
from django.core.paginator import Paginator

from apps.organizations.models import Department, Hospital
from .models import SavedReport, GeneratedReport, ReportTemplate, DataSource, ReportFormat
from .services import ReportBuilderService, ReportExportService


@login_required
@ensure_csrf_cookie
def report_builder(request):
    """
    Visual report builder interface.

    Allows creating custom reports with:
    - Data source selection
    - Dynamic filters
    - Column selection
    - Chart configuration
    """
    user = request.user

    # Get hospitals for filter
    hospital = getattr(request, "tenant_hospital", None) or user.hospital
    hospitals = Hospital.objects.filter(status="active")
    if not user.is_px_admin() and hospital:
        hospitals = hospitals.filter(id=hospital.id)

    # Get saved reports
    saved_reports = SavedReport.objects.filter(created_by=user).order_by("-created_at")[:10]

    context = {
        "hospitals": hospitals,
        "saved_reports": saved_reports,
        "data_sources": DataSource.choices,
    }

    return render(request, "reports/report_builder.html", context)


@login_required
def report_preview_api(request):
    """
    API endpoint to preview report data.

    Returns JSON with:
    - Report data rows
    - Summary statistics
    - Chart data
    """
    if request.method != "POST":
        return JsonResponse({"error": "POST required"}, status=405)

    try:
        data = json.loads(request.body)
    except json.JSONDecodeError:
        return JsonResponse({"error": "Invalid JSON"}, status=400)

    data_source = data.get("data_source", "complaints")
    filter_config = data.get("filter_config", {})
    column_config = data.get("column_config", [])
    grouping_config = data.get("grouping_config", {})
    chart_config = data.get("chart_config", {})
    sort_config = data.get("sort_config", [])

    # Apply user's hospital restriction
    user = request.user
    hospital = getattr(request, "tenant_hospital", None) or user.hospital
    if not user.is_px_admin() and hospital:
        filter_config["hospital"] = str(hospital.id)

    # Generate report data
    report_data = ReportBuilderService.generate_report_data(
        data_source=data_source,
        filter_config=filter_config,
        column_config=column_config,
        grouping_config=grouping_config,
        sort_config=sort_config,
        user=user,
    )

    # Generate summary
    summary = ReportBuilderService.generate_summary(data_source, filter_config, user=user)

    return JsonResponse(
        {
            "success": True,
            "data": report_data,
            "summary": summary,
        }
    )


@login_required
def save_report(request):
    """Save a report configuration."""
    if request.method != "POST":
        return JsonResponse({"error": "POST required"}, status=405)

    try:
        data = json.loads(request.body)
    except json.JSONDecodeError:
        return JsonResponse({"error": "Invalid JSON"}, status=400)

    report_id = data.get("id")

    if report_id:
        # Update existing report
        report = get_object_or_404(SavedReport, id=report_id, created_by=request.user)
        report.name = data.get("name", report.name)
        report.description = data.get("description", report.description)
        report.data_source = data.get("data_source", report.data_source)
        report.filter_config = data.get("filter_config", report.filter_config)
        report.column_config = data.get("column_config", report.column_config)
        report.grouping_config = data.get("grouping_config", report.grouping_config)
        report.sort_config = data.get("sort_config", report.sort_config)
        report.is_shared = data.get("is_shared", report.is_shared)
        report.save()
    else:
        # Create new report
        report = SavedReport.objects.create(
            name=data.get("name", "Untitled Report"),
            description=data.get("description", ""),
            data_source=data.get("data_source", "complaints"),
            filter_config=data.get("filter_config", {}),
            column_config=data.get("column_config", []),
            grouping_config=data.get("grouping_config", {}),
            sort_config=data.get("sort_config", []),
            is_shared=data.get("is_shared", False),
            created_by=request.user,
            hospital=request.user.hospital,
        )

    return JsonResponse({"success": True, "report_id": str(report.id), "message": "Report saved successfully"})


@login_required
def saved_reports_list(request):
    """List all saved reports."""
    user = request.user

    # Get user's reports and shared reports
    hospital = getattr(request, "tenant_hospital", None) or user.hospital
    queryset = SavedReport.objects.filter(created_by=user)
    if hospital:
        queryset = queryset | SavedReport.objects.filter(is_shared=True, hospital=hospital)

    # Remove duplicates and order
    queryset = queryset.distinct().order_by("-created_at")

    # Filter by data source
    data_source = request.GET.get("data_source")
    if data_source:
        queryset = queryset.filter(data_source=data_source)

    # Search
    search = request.GET.get("search", "")
    if search:
        queryset = queryset.filter(name__icontains=search)

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

    context = {
        "page_obj": page_obj,
        "reports": page_obj.object_list,
        "data_sources": DataSource.choices,
        "search": search,
        "selected_source": data_source,
    }

    return render(request, "reports/saved_reports.html", context)


@login_required
def report_detail(request, report_id):
    """View a saved report with live data."""
    user = request.user

    report = get_object_or_404(SavedReport, id=report_id)

    # Check access
    hospital = getattr(request, "tenant_hospital", None) or user.hospital
    if report.created_by != user and not (report.is_shared and report.hospital == hospital):
        if not user.is_px_admin():
            messages.error(request, "You don't have access to this report.")
            return redirect("reports:saved_reports")

    # Apply user's hospital restriction
    filter_config = report.filter_config.copy()
    if not user.is_px_admin() and hospital:
        filter_config["hospital"] = str(hospital.id)

    # Generate report data
    report_data = ReportBuilderService.generate_report_data(
        data_source=report.data_source,
        filter_config=filter_config,
        column_config=report.column_config,
        grouping_config=report.grouping_config,
        sort_config=report.sort_config,
        user=user,
    )

    # Generate summary
    summary = ReportBuilderService.generate_summary(report.data_source, filter_config, user=user)

    # Update last run
    report.last_run_at = timezone.now()
    report.last_run_count = len(report_data.get("rows", []))
    report.save(update_fields=["last_run_at", "last_run_count"])

    context = {
        "report": report,
        "data": report_data,
        "summary": summary,
        "source_fields": ReportBuilderService.SOURCE_FIELDS.get(report.data_source, {}),
    }

    return render(request, "reports/report_detail.html", context)


@login_required
def delete_report(request, report_id):
    """Delete a saved report."""
    report = get_object_or_404(SavedReport, id=report_id, created_by=request.user)

    if request.method == "POST":
        report.delete()
        messages.success(request, "Report deleted successfully.")
        return redirect("reports:saved_reports")

    return render(request, "reports/report_confirm_delete.html", {"report": report})


@login_required
def export_report(request, report_id, export_format):
    """Export a report to Excel, PDF, or CSV."""
    user = request.user

    report = get_object_or_404(SavedReport, id=report_id)

    # Check access
    hospital = getattr(request, "tenant_hospital", None) or user.hospital
    if report.created_by != user and not (report.is_shared and report.hospital == hospital):
        if not user.is_px_admin():
            messages.error(request, "You don't have access to this report.")
            return redirect("reports:saved_reports")

    # Apply user's hospital restriction
    filter_config = report.filter_config.copy()
    if not user.is_px_admin() and hospital:
        filter_config["hospital"] = str(hospital.id)

    # Generate report data
    report_data = ReportBuilderService.generate_report_data(
        data_source=report.data_source,
        filter_config=filter_config,
        column_config=report.column_config,
        grouping_config=report.grouping_config,
        sort_config=report.sort_config,
        user=user,
    )

    rows = report_data.get("rows", [])
    columns = report_data.get("columns", [])
    column_keys = report_data.get("column_keys", columns)  # Use keys if available, fallback to labels

    # Generate filename
    filename = f"{report.name.replace(' ', '_')}_{timezone.now().strftime('%Y%m%d')}"

    # Export based on format
    if export_format == "csv":
        return ReportExportService.export_to_csv(rows, columns, column_keys, filename)
    elif export_format == "excel":
        return ReportExportService.export_to_excel(rows, columns, column_keys, filename)
    elif export_format == "pdf":
        return ReportExportService.export_to_pdf(rows, columns, column_keys, report.name, filename)
    else:
        messages.error(request, f"Unsupported export format: {export_format}")
        return redirect("reports:report_detail", report_id=report_id)


@login_required
def report_templates(request):
    """List available report templates."""
    templates = ReportTemplate.objects.filter(is_active=True).order_by("category", "sort_order", "name")

    # Group by category
    categories = {}
    for template in templates:
        cat = template.category or "General"
        if cat not in categories:
            categories[cat] = []
        categories[cat].append(template)

    context = {
        "categories": categories,
        "templates": templates,
    }

    return render(request, "reports/report_templates.html", context)


@login_required
def use_template(request, template_id):
    """Create a report from a template."""
    template = get_object_or_404(ReportTemplate, id=template_id, is_active=True)

    if request.method == "POST":
        # Create report from template with overrides
        overrides = {
            "name": request.POST.get("name", f"{template.name} - {timezone.now().strftime('%Y-%m-%d')}"),
        }

        # Apply any filter overrides from the form
        for key, value in request.POST.items():
            if key.startswith("filter_"):
                filter_key = key[7:]  # Remove 'filter_' prefix
                if "filter_config" not in overrides:
                    overrides["filter_config"] = template.filter_config.copy()
                overrides["filter_config"][filter_key] = value

        report = template.create_report(request.user, overrides)
        messages.success(request, f"Report created from template: {template.name}")
        return redirect("reports:report_detail", report_id=report.id)

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

    context = {
        "template": template,
        "hospitals": hospitals,
        "source_filters": ReportBuilderService.SOURCE_FILTERS.get(template.data_source, []),
    }

    return render(request, "reports/use_template.html", context)


@login_required
def filter_options_api(request):
    """API endpoint to get filter options for a data source."""
    data_source = request.GET.get("data_source", "complaints")

    options = {}

    # Status options - use defined choices, not database queries
    if data_source == "complaints":
        from apps.complaints.models import Complaint

        # Get unique status values from model choices
        options["status"] = (
            [choice[0] for choice in Complaint.STATUS_CHOICES]
            if hasattr(Complaint, "STATUS_CHOICES")
            else ["open", "in_progress", "resolved", "closed"]
        )
        options["severity"] = ["low", "medium", "high", "critical"]
        options["priority"] = ["low", "medium", "high", "urgent"]
        # Get unique source types from model choices or use defaults
        options["source"] = ["walk_in", "call", "email", "website", "social_media", "app"]

    elif data_source == "inquiries":
        from apps.complaints.models import Complaint

        options["status"] = (
            [choice[0] for choice in Complaint.STATUS_CHOICES]
            if hasattr(Complaint, "STATUS_CHOICES")
            else ["open", "in_progress", "resolved", "closed"]
        )

    elif data_source == "observations":
        from apps.observations.models import Observation, ObservationStatus

        options["status"] = [s.value for s in ObservationStatus]
        options["severity"] = ["low", "medium", "high", "critical"]

    elif data_source == "surveys":
        options["status"] = ["pending", "sent", "completed", "expired"]
        options["patient_type"] = ["inpatient", "outpatient", "emergency"]
        options["journey_type"] = ["admission", "discharge", "visit"]

    elif data_source == "px_actions":
        options["status"] = ["open", "in_progress", "completed", "closed"]
        options["priority"] = ["low", "medium", "high", "urgent"]

    elif data_source == "physicians":
        options["journey_type"] = ["inpatient", "outpatient", "emergency"]

    # Hospital options
    hospitals = Hospital.objects.filter(status="active")
    if not request.user.is_px_admin() and request.user.hospital:
        hospitals = hospitals.filter(id=request.user.hospital.id)
    options["hospitals"] = list(hospitals.values("id", "name"))

    # Department options (filtered by hospital if provided)
    hospital_id = request.GET.get("hospital")
    departments = Department.objects.filter(status="active")
    if hospital_id:
        departments = departments.filter(hospital_id=hospital_id)
    elif not request.user.is_px_admin() and request.user.hospital:
        departments = departments.filter(hospital=request.user.hospital)
    options["departments"] = list(departments.values("id", "name"))

    # Available columns for the data source
    fields = ReportBuilderService.SOURCE_FIELDS.get(data_source, {})
    # Default columns (first 8 fields)
    default_columns = list(fields.keys())[:8]
    options["columns"] = [
        {"key": key, "label": info["label"], "type": info["type"], "selected": key in default_columns}
        for key, info in fields.items()
    ]

    return JsonResponse(options)


@login_required
def available_fields_api(request):
    """API endpoint to get available fields for a data source."""
    data_source = request.GET.get("data_source", "complaints")

    fields = ReportBuilderService.SOURCE_FIELDS.get(data_source, {})

    return JsonResponse({"fields": {k: {"label": v["label"], "type": v["type"]} for k, v in fields.items()}})
