import os
from datetime import timedelta
import uuid
import json
from django.conf import settings
from django.core.mail import send_mail
from django.contrib.auth.decorators import login_required, user_passes_test
from django.http import JsonResponse, HttpResponse
from django.shortcuts import render, get_object_or_404, redirect
from django.utils import timezone
from django.views.generic import ListView, DetailView
from django.views.decorators.csrf import csrf_exempt
from django.contrib.admin.views.decorators import staff_member_required


from .models import (
    Service, Testimonial, BlogPost, CareerPosition, Enquiry, CareerApplication,
    CareRequest, CaregiverProfile, CareAssignment,
    SupportTicket, SupportMessage, StaffNotification,
)
from .whatsapp import send_whatsapp_text, route_number
from .forms import (
    EnquiryForm, CareerApplicationForm,
    CareRequestStep1Form, CareRequestStep2Form, CareRequestStep3Form,
    CaregiverAvailabilityForm, AssignmentCreateForm, SupportTicketForm,
)

def home(request):
    services = Service.objects.filter(is_featured=True)[:6]
    testimonials = Testimonial.objects.filter(is_published=True)[:6]
    return render(request, "website/pages/home.html", {
        "services": services,
        "testimonials": testimonials,
        "page_title": "Professional Home Care & Nursing Services You Can Trust",
        "page_description": "Holistic Caregiver Services Ltd provides professional home nursing, elderly care, post-hospital recovery support, and compassionate caregiving.",
    })

def about(request):
    return render(request, "website/pages/about.html", {"page_title": "About Us"})

def services(request):
    all_services = Service.objects.all()
    return render(request, "website/pages/services.html", {"services": all_services, "page_title": "Our Services"})

def care_process(request):
    return render(request, "website/pages/care_process.html", {"page_title": "Our Care Process"})

def why_choose_us(request):
    return render(request, "website/pages/why_choose_us.html", {"page_title": "Why Choose Us"})

def testimonials(request):
    items = Testimonial.objects.filter(is_published=True)
    return render(request, "website/pages/testimonials.html", {"testimonials": items, "page_title": "Testimonials"})

def careers(request):
    positions = CareerPosition.objects.filter(is_open=True)
    form = CareerApplicationForm()

    if request.method == "POST":
        form = CareerApplicationForm(request.POST, request.FILES)
        if form.is_valid():
            app = form.save()
            send_mail(
                subject="New Career Application",
                message=f"New application from {app.full_name} ({app.email}).",
                from_email=settings.DEFAULT_FROM_EMAIL,
                recipient_list=[getattr(settings, "ADMIN_NOTIFY_EMAIL", "admin@example.com")],
                fail_silently=True,
            )
            return redirect("website:careers_success")

    return render(request, "website/pages/careers.html", {
        "positions": positions,
        "form": form,
        "page_title": "Careers",
    })

def careers_success(request):
    return render(request, "website/pages/careers_success.html", {"page_title": "Application Received"})

def contact(request):
    form = EnquiryForm()
    if request.method == "POST":
        form = EnquiryForm(request.POST)
        if form.is_valid():
            enquiry = form.save()
            send_mail(
                subject=f"New Enquiry: {enquiry.get_enquiry_type_display()}",
                message=f"From: {enquiry.full_name}\nPhone: {enquiry.phone}\nEmail: {enquiry.email}\nLocation: {enquiry.location}\nPreferred time: {enquiry.preferred_contact_time}\n\n{enquiry.message}",
                from_email=settings.DEFAULT_FROM_EMAIL,
                recipient_list=[getattr(settings, "ADMIN_NOTIFY_EMAIL", "admin@example.com")],
                fail_silently=True,
            )
            wa_to = route_number(enquiry.enquiry_type)
            send_whatsapp_text(wa_to, f"New Enquiry ({enquiry.get_enquiry_type_display()}):\n{enquiry.full_name} | {enquiry.phone}\nLocation: {enquiry.location}\n\n{enquiry.message[:700]}")
            return redirect("website:contact_success")

    return render(request, "website/pages/contact.html", {
        "form": form,
        "page_title": "Contact Us",
    })

