"""
Request and allocation page
"""

from typing import Any

from django.contrib import messages
from django.http import HttpResponse
from django.shortcuts import render
from django.urls import reverse
from django.utils.decorators import method_decorator
from django.utils.translation import gettext_lazy as _

from asset.filters import AssetAllocationFilter, AssetRequestFilter, CustomAssetFilter
from asset.forms import AssetAllocationForm, AssetRequestForm
from asset.models import Asset, AssetAssignment, AssetRequest, ReturnImages
from base.methods import filtersubordinates
from employee.models import Employee
from horilla.horilla_middlewares import _thread_locals
from horilla_views.cbv_methods import login_required, permission_required
from horilla_views.generic.cbv.views import (
    HorillaDetailedView,
    HorillaFormView,
    HorillaListView,
    HorillaNavView,
    HorillaTabView,
    TemplateView,
)
from notifications.signals import notify


@method_decorator(login_required, name="dispatch")
class RequestAndAllocationView(TemplateView):
    """
    for request and allocation page
    """

    template_name = "cbv/request_and_allocation/request_and_allocation.html"


@method_decorator(login_required, name="dispatch")
class AllocationList(HorillaListView):
    """
    For both  asset allocation and asset tab
    """

    # view_id = "view-container"

    bulk_update_fields = ["asset_id__expiry_date"]

    model = AssetAssignment
    filter_class = AssetAllocationFilter

    def __init__(self, **kwargs: Any) -> None:
        super().__init__(**kwargs)
        self.search_url = reverse("list-asset")

    columns = [
        (_("Asset"), "asset_id", "get_avatar"),
        (_("Category"), "asset_id__asset_category_id"),
        (_("Expiry Date"), "asset_id__expiry_date"),
    ]

    header_attrs = {
        "action": """
                   style = "width:180px !important"
                   """,
        "asset_id__asset_name": """
                   style = "width:250px !important"
                   """,
        "asset_id__asset_category_id": """
                   style = "width:250px !important"
                   """,
        "asset_id__expiry_date": """
                   style = "width:250px !important"
                   """,
    }

    sortby_mapping = [
        ("Category", "asset_id__asset_category_id__asset_category_name"),
        ("Expiry Date", "asset_id__expiry_date"),
    ]

    action_method = "asset_action"

    row_attrs = """
                hx-get='{detail_view_asset}?instance_ids={ordered_ids}'
                hx-target="#genericModalBody"
                data-target="#genericModal"
                data-toggle="oh-modal-toggle"
                """


@method_decorator(login_required, name="dispatch")
class AssetList(AllocationList):
    """
    Asset tab
    """

    # view_id = "assetlist"
    def get_queryset(self):
        """
        Returns a queryset of AssetRequest objects filtered by
        the current user's employee ID.
        """
        queryset = super().get_queryset()
        employee = self.request.user.employee_get
        queryset = queryset.filter(assigned_to_employee_id=employee).exclude(
            return_status__isnull=False
        )
        return queryset

    selected_instances_key_id = "assetlistInstances"


@method_decorator(login_required, name="dispatch")
class AssetAllocationList(AllocationList):
    """
    Asset allocation tab
    """

    def __init__(self, **kwargs: Any) -> None:
        super().__init__(**kwargs)
        self.search_url = reverse("list-asset-allocation")

    columns = [
        (
            _("Allocated User"),
            "assigned_to_employee_id",
            "assigned_to_employee_id__get_avatar",
        ),
        (_("Asset"), "asset_id"),
        (_("Assigned Date"), "assigned_date"),
        (_("Return Date"), "return_status_col"),
    ]

    sortby_mapping = [
        ("Allocated User", "assigned_to_employee_id__get_full_name"),
        ("Asset", "asset_id__asset_name"),
        ("Assigned Date", "assigned_date"),
        ("Return Date", "return_status_col"),
    ]

    action_method = "allocation_action"

    row_attrs = """
                hx-get='{detail_view_asset_allocation}?instance_ids={ordered_ids}'
                hx-target="#genericModalBody"
                data-target="#genericModal"
                data-toggle="oh-modal-toggle"
                """


