from __future__ import annotations

from django.shortcuts import render, get_object_or_404, redirect
from django.contrib.admin.views.decorators import staff_member_required
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
import django_filters as filters
from django.contrib import messages
from django.urls import reverse
from django.contrib.auth import get_user_model
from datetime import datetime
from django.contrib.contenttypes.models import ContentType

from admin_frontend.templatetags.public_urls import public_route
from admin_frontend.nav import _nav_items
from .models import Lead


@staff_member_required
@public_route(label="Leads", order=22, icon="envelope")
def leads_list(request):
    """List Leads captured from the public site with filtering and pagination."""

    class LeadFilter(filters.FilterSet):
        name = filters.CharFilter(field_name="name", lookup_expr="icontains", label="Name")
        email = filters.CharFilter(field_name="email", lookup_expr="icontains", label="Email")
        phone = filters.CharFilter(field_name="phone", lookup_expr="icontains", label="Phone")
        org = filters.CharFilter(field_name="organization__code", lookup_expr="icontains", label="Org Code")
        source = filters.ChoiceFilter(field_name="source", label="Source", choices=Lead.LeadSource.choices)
        created_at = filters.DateTimeFromToRangeFilter(
            field_name="created_at",
            label="Created between",
            widget=filters.widgets.RangeWidget(
                attrs={
                    "type": "datetime-local",
                    "style": "color-scheme: light;",
                    "class": "border border-gray-300 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500",
                }
            ),
        )

        class Meta:
            model = Lead
            fields = ["name", "email", "phone", "org", "source", "created_at"]

        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            try:
                from crispy_forms.helper import FormHelper
                from crispy_forms.layout import Layout, Field
                helper = FormHelper()
                helper.form_tag = False
                helper.layout = Layout(
                    Field("name", template="crispy/field_nowrap.html"),
                    Field("email", template="crispy/field_nowrap.html"),
                    Field("phone", template="crispy/field_nowrap.html"),
                    Field("org", template="crispy/field_nowrap.html"),
                    Field("source", template="crispy/field_nowrap.html"),
                    Field("created_at", template="crispy/field_nowrap.html"),
                )
                self.form.helper = helper
            except Exception:
                pass

    qs = Lead.objects.select_related("organization").order_by("-created_at")
    lead_filter = LeadFilter(request.GET, queryset=qs)

    paginator = Paginator(lead_filter.qs, 10)
    page = request.GET.get("page")
    try:
        page_obj = paginator.page(page)
    except PageNotAnInteger:
        page_obj = paginator.page(1)
    except EmptyPage:
        page_obj = paginator.page(paginator.num_pages)

    context = {
        "nav": _nav_items(),
        "leads": page_obj.object_list,
        "page_obj": page_obj,
        "filter": lead_filter,
    }
    return render(request, "admin_frontend/leads_list.html", context)


@staff_member_required
def lead_detail(request, pk: int):
    lead = get_object_or_404(Lead.objects.select_related("organization"), pk=pk)

    def _parse_pickup_details(message: str):
        data = {"address": "", "preferred": "", "materials": ""}
        try:
            for line in (message or "").splitlines():
                if line.lower().startswith("address:"):
                    data["address"] = line.split(":", 1)[1].strip()
                elif line.lower().startswith("preferred:"):
                    data["preferred"] = line.split(":", 1)[1].strip()
                elif line.lower().startswith("materials:"):
                    data["materials"] = line.split(":", 1)[1].strip()
        except Exception:
            pass
        return data

    suggested = _parse_pickup_details(getattr(lead, "message", "") or "")
    # Fetch any uploaded Documents attached to this Lead
    try:
        from recycle_core.models import Document
        ct = ContentType.objects.get_for_model(Lead)
        documents = Document.objects.filter(content_type=ct, object_id=lead.id).order_by("-created_at")
    except Exception:
        documents = []

    User = get_user_model()
    drivers = User.objects.all().order_by("username")
    context = {"nav": _nav_items(), "lead": lead, "drivers": drivers, "suggested": suggested, "documents": documents}
    return render(request, "admin_frontend/lead_detail.html", context)


@staff_member_required
def lead_convert_to_pickup(request, pk: int):
    lead = get_object_or_404(Lead.objects.select_related("organization"), pk=pk)
    if request.method != "POST":
        return redirect("public_frontend_admin:lead_detail", pk=pk)

    from recycle_core.models import Customer, CustomerSite, PickupOrder

    address = (request.POST.get("address") or "").strip()
    scheduled_at_raw = (request.POST.get("scheduled_at") or "").strip()
    driver_id = (request.POST.get("driver") or "").strip()

    if not address:
        messages.error(request, "Address is required to create a pickup.")
        return redirect("public_frontend_admin:lead_detail", pk=pk)

    scheduled_at = None
    if scheduled_at_raw:
        try:
            scheduled_at = datetime.fromisoformat(scheduled_at_raw)
        except Exception:
            messages.error(request, "Invalid date/time format for schedule.")
            return redirect("public_frontend_admin:lead_detail", pk=pk)

    # Find or create customer for this lead under the same organization
    org = lead.organization
    customer = None
    if lead.email:
        customer = Customer.objects.filter(organization=org, email__iexact=lead.email).first()
    if customer is None:
        customer = Customer.objects.filter(organization=org, name__iexact=lead.name).first()
    if customer is None:
        customer = Customer.objects.create(
            organization=org,
            name=lead.name,
            email=lead.email,
            phone=lead.phone,
            billing_address="",
        )

    # Create a site for the pickup
    site = CustomerSite.objects.create(
        customer=customer,
        name="",
        address=address,
        contact_name=lead.name,
        contact_phone=lead.phone,
        contact_email=lead.email,
    )

    pickup = PickupOrder.objects.create(
        organization=org,
        customer=customer,
        site=site,
        status=PickupOrder.STATUS_REQUESTED,
        scheduled_at=scheduled_at,
    )

    # Optionally assign a driver and mark scheduled
    if driver_id:
        try:
            User = get_user_model()
            driver = User.objects.get(pk=int(driver_id))
            pickup.assigned_driver = driver
            if scheduled_at:
                pickup.status = PickupOrder.STATUS_SCHEDULED
            pickup.save(update_fields=["assigned_driver", "status"])
        except Exception:
            pass

    messages.success(request, f"Created pickup #{pickup.id} for customer '{customer.name}'.")
    return redirect("recycle_core:pickups_list")