def contact_success(request):
    return render(request, "website/pages/contact_success.html", {"page_title": "Thank You"})

class BlogListView(ListView):
    template_name = "website/pages/blog_list.html"
    context_object_name = "posts"
    paginate_by = 9

    def get_queryset(self):
        return BlogPost.objects.filter(is_published=True)

class BlogDetailView(DetailView):
    template_name = "website/pages/blog_detail.html"
    context_object_name = "post"

    def get_object(self):
        return get_object_or_404(BlogPost, slug=self.kwargs["slug"], is_published=True)





def offline(request):
    return render(request, 'website/pages/offline.html', {'page_title': 'Offline'})



def _auto_assign_staff():
    """Round-robin assignment among staff users (excluding superusers optional)."""
    from django.contrib.auth import get_user_model
    User = get_user_model()
    staff = list(User.objects.filter(is_staff=True, is_active=True).order_by("id"))
    if not staff:
        return None
    # pick the staff with least open tickets
    from .models import SupportTicket
    best = None
    best_count = None
    for u in staff:
        c = SupportTicket.objects.filter(status__in=["open","pending"], assigned_to=u).count()
        if best is None or c < best_count:
            best, best_count = u, c
    return best

def _make_staff_notifications(title, body, url=""):
    from django.contrib.auth import get_user_model
    User = get_user_model()
    staff = User.objects.filter(is_staff=True, is_active=True)
    for u in staff:
        StaffNotification.objects.create(user=u, title=title[:140], body=body or "", url=url or "")

def _set_ticket_sla(ticket):
    try:
        mins = getattr(settings, "SUPPORT_SLA_MINUTES", 15)
    except Exception:
        mins = 15
    ticket.sla_minutes = mins
    ticket.due_at = ticket.created_at + timedelta(minutes=mins)

# -----------------------------------------------------------------------------
# Care Request Workflow (Step-by-step intake)
# -----------------------------------------------------------------------------
def _wizard_get(request):
    return request.session.get("care_wizard", {})

def _wizard_set(request, data):
    request.session["care_wizard"] = data
    request.session.modified = True

def care_request_step1(request):
    data = _wizard_get(request)
    form = CareRequestStep1Form(initial=data.get("step1"))
    if request.method == "POST":
        form = CareRequestStep1Form(request.POST)
        if form.is_valid():
            data["step1"] = form.cleaned_data
            _wizard_set(request, data)
            return redirect("website:care_request_step2")
    return render(request, "website/pages/care_request_step1.html", {"form": form, "page_title": "Request Care (Step 1/4)"})

def care_request_step2(request):
    data = _wizard_get(request)
    if not data.get("step1"):
        return redirect("website:care_request_step1")
    form = CareRequestStep2Form(initial=data.get("step2"))
    if request.method == "POST":
        form = CareRequestStep2Form(request.POST)
        if form.is_valid():
            data["step2"] = form.cleaned_data
            _wizard_set(request, data)
            return redirect("website:care_request_step3")
    return render(request, "website/pages/care_request_step2.html", {"form": form, "page_title": "Request Care (Step 2/4)"})

def care_request_step3(request):
    data = _wizard_get(request)
    if not data.get("step1") or not data.get("step2"):
        return redirect("website:care_request_step1")
    form = CareRequestStep3Form(initial=data.get("step3"))
    if request.method == "POST":
        form = CareRequestStep3Form(request.POST)
        if form.is_valid():
            data["step3"] = form.cleaned_data
            _wizard_set(request, data)
            return redirect("website:care_request_review")
    return render(request, "website/pages/care_request_step3.html", {"form": form, "page_title": "Request Care (Step 3/4)"})