@method_decorator(login_required, name="dispatch")
class AssetRequestList(HorillaListView):
    """
    Asset Request Tab
    """

    def __init__(self, **kwargs: Any) -> None:
        super().__init__(**kwargs)

        self.search_url = reverse("list-asset-request")
        # self.view_id = "view-container"
        if self.request.user.has_perm("asset.add_assetassignment"):
            self.action_method = "action_col"

    model = AssetRequest
    filter_class = AssetRequestFilter

    def get_queryset(self):
        """
        Returns a filtered queryset of AssetRequest objects
        based on user permissions and employee ID.
        """

        queryset = super().get_queryset()
        queryset = filtersubordinates(
            request=self.request,
            perm="asset.view_assetrequest",
            queryset=queryset,
            field="requested_employee_id",
        ) | queryset.filter(requested_employee_id=self.request.user.employee_get)
        return queryset

    columns = [
        (
            _("Request User"),
            "requested_employee_id",
            "requested_employee_id__get_avatar",
        ),
        (_("Asset Category"), "asset_category_id"),
        (_("Requested Date"), "asset_request_date"),
        (_("Status"), "status_col"),
    ]

    header_attrs = {
        "action": """
                   style = "width:180px !important"
                   """
    }

    sortby_mapping = [
        ("Request User", "requested_employee_id__get_full_name"),
        ("Asset Category", "asset_category_id__asset_category_name"),
        ("Requested Date", "asset_request_date"),
        ("Status", "status_col"),
    ]

    row_attrs = """
                hx-get='{detail_view_asset_request}?instance_ids={ordered_ids}'
                hx-target="#genericModalBody"
                data-target="#genericModal"
                data-toggle="oh-modal-toggle"
                """


@method_decorator(login_required, name="dispatch")
class RequestAndAllocationTab(HorillaTabView):
    """
    Tab View
    """

    def __init__(self, **kwargs: Any) -> None:
        super().__init__(**kwargs)
        self.tabs = [
            {
                "title": _("Asset"),
                "url": f"{reverse('list-asset')}",
            },
            {
                "title": _("Asset Request"),
                "url": f"{reverse('list-asset-request')}",
                "actions": [
                    {
                        "action": "Create Request",
                        "attrs": f"""
                                data-toggle="oh-modal-toggle"
                                data-target="#genericModal"
                                hx-get="{reverse('asset-request-creation')}"
                                hx-target="#genericModalBody"
                                style="cursor: pointer;"
                                """,
                    }
                ],
            },
        ]
        if self.request.user.has_perm("asset.view_assetassignment"):
            self.tabs.append(
                {
                    "title": _("Asset Allocation"),
                    "url": f"{reverse('list-asset-allocation')}",
                    "actions": [
                        {
                            "action": "Create Allocation",
                            "attrs": f"""
                                data-toggle="oh-modal-toggle"
                                data-target="#genericModal"
                                hx-get="{reverse('asset-allocate-creation')}"
                                hx-target="#genericModalBody"
                                style="cursor: pointer;"
                                """,
                        }
                    ],
                },
            )


@method_decorator(login_required, name="dispatch")
class RequestAndAllocationNav(HorillaNavView):
    """
    Nav bar
    """

    def __init__(self, **kwargs: Any) -> None:
        super().__init__(**kwargs)
        self.search_url = reverse("tab-asset-request-allocation")

    nav_title = _("Asset")
    filter_instance = AssetAllocationFilter()
    filter_form_context_name = "asset_allocation_filter_form"
    filter_body_template = "cbv/request_and_allocation/filter.html"
    search_swap_target = "#listContainer"

    def get_context_data(self, **kwargs):
        """
        context data
        """
        context = super().get_context_data(**kwargs)
        assets_filter_form = CustomAssetFilter()
        asset_request_filter_form = AssetRequestFilter()
        context["assets_filter_form"] = assets_filter_form.form
        context["asset_request_filter_form"] = asset_request_filter_form.form
        return context

    group_by_fields = [
        ("requested_employee_id", _("Asset Request / Employee")),
        ("asset_category_id", _("Asset Request / Asset Category")),
        ("asset_request_date", _("Asset Request / Request Date")),
        ("asset_request_status", _("Asset Request / Status")),
        ("assigned_to_employee_id", _("Asset Allocation / Employee")),
        ("assigned_date", _("Asset Allocation / Assigned Date")),
        ("return_date", _("Asset Allocation / Return Date")),
    ]


