"""
revenue/views.py
================
Function-based views for Revenue Management (Module 4).
Includes CRUD endpoints, dashboard, and report with Excel export.

NOTE: ``horilla.decorators`` (NOT ``horilla_views.cbv_methods``) must be
used here — the latter expects a CBV ``self`` first-argument.
"""

import io
from datetime import date

from django.contrib import messages
from django.db.models import Q, Sum
from django.http import HttpResponse
from django.shortcuts import get_object_or_404, render
from django.utils.translation import gettext_lazy as _
from django.views.decorators.http import require_http_methods

from horilla.decorators import login_required, permission_required

from .forms import (
    RevenueHeadForm,
    RevenueItemForm,
    RevenueRecordForm,
    RevenueReportFilterForm,
    RevenueSubHeadForm,
)
from .models import RevenueHead, RevenueItem, RevenueRecord, RevenueSubHead


# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------


def _close_modal_reload():
    """Standard HTMX response to close the open modal and reload the page."""
    return HttpResponse(
        "<script>"
        "$('#genericModal').removeClass('oh-modal--show');"
        "$('#reloadMessagesButton').click();"
        "location.reload();"
        "</script>"
    )


def _hx_delete_response():
    """Standard response after a delete triggered from a list row."""
    return HttpResponse(
        "<script>"
        "$('.filterButton').click();"
        "$('#reloadMessagesButton').click();"
        "</script>"
    )


# ---------------------------------------------------------------------------
# Dashboard
# ---------------------------------------------------------------------------


@login_required
@permission_required("revenue.view_revenuehead")
def revenue_dashboard(request):
    today = date.today()
    current_year = today.year
    current_month = today.month

    ytd_records = RevenueRecord.objects.filter(transaction_date__year=current_year)
    mtd_records = ytd_records.filter(transaction_date__month=current_month)

    ytd_total = ytd_records.aggregate(t=Sum("amount"))["t"] or 0
    mtd_total = mtd_records.aggregate(t=Sum("amount"))["t"] or 0

    # Revenue by head (current year), single query
    head_totals = (
        RevenueRecord.objects.filter(transaction_date__year=current_year)
        .values("item__sub_head__head__id", "item__sub_head__head__code", "item__sub_head__head__name")
        .annotate(total=Sum("amount"))
        .order_by("-total")
    )

    recent = (
        RevenueRecord.objects.select_related("item__sub_head__head", "department", "recorded_by")
        .order_by("-transaction_date", "-created_at")[:10]
    )

    context = {
        "ytd_total": ytd_total,
        "mtd_total": mtd_total,
        "by_head": head_totals,
        "recent": recent,
        "current_year": current_year,
        "head_count": RevenueHead.objects.filter(is_active=True).count(),
        "item_count": RevenueItem.objects.filter(is_active=True).count(),
    }
    return render(request, "revenue/dashboard.html", context)


# ---------------------------------------------------------------------------
# Revenue Head CRUD
# ---------------------------------------------------------------------------


@login_required
@permission_required("revenue.view_revenuehead")
def revenue_head_list(request):
    heads = (
        RevenueHead.objects.filter(is_active=True)
        .prefetch_related("sub_heads")
        .order_by("name")
    )
    return render(request, "revenue/head_list.html", {"heads": heads})


@login_required
@permission_required("revenue.add_revenuehead")
def revenue_head_form(request, pk=None):
    instance = get_object_or_404(RevenueHead, pk=pk) if pk else None
    form = RevenueHeadForm(request.POST or None, instance=instance)
    if request.method == "POST" and form.is_valid():
        form.save()
        messages.success(request, _("Revenue head saved."))
        return _close_modal_reload()
    return render(
        request,
        "revenue/partials/form_modal.html",
        {"form": form, "title": _("Revenue Head"), "is_create": instance is None},
    )


