from __future__ import annotations

from django.shortcuts import render, redirect, get_object_or_404
from django.contrib import messages
from django.urls import reverse
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger

from orgs.models import Organization, UserProfile
from recycle_core.models import ProvidedService
from recycle_core.models import Material, ScrapListing, PickupOrder
from cms.models import Post, PostCategory

from .forms import (
    PickupRequestForm,
    ContactForm,
    RegistrationForm,
    PublicUserForm,
    PublicUserPhotoForm,
    PublicUserProfileExtraForm,
)
from .models import Lead
from recycle_core.controllers.pickup_request import (
    PickupRequestController,
    PickupRequestData,
)

from django.contrib.auth.views import LoginView
from django.urls import reverse


def home(request):
    org = getattr(request, "org", None)
    posts_qs = Post.objects.all()
    if org is not None:
        posts_qs = posts_qs.filter(organization=org)
    posts = posts_qs.order_by("-published_at")[:3]

    listings_qs = ScrapListing.objects.filter(is_public=True)
    if org is not None:
        listings_qs = listings_qs.filter(organization=org)
    listings = listings_qs.order_by("-created_at")[:6]

    materials_qs = Material.objects.all().order_by("name")
    if org is not None:
        materials_qs = materials_qs.filter(organization=org)
    materials = materials_qs[:12]

    services_qs = ProvidedService.objects.none()
    if org is not None:
        services_qs = ProvidedService.objects.filter(organization=org, is_enabled=True).order_by("display_order", "id")
    services = list(services_qs)

    pickup_form = PickupRequestForm()
    contact_form = ContactForm()
    register_form = RegistrationForm()

    return render(
        request,
        "public_frontend/home.html",
        {
            "posts": posts,
            "listings": listings,
            "materials": materials,
            "services": services,
            "pickup_form": pickup_form,
            "contact_form": contact_form,
            "org": org,
            "register_form": register_form,
        },
    )


def materials_list(request):
    org = getattr(request, "org", None)
    qs = Material.objects.all().order_by("name")
    if org is not None:
        qs = qs.filter(organization=org)
    return render(request, "public_frontend/materials_list.html", {"materials": qs, "org": org})


def listings_list(request):
    org = getattr(request, "org", None)
    qs = ScrapListing.objects.filter(is_public=True, status=ScrapListing.STATUS_OPEN).order_by("-created_at")
    if org is not None:
        qs = qs.filter(organization=org)
    paginator = Paginator(qs, 12)
    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)
    return render(request, "public_frontend/listings_list.html", {"page_obj": page_obj, "listings": page_obj.object_list, "org": org})


def listing_detail(request, pk: int):
    org = getattr(request, "org", None)
    base_qs = ScrapListing.objects.filter(is_public=True)
    if org is not None:
        base_qs = base_qs.filter(organization=org)
    listing = get_object_or_404(base_qs, pk=pk)
    return render(request, "public_frontend/listing_detail.html", {"listing": listing, "org": org})


def service_detail(request, pk: int):
    org = getattr(request, "org", None)
    base_qs = ProvidedService.objects.filter(is_enabled=True)
    if org is not None:
        base_qs = base_qs.filter(organization=org)
    service = get_object_or_404(base_qs, pk=pk)
    return render(request, "public_frontend/service_detail.html", {"service": service, "org": org})


def pickup_request(request):
    org = getattr(request, "org", None)
    # Prefill form for authenticated users
    initial = {}
    if request.user.is_authenticated:
        u = request.user
        full_name = (getattr(u, "get_full_name", lambda: "")() or "").strip()
        initial["name"] = full_name or u.username
        if getattr(u, "email", ""):
            initial["email"] = u.email
    form = PickupRequestForm(request.POST or None, request.FILES or None, initial=initial)
    if request.method == "POST":
        if not org:
            messages.error(request, "Organization context missing.")
            return redirect("public_frontend:pickup_request")
        if form.is_valid():
            ctrl = PickupRequestController()
            data = PickupRequestData(
                organization=org,
                name=form.cleaned_data.get("name"),
                email=form.cleaned_data.get("email", ""),
                phone=form.cleaned_data.get("phone", ""),
                address=form.cleaned_data.get("address", ""),
                materials=form.cleaned_data.get("materials", ""),
                preferred_at=form.cleaned_data.get("preferred_at"),
                files=request.FILES.getlist("photos") if hasattr(request, "FILES") and "photos" in request.FILES else [],
                created_by=request.user if request.user.is_authenticated else None,
            )
            result = ctrl.submit(data)
            if result.ok:
                messages.success(request, "Thanks! Your pickup request was submitted.")
                return redirect("public_frontend:home")
            else:
                messages.error(request, result.error or "Unable to submit your request.")
        else:
            messages.error(request, "Please correct the errors below.")
    return render(request, "public_frontend/pickup_request.html", {"form": form, "org": org})