@method_decorator(login_required, name="dispatch")
class AssetDetailView(HorillaDetailedView):
    """
    detail view of asset tab
    """

    def __init__(self, **kwargs: Any) -> None:
        super().__init__(**kwargs)
        self.body = [
            (_("Description"), "asset_id__asset_description"),
            (_("Tracking Id"), "asset_id__asset_tracking_id"),
            (_("Assigned Date"), "assigned_date"),
            (_("Status"), "asset_detail_status"),
            (_("Assigned by"), "assigned_by_employee_id"),
            (_("Batch No"), "asset_id__asset_lot_number_id"),
            # ("Category","asset_id__asset_category_id")
        ]

    action_method = "asset_detail_action"

    model = AssetAssignment
    title = _("Asset Information")
    header = {
        "title": "asset_id__asset_name",
        "subtitle": "asset_id__asset_category_id",
        "avatar": "get_avatar",
    }


@method_decorator(login_required, name="dispatch")
class AssetRequestDetailView(HorillaDetailedView):
    """
    detail view of asset request tab
    """

    def __init__(self, **kwargs: Any) -> None:
        super().__init__(**kwargs)
        self.body = [
            (_("Asset Category"), "asset_category_id"),
            (_("Requested Date"), "asset_request_date"),
            (_("Request Description"), "description"),
            (_("Status"), "status_col"),
        ]

    model = AssetRequest
    title = _("Details")
    header = {
        "title": "requested_employee_id",
        "subtitle": "asset_request_detail_subtitle",
        "avatar": "requested_employee_id__get_avatar",
    }
    action_method = "detail_action_col"


@method_decorator(login_required, name="dispatch")
class AssetAllocationDetailView(HorillaDetailedView):
    """
    detail view of asset allocation tab
    """

    def __init__(self, **kwargs: Any) -> None:
        super().__init__(**kwargs)
        self.body = [
            (_("Returned Status"), "return_status"),
            (_("Allocated User"), "assigned_by_employee_id"),
            (_("Allocated Date"), "assigned_date"),
            (_("Return Date"), "return_date"),
            (_("Asset"), "asset_id"),
            (_("Return Description"), "return_condition"),
            (_("Status"), "detail_status"),
        ]

    model = AssetAssignment
    title = _("Details")
    header = {
        "title": "assigned_to_employee_id",
        "subtitle": "asset_allocation_detail_subtitle",
        "avatar": "assigned_to_employee_id__get_avatar",
    }
    action_method = "asset_allocation_detail_action"


@method_decorator(login_required, name="dispatch")
class AssetRequestCreateForm(HorillaFormView):
    """
    Create Asset request
    """

    model = AssetRequest
    form_class = AssetRequestForm
    template_name = "cbv/request_and_allocation/forms/req_form.html"
    new_display_title = _("Asset Request")

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        if self.request.GET.get("pk"):
            pk = self.request.GET.get("pk")
            self.form.fields["requested_employee_id"].queryset = (
                Employee.objects.filter(id=pk)
            )
            self.form.fields["requested_employee_id"].initial = pk
        return context

    def form_valid(self, form: AssetRequestForm) -> HttpResponse:
        """
        Handles validation and saving of an AssetRequestForm.
        """
        if form.is_valid():
            message = _("Asset Request Created Successfully")
            form.save()
            messages.success(self.request, message)
            return self.HttpResponse()
        return super().form_valid(form)


