from datetime import timedelta

from django.contrib.admin.views.decorators import staff_member_required
from django.contrib.auth.decorators import login_required
from django.contrib.auth.forms import PasswordChangeForm
from django.contrib.auth import update_session_auth_hash
from django.contrib import messages
from django.core.mail import EmailMultiAlternatives
from django.db.models import Count, Q
from django.shortcuts import render, get_object_or_404, redirect
from django.template.loader import get_template
from django.conf import settings
from django.urls import reverse
from django.utils import timezone
from django.views.decorators.http import require_POST

from .forms import FormWithCaptcha
from .middleware import get_session_utm
from .models import Contact, EmailMessage, PageVisit
from .traffic import TRAFFIC_TYPE_LABELS, TrafficType

def send_contact_email(email, subject, message):
    subject = "New Contact Request for AI ML Operations, LLC"
    from_email = "ryan@aimloperations.com"
    to="ryan@aimloperations.com"
    d = {"subject": subject, "message": message, "email": email}
    html_content = get_template(r'emails/contact_email.html').render(d)
    text_content = get_template(r'emails/contact_email.txt').render(d)
    
    msg = EmailMultiAlternatives(subject, text_content, from_email, [to])
    msg.attach_alternative(html_content, "text/html")
    msg.send(fail_silently=True)

# Create your views here.
def index(request):    
    return render(request, "public/new_index.html", {})

def chat(request):
    return render(request, "public/chat.html", {})

def ai_education(request):
    return render(request, "public/ai_education.html", {})

def computers(request):
    return render(request, "public/computers.html", {})

def web_design(request):
    from .web_design_pricing import (
        WEB_DESIGN_INCLUDED,
        WEB_DESIGN_PRICING_DISCLAIMER,
        features_for_json,
        estimate_web_design_cost,
    )

    return render(
        request,
        "public/web_design.html",
        {
            "pricing_features": features_for_json(),
            "pricing_included": WEB_DESIGN_INCLUDED,
            "pricing_disclaimer": WEB_DESIGN_PRICING_DISCLAIMER,
            "pricing_base_estimate": estimate_web_design_cost(),
        },
    )

def ai_sensor(request):
    return render(request, "public/ai_sensor.html", {})

def file_hosting(request):
    return render(request, "public/file_hosting.html", {})

def bot(request):
    return render(request, "public/bot.html", {})

def forward_deployed(request):
    return render(request, "public/forward_deployed.html", {})

def ml_model(request):
    return render(request, "public/ml_model.html", {})

def terms_of_service(request):
    return render(request, "public/terms_of_service.html", {})

@login_required
def preview_email(request, pk):
    email_instance = get_object_or_404(EmailMessage, pk=pk)
    context = {
        "title":email_instance.subject,
        "content":email_instance.body
    }
    return render(
        request, 'public/preview_email.html', context
    )

def contact(request):
    errors = ''
    

    if request.method == 'POST':
        name = request.POST.get('name')
        email = request.POST.get('email')
        message = request.POST.get('message', "")
        subject = request.POST.get('subject', "")
        capchaForm = FormWithCaptcha(request.POST)
        
        if len(name) > 0 and len(email) > 0 and len(subject) > 0:
            if settings.DEBUG or capchaForm.is_valid():

            
                # then we are good
                utm = get_session_utm(request.session)
                c = Contact(
                    name=name,
                    email=email,
                    blurb=message,
                    subject=subject,
                    utm_source=utm.get("utm_source", ""),
                    utm_medium=utm.get("utm_medium", ""),
                    utm_campaign=utm.get("utm_campaign", ""),
                    utm_term=utm.get("utm_term", ""),
                    utm_content=utm.get("utm_content", ""),
                )
                c.save()
                # send the email.
                try:
                    send_contact_email(email, subject, message)
                except Exception as e:
                    print(f'Error sending the email {e}')
                    print('Contact Request:')
                    print(f'From: {name}')
                    print(f'Message: {message}')
                return render(request, "public/contact.html", {'success':True, 'capchaForm': FormWithCaptcha()})
            else:
                return render(request, "public/contact.html", {'errors': "There was an error submitting. Try again", 'capchaForm': capchaForm})
        else:
            if len(name) == 0 and len(email) == 0:
                errors = 'Both name and email are required'
            elif len(email) == 0:
                errors = 'Email is required'
            elif len(name) == 0:
                errors = 'Name is required'
            # we need to show an error
            return render(request, "public/contact.html", {'errors': errors, 'capchaForm': capchaForm})
    
    capcha = None if settings.DEBUG else FormWithCaptcha()
    return render(request, "public/contact.html", {'capchaForm': capcha})

@login_required
def change_password(request):
    if request.method == 'POST':
        form = PasswordChangeForm(request.user, request.POST)
        if form.is_valid():
            user = form.save()
            update_session_auth_hash(request, user)  # Important!
            messages.success(request, 'Your password was successfully updated!')
            return redirect('public_index')
        else:
            messages.error(request, 'Please correct the error below.')
    else:
        form = PasswordChangeForm(request.user)
    return render(request, 'public/change_password.html', {
        'form': form
    })