def care_request_review(request):
    data = _wizard_get(request)
    if not data.get("step1") or not data.get("step2"):
        return redirect("website:care_request_step1")

    if request.method == "POST":
        s1 = data.get("step1", {})
        s2 = data.get("step2", {})
        s3 = data.get("step3", {})

        cr = CareRequest.objects.create(
            full_name=s1.get("full_name",""),
            phone=s1.get("phone",""),
            email=s1.get("email","") or "",
            location=s1.get("location","") or "",
            request_type=s2.get("request_type","home_care"),
            patient_age=s2.get("patient_age"),
            care_needs=s2.get("care_needs",""),
            schedule_notes=s2.get("schedule_notes","") or "",
            preferred_start_date=s3.get("preferred_start_date"),
            preference_notes=s3.get("preference_notes","") or "",
            risk_notes=s3.get("risk_notes","") or "",
            status="new",
        )

        # Email notify
        send_mail(
            subject=f"New Care Request: {cr.get_request_type_display()}",
            message=f"Name: {cr.full_name}\nPhone: {cr.phone}\nLocation: {cr.location}\n\nNeeds: {cr.care_needs}\nSchedule: {cr.schedule_notes}\nStart: {cr.preferred_start_date}\n\nPreferences: {cr.preference_notes}\nRisks: {cr.risk_notes}",
            from_email=settings.DEFAULT_FROM_EMAIL,
            recipient_list=[getattr(settings, "ADMIN_NOTIFY_EMAIL", "admin@example.com")],
            fail_silently=True,
        )

        # WhatsApp routing (optional)
        wa_to = route_number(cr.request_type)
        send_whatsapp_text(wa_to, f"New Care Request ({cr.get_request_type_display()}):\n{cr.full_name} | {cr.phone}\nLocation: {cr.location}\nNeeds: {cr.care_needs[:500]}")

        # Clear wizard
        request.session.pop("care_wizard", None)
        return redirect("website:care_request_success")

    return render(request, "website/pages/care_request_review.html", {
        "data": data,
        "page_title": "Request Care (Review & Submit)",
    })

def care_request_success(request):
    return render(request, "website/pages/care_request_success.html", {"page_title": "Request Submitted"})


# -----------------------------------------------------------------------------
# WhatsApp Business API Webhook (Cloud API)
# -----------------------------------------------------------------------------
def whatsapp_webhook(request):
    # Verification (GET)
    if request.method == "GET":
        mode = request.GET.get("hub.mode")
        token = request.GET.get("hub.verify_token")
        challenge = request.GET.get("hub.challenge")
        if mode == "subscribe" and token == getattr(settings, "WHATSAPP_VERIFY_TOKEN", ""):
            return HttpResponse(challenge or "", content_type="text/plain")
        return HttpResponse("Verification failed", status=403)

    # Incoming messages (POST)
    if request.method == "POST":
        try:
            payload = json.loads(request.body.decode("utf-8") or "{}")
        except Exception:
            payload = {}
        # Minimal acknowledgement; store/route can be expanded
        return JsonResponse({"status": "ok"})
    return JsonResponse({"detail": "Method not allowed"}, status=405)


# -----------------------------------------------------------------------------
# Caregiver Dashboard (Availability + Assignments)
# -----------------------------------------------------------------------------
def _is_staff(user):
    return user.is_authenticated and user.is_staff

@login_required
def caregiver_portal(request):
    # Caregivers (non-staff) can view their own assignments if they have a profile
    profile, _ = CaregiverProfile.objects.get_or_create(user=request.user)
    assignments = profile.assignments.select_related("care_request").all()[:50]
    form = CaregiverAvailabilityForm(instance=profile)
    if request.method == "POST":
        form = CaregiverAvailabilityForm(request.POST, instance=profile)
        if form.is_valid():
            form.save()
            return redirect("website:caregiver_portal")
    return render(request, "website/pages/caregiver_portal.html", {
        "profile": profile,
        "assignments": assignments,
        "form": form,
        "page_title": "Caregiver Portal",
    })