def contact(request):
    org = getattr(request, "org", None)
    form = ContactForm(request.POST or None)
    if request.method == "POST":
        if not org:
            messages.error(request, "Organization context missing.")
            return redirect("public_frontend:contact")
        if form.is_valid():
            Lead.objects.create(
                organization=org,
                name=form.cleaned_data["name"],
                email=form.cleaned_data["email"],
                phone=form.cleaned_data.get("phone", ""),
                subject=form.cleaned_data.get("subject", ""),
                message=form.cleaned_data.get("message", ""),
                source="contact",
                created_by=request.user if request.user.is_authenticated else None,
            )
            messages.success(request, "Thanks! We will get back to you shortly.")
            return redirect("public_frontend:home")
        messages.error(request, "Please correct the errors below.")
    return render(request, "public_frontend/contact.html", {"form": form, "org": org})


def register(request):
    from django.contrib.auth import get_user_model
    from django.contrib.auth.models import Group
    from orgs.models import UserProfile

    org = getattr(request, "org", None)
    if not org:
        messages.error(request, "Organization context missing.")
        return redirect("public_frontend:home")

    form = RegistrationForm(request.POST or None)
    if request.method == "POST":
        if form.is_valid():
            User = get_user_model()
            user = User(username=form.cleaned_data["username"], email=form.cleaned_data["email"], is_active=False)
            user.set_password(form.cleaned_data["password1"])
            user.save()
            role = form.cleaned_data["role"]
            # Create org profile
            UserProfile.objects.create(user=user, organization=org, role=role)
            # Add to group matching the role if exists
            try:
                g = Group.objects.filter(name=role).first()
                if g:
                    user.groups.add(g)
            except Exception:
                pass
            messages.success(request, "Account created. Please wait for admin approval.")
            return redirect("public_frontend:home")
        else:
            messages.error(request, "Please correct the errors below.")

    return render(request, "public_frontend/register.html", {"form": form, "org": org})


def blog_list(request):
    org = getattr(request, "org", None)
    qs = Post.objects.all().order_by("-published_at", "-created_at")
    if org is not None:
        qs = qs.filter(organization=org)
    paginator = Paginator(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)
    return render(request, "public_frontend/blog_list.html", {"page_obj": page_obj, "posts": page_obj.object_list, "org": org})


def blog_detail(request, slug: str):
    org = getattr(request, "org", None)
    base_qs = Post.objects.all()
    if org is not None:
        base_qs = base_qs.filter(organization=org)
    post = get_object_or_404(base_qs, slug=slug)
    # Ensure markdown is rendered; fallback to raw content if needed
    html = getattr(post, "content_html", None) or getattr(post, "content", "")
    return render(request, "public_frontend/blog_detail.html", {"post": post, "html": html, "org": org})


class PublicLoginView(LoginView):
    template_name = "public_frontend/login.html"
    redirect_authenticated_user = True

    def get_success_url(self):
        return reverse("public_frontend:home")


from django.contrib.auth.decorators import login_required
from django.contrib.auth import get_user_model
from django.utils import timezone
from recycle_core.models import CarbonEvent, CarbonBalance


@login_required
def my_profile(request):
    user = request.user
    profile = getattr(user, "recycle_profile", None)
    role_code = getattr(profile, "role", None)
    role_label = dict(UserProfile.ROLE_CHOICES).get(role_code, "-") if role_code else "-"
    if request.method == "POST":
        form_user = PublicUserForm(request.POST, instance=user)
        form_photo = PublicUserPhotoForm(request.POST, request.FILES, instance=profile) if profile else None
        form_extras = PublicUserProfileExtraForm(request.POST, instance=profile) if profile else None
        ok_user = form_user.is_valid()
        ok_photo = True if form_photo is None else form_photo.is_valid()
        ok_extras = True if form_extras is None else form_extras.is_valid()
        if ok_user and ok_photo and ok_extras:
            form_user.save()
            if form_photo is not None:
                form_photo.save()
            if form_extras is not None:
                form_extras.save()
            messages.success(request, "Profile updated.")
            return redirect(reverse("public_frontend:my_profile"))
        messages.error(request, "Please correct the errors below.")
    else:
        form_user = PublicUserForm(instance=user)
        form_photo = PublicUserPhotoForm(instance=profile) if profile else None
        form_extras = PublicUserProfileExtraForm(instance=profile) if profile else None

    # Request history (pickup requests submitted via public form, matched by email)
    history = []
    try:
        email = (user.email or "").strip()
        if email:
            qs = Lead.objects.filter(email__iexact=email, source="pickup_request").order_by("-created_at")
            org = getattr(request, "org", None)
            if org is not None:
                qs = qs.filter(organization=org)
            history = list(qs[:20])
    except Exception:
        history = []

    # Carbon summary for user's organization
    org = getattr(request, "org", None) or getattr(profile, "organization", None)
    carbon = None
    if org is not None:
        today = timezone.now().date()
        bal = CarbonBalance.objects.filter(organization=org, year=today.year, month=today.month).first()
        pending = CarbonEvent.objects.filter(organization=org, status=CarbonEvent.STATUS_PENDING).count()
        carbon = {
            "pending_events": pending,
            "approved_mtd": bal.approved_kgco2e if bal else 0,
        }

    return render(
        request,
        "public_frontend/my_profile.html",
        {
            "form_user": form_user,
            "form_photo": form_photo,
            "form_extras": form_extras,
            "has_profile": bool(profile),
            "username_value": user.username,
            "role_label": role_label,
            "request_history": history,
            "carbon": carbon,
        },
    )
