# (c) cavaliba.com - sirene - sms_view.py

from django.contrib import messages
from django.db.models import Count
from django.db.models.functions import ExtractDay, ExtractMonth, ExtractYear
from django.shortcuts import redirect, render
from django.utils.translation import gettext as _

from app_data.aaa import start_view
from app_home.configuration import get_configuration
from app_home.log import DEBUG, INFO, WARNING, log

# Celery tasks
from app_sirene.notify import task_send_sms

from .forms import SMSForm
from .models import SMSJournal
from .sms import get_sms_quota, sms_check_valid_number

# -------------------------------------------
#
# -------------------------------------------


def sms_send(request):

    context = start_view(
        request,
        app="sirene",
        view="sms_send",
        noauth="app_sirene:index",
        perm="p_sirene_sms_send",
        noauthz="app_sirene:private",
    )
    if context["redirect"]:
        return redirect(context["redirect"])
    aaa = context["aaa"]

    if get_sms_quota(aaa) < 1:
        messages.add_message(request, messages.ERROR, _("Insufficient SMS Quota"))
        log(
            WARNING,
            aaa=aaa,
            app="sirene",
            view="sms",
            action="quota",
            status="KO",
            data="insufficient SMS quota",
        )
        return redirect("app_sirene:private")

    if request.method == "POST":
        form = SMSForm(request.POST)
        if form.is_valid():
            cd = form.cleaned_data
            mobile = cd["mobile"]
            message = cd["message"]

            if not sms_check_valid_number(mobile):
                messages.add_message(request, messages.ERROR, _("Invalid SMS number"))
                log(
                    WARNING,
                    aaa=aaa,
                    app="sirene",
                    view="sms",
                    action="send",
                    status="KO",
                    data="Invalid number",
                )
            else:
                task_send_sms.delay([mobile], message, aaa=aaa)
                messages.add_message(request, messages.SUCCESS, _("SMS sent"))
                log(
                    INFO,
                    aaa=aaa,
                    app="sirene",
                    view="sms",
                    action="send",
                    status="OK",
                    data="Queued",
                )
                return redirect("app_sirene:private")
    else:
        form = SMSForm()
        log(DEBUG, aaa=aaa, app="sirene", view="sms", action="form", status="OK", data="Get form")

    context["sms_warning"] = get_configuration("sirene", "SMS_WARNING")
    context["form"] = form
    return render(request, "app_sirene/sms_send.html", context)


# -----------------------------------------
#  SMS journal
# -----------------------------------------
def sms_journal(request):

    context = start_view(
        request,
        app="sirene",
        view="sms_journal",
        noauth="app_sirene:index",
        perm="p_sirene_sms_journal",
        noauthz="app_sirene:private",
    )
    if context["redirect"]:
        return redirect(context["redirect"])
    aaa = context["aaa"]

    bigset_size = int(get_configuration("data", "DATA_BIGSET_SIZE"))
    count = SMSJournal.objects.count()
    context["count"] = count
    context["bigset"] = True

    # Search query (POST)
    import re

    query = ""
    if request.method == "POST":
        if request.POST.get("query"):
            query = request.POST.get("query")
            m = re.compile(r"[a-zA-Z0-9()_/.-]*$")
            if not m.match(query):
                query = ""
    context["query"] = query

    # Pagination (GET)
    try:
        size = int(request.GET.get("size", bigset_size))
        page = int(request.GET.get("page", 1))
    except Exception:
        return redirect("app_sirene:sms_journal")

    if page < 1 or size > 10000 or size < 1:
        return redirect("app_sirene:sms_journal")

    offset = (page - 1) * size
    limit = offset + size

    qs = SMSJournal.objects.order_by("-created_at")
    if query:
        qs = qs.filter(created_by__icontains=query)

    journal = qs[offset:limit]

    log(
        DEBUG,
        aaa=aaa,
        app="sirene",
        view="sms",
        action="journal",
        status="OK",
        data=f"{count} entries",
    )

    # Pagination context
    context["size"] = size
    context["page"] = page
    page_last = int(count / size) + 1
    context["page_prev"] = max(page - 1, 1)
    context["page_first"] = page == 1
    context["page_current"] = 1 < page < page_last
    context["page_last"] = page_last
    context["page_last_active"] = page >= page_last
    context["page_next"] = min(page + 1, page_last)

    context["journal"] = journal
    return render(request, "app_sirene/sms_journal.html", context)


# -----------------------------------------
#  SMS stats
# -----------------------------------------
def sms_stat(request):

    context = start_view(
        request,
        app="sirene",
        view="sms_stat",
        noauth="app_sirene:index",
        perm="p_sirene_sms_stat",
        noauthz="app_sirene:private",
    )
    if context["redirect"]:
        return redirect(context["redirect"])
    aaa = context["aaa"]

    stat_year = (
        SMSJournal.objects.annotate(year=ExtractYear("created_at"))
        .values("year")
        .annotate(count=Count("id"))
        .annotate(numsender=Count("created_by", distinct=True))
        .annotate(numdest=Count("mobile", distinct=True))
    )

    stat_month = (
        SMSJournal.objects.annotate(year=ExtractYear("created_at"))
        .annotate(month=ExtractMonth("created_at"))
        .values("year", "month")
        .annotate(count=Count("id"))
        .annotate(numsender=Count("created_by", distinct=True))
        .annotate(numdest=Count("mobile", distinct=True))
    )

    stat_day = (
        SMSJournal.objects.annotate(year=ExtractYear("created_at"))
        .annotate(month=ExtractMonth("created_at"))
        .annotate(day=ExtractDay("created_at"))
        .values("year", "month", "day")
        .annotate(count=Count("id"))
        .annotate(numsender=Count("created_by", distinct=True))
        .annotate(numdest=Count("mobile", distinct=True))
    )

    log(DEBUG, aaa=aaa, app="sirene", view="sms", action="stat", status="OK", data="Get form")

    context["stat_year"] = stat_year
    context["stat_month"] = stat_month
    context["stat_day"] = stat_day
    return render(request, "app_sirene/sms_stat.html", context)