@user_passes_test(_is_staff)
def staff_care_dashboard(request):
    # Staff dashboard for intake + matching
    care_requests = CareRequest.objects.all().order_by("-created_at")[:50]
    caregivers = CaregiverProfile.objects.filter(is_active=True).select_related("user").order_by("user__first_name")[:100]
    assignments = CareAssignment.objects.select_related("care_request", "caregiver", "caregiver__user").all()[:50]
    return render(request, "website/pages/staff_care_dashboard.html", {
        "care_requests": care_requests,
        "caregivers": caregivers,
        "assignments": assignments,
        "page_title": "Staff Care Dashboard",
    })

@user_passes_test(_is_staff)
def staff_assignment_create(request):
    form = AssignmentCreateForm()
    if request.method == "POST":
        form = AssignmentCreateForm(request.POST)
        if form.is_valid():
            assign = form.save()
            # Update care request status
            cr = assign.care_request
            if cr.status in ("new", "assessment"):
                cr.status = "matched"
                cr.save(update_fields=["status"])
            # Optional WhatsApp notify (internal)
            wa_to = getattr(settings, "WHATSAPP_DEFAULT_ROUTE", "")
            send_whatsapp_text(wa_to, f"Care Assignment created: {assign.caregiver} assigned to {assign.care_request.full_name} ({assign.care_request.get_request_type_display()}).")
            return redirect("website:staff_care_dashboard")
    return render(request, "website/pages/staff_assignment_create.html", {"form": form, "page_title": "Create Assignment"})


def legal_privacy(request):
    return render(request, "website/pages/legal_privacy.html", {"page_title": "Privacy Policy"})

def legal_terms(request):
    return render(request, "website/pages/legal_terms.html", {"page_title": "Terms & Conditions"})

def legal_disclaimer(request):
    return render(request, "website/pages/legal_disclaimer.html", {"page_title": "Disclaimer"})


# -----------------------------------------------------------------------------
# Support Tickets
# -----------------------------------------------------------------------------
def support_ticket_create(request):
    """Create a support ticket from the chat widget or full page."""
    from .forms import SupportTicketForm
    from .models import SupportTicket, SupportMessage

    if request.method == "POST":
        form = SupportTicketForm(request.POST)
        if form.is_valid():
            data = form.cleaned_data
            public_id = SupportTicket.new_id()
            secret = str(uuid.uuid4())
            ticket = SupportTicket.objects.create(
                public_id=public_id,
                secret=secret,
                full_name=data.get("full_name",""),
                email=data.get("email","") or "",
                phone=data.get("phone","") or "",
                subject=(data.get("subject") or "Support Request")[:180],
                status="open",
            )
            # Auto-assign staff + set SLA
            ticket.assigned_to = _auto_assign_staff()
            _set_ticket_sla(ticket)
            ticket.save()
            SupportMessage.objects.create(
                ticket=ticket,
                sender="client",
                message=data.get("message","").strip(),
            )
            ticket.last_client_message_at = ticket.created_at
            ticket.save(update_fields=["last_client_message_at"])
            # Notify staff (in-app) + WhatsApp
            _make_staff_notifications(
                title=f"New support ticket #{ticket.public_id}",
                body=f"{ticket.full_name} • {ticket.subject}",
                url=f"/staff/support/{ticket.public_id}/",
            )
            # Optional: route to WhatsApp too (keep it separate from floating button)
            try:
                wa_to = route_number("home_care")
                send_whatsapp_text(wa_to, f"New Support Ticket #{ticket.public_id}\n{ticket.full_name} | {ticket.phone}\n{ticket.subject}\n\n{data.get('message','')[:700]}")
            except Exception:
                pass

            # Store last ticket in session for widget preview
            try:
                request.session["last_support_ticket"] = {"public_id": ticket.public_id, "secret": ticket.secret}
            except Exception:
                pass

            # If submitted from the widget, respond with JSON for instant success UI
            is_ajax = request.headers.get("x-requested-with") == "XMLHttpRequest" or request.POST.get("from_widget") == "1"
            if is_ajax:
                return JsonResponse({
                    "ok": True,
                    "ticket_public_id": ticket.public_id,
                    "ticket_url": f"/support/t/{ticket.public_id}/{ticket.secret}/",
                })

            return redirect("website:support_ticket_thanks", public_id=ticket.public_id, secret=ticket.secret)
    else:
        form = SupportTicketForm()

    return render(request, "website/pages/support_ticket_new.html", {"form": form, "page_title": "Support"})