@login_required
@permission_required("revenue.delete_revenuehead")
@require_http_methods(["POST", "DELETE"])
def revenue_head_delete(request, pk):
    obj = get_object_or_404(RevenueHead, pk=pk)
    obj.is_active = False
    obj.save(update_fields=["is_active"])
    messages.success(request, _("Revenue head deactivated."))
    return _hx_delete_response()


# ---------------------------------------------------------------------------
# Revenue Sub-Head CRUD
# ---------------------------------------------------------------------------


@login_required
@permission_required("revenue.view_revenuesubhead")
def revenue_sub_head_list(request):
    head_id = request.GET.get("head")
    qs = RevenueSubHead.objects.filter(is_active=True).select_related("head").order_by(
        "head__name", "name"
    )
    if head_id:
        qs = qs.filter(head_id=head_id)
    return render(request, "revenue/sub_head_list.html", {"sub_heads": qs})


@login_required
@permission_required("revenue.add_revenuesubhead")
def revenue_sub_head_form(request, pk=None):
    instance = get_object_or_404(RevenueSubHead, pk=pk) if pk else None
    initial = {}
    if not pk:
        initial["head"] = request.GET.get("head")
    form = RevenueSubHeadForm(request.POST or None, instance=instance, initial=initial)
    if request.method == "POST" and form.is_valid():
        form.save()
        messages.success(request, _("Revenue sub-head saved."))
        return _close_modal_reload()
    return render(
        request,
        "revenue/partials/form_modal.html",
        {"form": form, "title": _("Revenue Sub-Head"), "is_create": instance is None},
    )


@login_required
@permission_required("revenue.delete_revenuesubhead")
@require_http_methods(["POST", "DELETE"])
def revenue_sub_head_delete(request, pk):
    obj = get_object_or_404(RevenueSubHead, pk=pk)
    obj.is_active = False
    obj.save(update_fields=["is_active"])
    messages.success(request, _("Revenue sub-head deactivated."))
    return _hx_delete_response()


# ---------------------------------------------------------------------------
# Revenue Item CRUD
# ---------------------------------------------------------------------------


@login_required
@permission_required("revenue.view_revenueitem")
def revenue_item_list(request):
    sub_id = request.GET.get("sub_head")
    qs = RevenueItem.objects.filter(is_active=True).select_related("sub_head__head").order_by(
        "sub_head__head__name", "sub_head__name", "name"
    )
    if sub_id:
        qs = qs.filter(sub_head_id=sub_id)
    return render(request, "revenue/item_list.html", {"items": qs})


@login_required
@permission_required("revenue.add_revenueitem")
def revenue_item_form(request, pk=None):
    instance = get_object_or_404(RevenueItem, pk=pk) if pk else None
    form = RevenueItemForm(request.POST or None, instance=instance)
    if request.method == "POST" and form.is_valid():
        form.save()
        messages.success(request, _("Revenue item saved."))
        return _close_modal_reload()
    return render(
        request,
        "revenue/partials/form_modal.html",
        {"form": form, "title": _("Revenue Item"), "is_create": instance is None},
    )


@login_required
@permission_required("revenue.delete_revenueitem")
@require_http_methods(["POST", "DELETE"])
def revenue_item_delete(request, pk):
    obj = get_object_or_404(RevenueItem, pk=pk)
    obj.is_active = False
    obj.save(update_fields=["is_active"])
    messages.success(request, _("Revenue item deactivated."))
    return _hx_delete_response()


# ---------------------------------------------------------------------------
# Revenue Records
# ---------------------------------------------------------------------------


@login_required
@permission_required("revenue.view_revenuerecord")
def revenue_record_list(request):
    qs = RevenueRecord.objects.select_related(
        "item__sub_head__head", "department", "recorded_by"
    ).order_by("-transaction_date", "-created_at")
    item_id = request.GET.get("item")
    if item_id:
        qs = qs.filter(item_id=item_id)
    return render(request, "revenue/record_list.html", {"records": qs})