@method_decorator(login_required, name="dispatch")
@method_decorator(permission_required(perm="asset.add_asset"), name="dispatch")
class AssetAllocationFormView(HorillaFormView):
    """
    Create Asset Allocation
    """

    model = AssetAssignment
    form_class = AssetAllocationForm
    template_name = "cbv/request_and_allocation/forms/allo_form.html"
    new_display_title = _("Asset Allocation")

    def form_valid(self, form: AssetAllocationForm) -> HttpResponse:
        """
        form valid function
        """
        if form.is_valid():
            asset = form.instance.asset_id
            asset.asset_status = "In use"
            asset.save()
            message = _("Asset allocated Successfully")
            form.save()
            request = getattr(_thread_locals, "request", None)
            files = request.FILES.getlist("assign_images")
            attachments = []
            if request.FILES:
                for file in files:
                    attachment = ReturnImages()
                    attachment.image = file
                    attachment.save()
                    attachments.append(attachment)
                form.instance.assign_images.add(*attachments)
            messages.success(self.request, message)
            return self.HttpResponse()
        return super().form_valid(form)


class AssetApproveFormView(HorillaFormView):
    """
    Create Asset Allocation
    """

    model = AssetAssignment
    form_class = AssetAllocationForm
    template_name = "cbv/request_and_allocation/forms/asset_approve_form.html"
    new_display_title = _("Asset Allocation")

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        req_id = self.kwargs.get("req_id")
        asset_request = AssetRequest.objects.filter(id=req_id).first()
        asset_category = asset_request.asset_category_id
        assets = asset_category.asset_set.filter(asset_status="Available")
        self.form.fields["asset_id"].queryset = assets
        self.form.fields["assigned_to_employee_id"].initial = (
            asset_request.requested_employee_id
        )
        self.form.fields["assigned_by_employee_id"].initial = (
            self.request.user.employee_get
        )
        return context

    def form_invalid(self, form: Any) -> HttpResponse:
        if not form.is_valid():
            errors = form.errors.as_data()
            return render(
                self.request, self.template_name, {"form": form, "errors": errors}
            )
        return super().form_invalid(form)

    def form_valid(self, form: AssetAllocationForm) -> HttpResponse:
        """
        form valid function
        """
        req_id = self.kwargs.get("req_id")
        asset_request = AssetRequest.objects.filter(id=req_id).first()
        if form.is_valid():
            asset = form.instance.asset_id.id
            asset = Asset.objects.filter(id=asset).first()
            asset.asset_status = "In use"
            asset.save()
            # form = form.save(commit=False)
            # form.assigned_by_employee_id = self.request.user.employee_get
            form.save()
            asset_request.asset_request_status = "Approved"
            asset_request.save()
            request = getattr(_thread_locals, "request", None)
            files = request.FILES.getlist("assign_images")
            attachments = []
            if request.FILES:
                for file in files:
                    attachment = ReturnImages()
                    attachment.image = file
                    attachment.save()
                    attachments.append(attachment)
                form.instance.assign_images.add(*attachments)
            messages.success(self.request, _("Asset request approved successfully!."))
            notify.send(
                self.request.user.employee_get,
                recipient=asset_request.requested_employee_id.employee_user_id,
                verb="Your asset request approved!.",
                verb_ar="تم الموافقة على طلب الأصول الخاص بك!",
                verb_de="Ihr Antragsantrag wurde genehmigt!",
                verb_es="¡Su solicitud de activo ha sido aprobada!",
                verb_fr="Votre demande d'actif a été approuvée !",
                redirect=reverse("asset-request-allocation-view")
                + f"?asset_request_date={asset_request.asset_request_date}\
                &asset_request_status={asset_request.asset_request_status}",
                icon="bag-check",
            )
            return HttpResponse("<script>window.location.reload()</script>")
        return super().form_valid(form)