@staff_member_required
def utm_dashboard(request):
    try:
        days = int(request.GET.get("days", "30"))
    except (TypeError, ValueError):
        days = 30
    if days not in (7, 30, 90, 365):
        days = 30

    traffic_filter = request.GET.get("traffic", "")
    since = timezone.now() - timedelta(days=days)
    visits = PageVisit.objects.filter(created__gte=since)

    if traffic_filter in {t.value for t in TrafficType}:
        visits = visits.filter(traffic_type=traffic_filter)

    type_counts_qs = (
        PageVisit.objects.filter(created__gte=since)
        .values("traffic_type")
        .annotate(total=Count("id"))
        .order_by("-total")
    )
    type_counts = [
        {
            "key": row["traffic_type"],
            "label": TRAFFIC_TYPE_LABELS.get(
                TrafficType(row["traffic_type"]), row["traffic_type"]
            )
            if row["traffic_type"] in {t.value for t in TrafficType}
            else row["traffic_type"],
            "total": row["total"],
        }
        for row in type_counts_qs
    ]

    total_visits = PageVisit.objects.filter(created__gte=since).count()
    human_count = PageVisit.objects.filter(
        created__gte=since, traffic_type=TrafficType.HUMAN
    ).count()
    ai_count = PageVisit.objects.filter(
        created__gte=since, traffic_type=TrafficType.AI_BOT
    ).count()
    indexer_count = PageVisit.objects.filter(
        created__gte=since, traffic_type=TrafficType.SEARCH_INDEXER
    ).count()
    utm_landings = PageVisit.objects.filter(
        created__gte=since, is_landing=True
    ).count()
    attributed_visits = PageVisit.objects.filter(created__gte=since).exclude(
        utm_source=""
    ).count()

    def top_utm(field: str, limit: int = 10):
        return list(
            PageVisit.objects.filter(created__gte=since)
            .exclude(**{field: ""})
            .values(field)
            .annotate(total=Count("id"))
            .order_by("-total")[:limit]
        )

    top_pages = list(
        visits.values("path")
        .annotate(total=Count("id"))
        .order_by("-total")[:15]
    )

    recent = list(visits[:100])

    contacts_with_utm = (
        Contact.objects.filter(created__gte=since)
        .exclude(utm_source="")
        .order_by("-created")[:25]
    )

    return render(
        request,
        "public/utm_dashboard.html",
        {
            "days": days,
            "traffic_filter": traffic_filter,
            "traffic_choices": [
                (t.value, TRAFFIC_TYPE_LABELS[t]) for t in TrafficType
            ],
            "total_visits": total_visits,
            "human_count": human_count,
            "ai_count": ai_count,
            "indexer_count": indexer_count,
            "utm_landings": utm_landings,
            "attributed_visits": attributed_visits,
            "type_counts": type_counts,
            "top_sources": top_utm("utm_source"),
            "top_mediums": top_utm("utm_medium"),
            "top_campaigns": top_utm("utm_campaign"),
            "top_pages": top_pages,
            "recent_visits": recent,
            "contacts_with_utm": contacts_with_utm,
        },
    )


@staff_member_required
def leads_list(request):
    try:
        days = int(request.GET.get("days", "90"))
    except (TypeError, ValueError):
        days = 90
    if days not in (7, 30, 90, 365, 0):
        days = 90

    status = request.GET.get("status", "")
    q = (request.GET.get("q") or "").strip()
    utm_only = request.GET.get("utm") == "1"

    leads = Contact.objects.all().order_by("-created")
    if days:
        leads = leads.filter(created__gte=timezone.now() - timedelta(days=days))
    if status == "new":
        leads = leads.filter(contacted=False)
    elif status == "contacted":
        leads = leads.filter(contacted=True)
    if utm_only:
        leads = leads.exclude(utm_source="")
    if q:
        leads = leads.filter(
            Q(name__icontains=q)
            | Q(email__icontains=q)
            | Q(subject__icontains=q)
            | Q(blurb__icontains=q)
            | Q(utm_source__icontains=q)
            | Q(utm_campaign__icontains=q)
        )

    base = Contact.objects.all()
    if days:
        base = base.filter(created__gte=timezone.now() - timedelta(days=days))

    total = base.count()
    new_count = base.filter(contacted=False).count()
    contacted_count = base.filter(contacted=True).count()
    with_utm = base.exclude(utm_source="").count()

    return render(
        request,
        "public/leads_list.html",
        {
            "leads": leads[:200],
            "lead_count": leads.count(),
            "days": days,
            "status": status,
            "q": q,
            "utm_only": utm_only,
            "total": total,
            "new_count": new_count,
            "contacted_count": contacted_count,
            "with_utm": with_utm,
        },
    )


@staff_member_required
def lead_detail(request, pk):
    lead = get_object_or_404(Contact, pk=pk)
    return render(request, "public/lead_detail.html", {"lead": lead})


@staff_member_required
@require_POST
def lead_toggle_contacted(request, pk):
    lead = get_object_or_404(Contact, pk=pk)
    lead.contacted = not lead.contacted
    lead.save(update_fields=["contacted", "last_modified"])
    messages.success(
        request,
        f"Marked {lead.name} as {'contacted' if lead.contacted else 'new'}.",
    )
    next_url = request.POST.get("next") or reverse("lead_detail", kwargs={"pk": lead.pk})
    return redirect(next_url)