def support_panel_preview(request):
    """Secure preview:
    - Preferred: phone + ticket public_id must match a real ticket (prevents random phone lookup).
    - Fallback: session last_support_ticket (same-device convenience).
    """
    from .models import SupportTicket, SupportMessage

    phone = (request.GET.get("phone") or "").strip()
    ticket_id = (request.GET.get("ticket") or "").strip()

    ticket = None

    # Secure path: require BOTH phone and ticket id
    if phone and ticket_id:
        ticket = SupportTicket.objects.filter(public_id=ticket_id, phone=phone).first()

    # Fallback: same-device session
    if not ticket:
        data = request.session.get("last_support_ticket") or {}
        public_id = (data.get("public_id") or "").strip()
        secret = (data.get("secret") or "").strip()
        if public_id and secret:
            ticket = SupportTicket.objects.filter(public_id=public_id, secret=secret).first()

    if not ticket:
        return JsonResponse({"ok": False, "messages": []})

    qs = SupportMessage.objects.filter(ticket=ticket).order_by("-created_at")[:3]
    msgs = []
    for m in reversed(list(qs)):
        msgs.append({
            "sender": m.sender,
            "message": m.message,
            "created_at": m.created_at.isoformat() if getattr(m, "created_at", None) else "",
        })

    return JsonResponse({
        "ok": True,
        "ticket_public_id": ticket.public_id,
        "ticket_url": f"/support/t/{ticket.public_id}/{ticket.secret}/",
        "messages": msgs,
    })


    qs = SupportMessage.objects.filter(ticket=ticket).order_by("-created_at")[:3]
    msgs = []
    for m in reversed(list(qs)):
        msgs.append({
            "sender": m.sender,
            "message": m.message,
            "created_at": m.created_at.isoformat() if getattr(m, "created_at", None) else "",
        })

    return JsonResponse({
        "ok": True,
        "ticket_public_id": ticket.public_id,
        "ticket_url": f"/support/t/{ticket.public_id}/{ticket.secret}/",
        "messages": msgs,
    })
def support_ticket_thanks(request, public_id, secret):
    ticket = SupportTicket.objects.filter(public_id=public_id, secret=secret).first()
    if not ticket:
        return redirect("website:home")
    return render(request, "website/pages/support_ticket_thanks.html", {"ticket": ticket, "page_title":"Ticket Created"})

def support_ticket_view(request, public_id, secret):
    ticket = SupportTicket.objects.filter(public_id=public_id, secret=secret).first()
    if not ticket:
        return redirect("website:home")

    if request.method == "POST":
        msg = (request.POST.get("message") or "").strip()
        if msg:
            SupportMessage.objects.create(ticket=ticket, sender="client", message=msg)
            ticket.last_client_message_at = timezone.now()
            ticket.save(update_fields=["last_client_message_at"])
            _make_staff_notifications(
                title=f"New reply on ticket #{ticket.public_id}",
                body=(msg[:180] + ("…" if len(msg)>180 else "")),
                url=f"/staff/support/{ticket.public_id}/",
            )
            try:
                wa_to = getattr(settings, 'WHATSAPP_SUPPORT_ROUTE', '') or route_number('home_care')
                send_whatsapp_text(
                    wa_to,
                    (
                        f"New client reply • Ticket #{ticket.public_id}\n"
                        f"{ticket.full_name} | {ticket.phone}\n\n"
                        f"{msg[:700]}"
                    ),
                )
            except Exception:
                pass
            return redirect("website:support_ticket_view", public_id=ticket.public_id, secret=ticket.secret)

    return render(request, "website/pages/support_ticket_view.html", {"ticket": ticket, "page_title": f"Ticket {ticket.public_id}"})