@login_required
@permission_required("revenue.add_revenuerecord")
def revenue_record_form(request, pk=None):
    instance = get_object_or_404(RevenueRecord, pk=pk) if pk else None
    form = RevenueRecordForm(request.POST or None, instance=instance, request_user=request.user)
    if request.method == "POST" and form.is_valid():
        record = form.save(commit=False)
        record.recorded_by = request.user
        record.save()
        messages.success(request, _("Revenue record %(ref)s saved.") % {"ref": record.reference_number})
        return _close_modal_reload()
    return render(
        request,
        "revenue/partials/form_modal.html",
        {"form": form, "title": _("Revenue Record"), "is_create": instance is None},
    )


@login_required
@permission_required("revenue.delete_revenuerecord")
@require_http_methods(["POST", "DELETE"])
def revenue_record_delete(request, pk):
    obj = get_object_or_404(RevenueRecord, pk=pk)
    ref = obj.reference_number
    obj.delete()
    messages.success(request, _("Revenue record %(ref)s deleted.") % {"ref": ref})
    return _hx_delete_response()


# ---------------------------------------------------------------------------
# Report: date-range + department filter + Excel export
# ---------------------------------------------------------------------------


@login_required
@permission_required("revenue.view_revenuerecord")
def revenue_report(request):
    form = RevenueReportFilterForm(request.GET or None)
    qs = RevenueRecord.objects.select_related(
        "item__sub_head__head", "department", "recorded_by"
    ).order_by("-transaction_date")

    if form.is_valid():
        d = form.cleaned_data
        if d.get("date_from"):
            qs = qs.filter(transaction_date__gte=d["date_from"])
        if d.get("date_to"):
            qs = qs.filter(transaction_date__lte=d["date_to"])
        if d.get("department"):
            qs = qs.filter(department=d["department"])
        if d.get("revenue_head"):
            qs = qs.filter(item__sub_head__head=d["revenue_head"])

    total = qs.aggregate(t=Sum("amount"))["t"] or 0

    # Excel export
    if request.GET.get("export") == "excel":
        return _export_revenue_excel(qs)

    context = {
        "form": form,
        "records": qs,
        "total": total,
        "count": qs.count(),
    }
    return render(request, "revenue/report.html", context)


def _export_revenue_excel(qs):
    import openpyxl
    from openpyxl.styles import Font, PatternFill

    wb = openpyxl.Workbook()
    ws = wb.active
    ws.title = "Revenue Report"

    headers = [
        "Reference #", "Transaction Date", "Revenue Code", "Revenue Head",
        "Sub-Head", "Item", "Department", "Amount (₦)", "Description", "Recorded By",
    ]
    header_font = Font(bold=True, color="FFFFFF")
    header_fill = PatternFill("solid", fgColor="2C7BE5")

    for col, h in enumerate(headers, 1):
        cell = ws.cell(row=1, column=col, value=h)
        cell.font = header_font
        cell.fill = header_fill

    for row_idx, rec in enumerate(qs, 2):
        ws.append([
            rec.reference_number,
            rec.transaction_date.strftime("%Y-%m-%d"),
            rec.item.code,
            rec.item.sub_head.head.name,
            rec.item.sub_head.name,
            rec.item.name,
            str(rec.department) if rec.department else "",
            float(rec.amount),
            rec.description,
            rec.recorded_by.get_full_name() if rec.recorded_by else "",
        ])

    # Auto-width
    for col in ws.columns:
        max_len = max((len(str(cell.value or "")) for cell in col), default=10)
        ws.column_dimensions[col[0].column_letter].width = min(max_len + 4, 40)

    buf = io.BytesIO()
    wb.save(buf)
    buf.seek(0)

    response = HttpResponse(
        buf.read(),
        content_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
    )
    response["Content-Disposition"] = 'attachment; filename="revenue_report.xlsx"'
    return response