@staff_member_required
def staff_support_dashboard(request):
    qs = SupportTicket.objects.all().order_by("-created_at")
    status = request.GET.get("status","")
    if status in {"open","pending","closed"}:
        qs = qs.filter(status=status)
    return render(request, "website/staff/support_dashboard.html", {"tickets": qs[:200], "status": status, "page_title": "Support Tickets"})

@staff_member_required
def staff_support_ticket(request, public_id):
    ticket = SupportTicket.objects.filter(public_id=public_id).first()
    if not ticket:
        return redirect("website:staff_support_dashboard")

    if request.method == "POST":
        action = request.POST.get("action")
        if action in {"open", "pending", "closed"}:
            ticket.status = action
            ticket.save()

        msg = (request.POST.get("staff_message") or "").strip()
        if msg:
            SupportMessage.objects.create(ticket=ticket, sender="staff", message=msg)

            now = timezone.now()
            if not ticket.first_response_at:
                ticket.first_response_at = now
            ticket.last_staff_message_at = now
            ticket.save(update_fields=["first_response_at", "last_staff_message_at"])

            # Notify client on WhatsApp (if phone provided)
            try:
                client_number = (ticket.phone or "").strip()
                if client_number:
                    base = getattr(settings, "SITE_BASE_URL", "") or ""
                    link = (
                        f"{base}/support/t/{ticket.public_id}/{ticket.secret}/"
                        if base else f"/support/t/{ticket.public_id}/{ticket.secret}/"
                    )

                    message = (
                        f"Holistic Caregiver Support ✅\n\n"
                        f"We replied to your ticket #{ticket.public_id}.\n\n"
                        f"Message:\n{msg[:1200]}\n\n"
                        f"Follow up here:\n{link}"
                    )
                    send_whatsapp_text(client_number, message)
            except Exception:
                pass

        return redirect("website:staff_support_ticket", public_id=ticket.public_id)

    return render(
        request,
        "website/staff/support_ticket.html",
        {"ticket": ticket, "page_title": f"Support {ticket.public_id}"},
    )


@staff_member_required
def staff_support_analytics(request):
    from django.db.models import Avg, Count
    from django.utils import timezone
    now = timezone.now()
    tickets = SupportTicket.objects.all()
    open_count = tickets.filter(status="open").count()
    pending_count = tickets.filter(status="pending").count()
    closed_count = tickets.filter(status="closed").count()

    # avg first response (minutes)
    resp_mins = []
    for t in tickets.exclude(first_response_at__isnull=True):
        resp_mins.append((t.first_response_at - t.created_at).total_seconds()/60.0)
    avg_first_response = round(sum(resp_mins)/len(resp_mins),2) if resp_mins else None

    sla_missed = tickets.filter(status__in=["open","pending"], due_at__isnull=False, due_at__lt=now, first_response_at__isnull=True).count()

    recent = tickets.order_by("-created_at")[:12]

    return render(request, "website/staff/support_analytics.html", {
        "open_count": open_count,
        "pending_count": pending_count,
        "closed_count": closed_count,
        "avg_first_response": avg_first_response,
        "sla_missed": sla_missed,
        "recent": recent,
        "page_title": "Support Analytics",
    })

@staff_member_required
def staff_notifications_poll(request):
    qs = StaffNotification.objects.filter(user=request.user, is_read=False)[:20]
    data = [{
        "id": n.id,
        "title": n.title,
        "body": n.body,
        "url": n.url,
        "created_at": n.created_at.isoformat(),
    } for n in qs]
    return JsonResponse({"items": data})

@staff_member_required
def staff_notifications_mark_read(request):
    ids = request.POST.get("ids","")
    try:
        id_list = [int(x) for x in ids.split(",") if x.strip().isdigit()]
    except Exception:
        id_list = []
    if id_list:
        StaffNotification.objects.filter(user=request.user, id__in=id_list).update(is_read=True)
    return JsonResponse({"ok": True})
