from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.decorators import user_passes_test
from django.contrib.auth import authenticate, login, logout
from django.contrib import messages
from django.utils import timezone
from datetime import timedelta, datetime
from django.db.models import Count, Q
from django.core.paginator import Paginator

from apps.properties.models import Property, PropertyCategory, Location, PropertyImage
from apps.leads.models import Lead
from apps.sales_updates.models import SalesUpdate
from apps.videos.models import Video
from apps.forms.models import DownloadableForm
from apps.landing_pages.models import LandingPage
from apps.newsletter.models import Subscriber
from apps.chatbot.models import ChatSession, ChatbotKnowledge
from apps.core.models import SiteSetting
from .models import PageVisit, VisitorProfile


def is_staff(user):
    return user.is_authenticated and user.is_staff


def admin_login(request):
    if request.user.is_authenticated and request.user.is_staff:
        return redirect('analytics:dashboard')
    if request.method == 'POST':
        username = request.POST.get('username', '').strip()
        password = request.POST.get('password', '')
        user = authenticate(request, username=username, password=password)
        if user and user.is_staff:
            login(request, user)
            return redirect('analytics:dashboard')
        messages.error(request, 'Invalid credentials or insufficient permissions.')
    return render(request, 'admin_panel/login.html')


def admin_logout(request):
    logout(request)
    return redirect('analytics:login')


@user_passes_test(is_staff, login_url='/admin-panel/login/')
def dashboard(request):
    now = timezone.now()
    last_24h = now - timedelta(hours=24)
    last_7d = now - timedelta(days=7)

    kpis = {
        'total_properties': Property.objects.count(),
        'published_properties': Property.objects.filter(is_published=True).count(),
        'total_leads': Lead.objects.count(),
        'new_leads_24h': Lead.objects.filter(created_at__gte=last_24h).count(),
        'new_leads_7d': Lead.objects.filter(created_at__gte=last_7d).count(),
        'total_subscribers': Subscriber.objects.filter(is_active=True).count(),
        'visits_24h': PageVisit.objects.filter(visited_at__gte=last_24h, is_bot=False).count(),
        'visits_7d': PageVisit.objects.filter(visited_at__gte=last_7d, is_bot=False).count(),
        'chat_sessions': ChatSession.objects.count(),
        'chat_conversions': ChatSession.objects.filter(converted_to_lead=True).count(),
    }

    chart_days = []
    for i in range(13, -1, -1):
        day = (now - timedelta(days=i)).date()
        day_start = timezone.make_aware(datetime.combine(day, datetime.min.time()))
        day_end = day_start + timedelta(days=1)
        chart_days.append({
            'date': day.strftime('%b %d'),
            'visits': PageVisit.objects.filter(visited_at__gte=day_start, visited_at__lt=day_end, is_bot=False).count(),
            'leads': Lead.objects.filter(created_at__gte=day_start, created_at__lt=day_end).count(),
        })

    recent_leads = Lead.objects.select_related('property')[:10]
    top_properties = Property.objects.filter(is_published=True).order_by('-views_count')[:5]
    leads_by_source = Lead.objects.values('source').annotate(c=Count('id')).order_by('-c')

    return render(request, 'admin_panel/dashboard.html', {
        'kpis': kpis,
        'chart_days': chart_days,
        'recent_leads': recent_leads,
        'top_properties': top_properties,
        'leads_by_source': leads_by_source,
    })


# -------- Properties --------
@user_passes_test(is_staff, login_url='/admin-panel/login/')
def properties_list(request):
    qs = Property.objects.select_related('category', 'location').order_by('-created_at')
    q = request.GET.get('q', '').strip()
    status = request.GET.get('status', '')
    if q:
        qs = qs.filter(Q(title__icontains=q) | Q(address__icontains=q))
    if status:
        qs = qs.filter(status=status)
    paginator = Paginator(qs, 20)
    return render(request, 'admin_panel/properties_list.html', {
        'page_obj': paginator.get_page(request.GET.get('page')),
        'q': q, 'status': status,
        'statuses': Property.STATUS_CHOICES,
    })


@user_passes_test(is_staff, login_url='/admin-panel/login/')
def properties_form(request, pk=None):
    prop = get_object_or_404(Property, pk=pk) if pk else None
    if request.method == 'POST':
        data = request.POST
        files = request.FILES
        try:
            cat = PropertyCategory.objects.get(pk=data.get('category')) if data.get('category') else None
            loc = Location.objects.get(pk=data.get('location')) if data.get('location') else None
            if not prop:
                prop = Property(created_by=request.user, category=cat, location=loc,
                                main_image=files.get('main_image'))
            else:
                if cat: prop.category = cat
                if loc: prop.location = loc
                if files.get('main_image'):
                    prop.main_image = files['main_image']

            for f in ['title', 'listing_type', 'status', 'address', 'price_period',
                      'short_description', 'description', 'features', 'title_documents',
                      'plot_size', 'video_url', 'meta_title', 'meta_description']:
                if data.get(f) is not None:
                    setattr(prop, f, data.get(f))

            for f in ['price', 'area_sqm']:
                v = data.get(f)
                if v:
                    setattr(prop, f, v)

            for f in ['bedrooms', 'bathrooms', 'toilets', 'parking_spaces', 'year_built']:
                v = data.get(f)
                if v and str(v).isdigit():
                    setattr(prop, f, int(v))

            prop.is_negotiable = data.get('is_negotiable') == 'on'
            prop.is_flyer_image = data.get('is_flyer_image') == 'on'
            prop.is_featured = data.get('is_featured') == 'on'
            prop.is_verified = data.get('is_verified') == 'on'
            prop.is_published = data.get('is_published') == 'on'

            if files.get('floor_plan'):
                prop.floor_plan = files['floor_plan']

            prop.save()

            for img in files.getlist('gallery_images'):
                PropertyImage.objects.create(property=prop, image=img)

            messages.success(request, f"Property '{prop.title}' saved.")
            return redirect('analytics:properties_list')
        except Exception as e:
            messages.error(request, f"Error: {e}")

    return render(request, 'admin_panel/properties_form.html', {
        'property': prop,
        'categories': PropertyCategory.objects.all(),
        'locations': Location.objects.all(),
        'listing_types': Property.LISTING_TYPES,
        'statuses': Property.STATUS_CHOICES,
    })


@user_passes_test(is_staff, login_url='/admin-panel/login/')
def properties_delete(request, pk):
    prop = get_object_or_404(Property, pk=pk)
    if request.method == 'POST':
        title = prop.title
        prop.delete()
        messages.success(request, f"Deleted '{title}'.")
    return redirect('analytics:properties_list')


# -------- Leads --------
@user_passes_test(is_staff, login_url='/admin-panel/login/')
def leads_list(request):
    qs = Lead.objects.select_related('property').order_by('-created_at')
    status = request.GET.get('status', '')
    source = request.GET.get('source', '')
    q = request.GET.get('q', '').strip()
    if status: qs = qs.filter(status=status)
    if source: qs = qs.filter(source=source)
    if q:
        qs = qs.filter(Q(name__icontains=q) | Q(email__icontains=q) | Q(phone__icontains=q))
    paginator = Paginator(qs, 25)
    return render(request, 'admin_panel/leads_list.html', {
        'page_obj': paginator.get_page(request.GET.get('page')),
        'status': status, 'source': source, 'q': q,
        'statuses': Lead.STATUS_CHOICES,
        'sources': Lead.SOURCE_CHOICES,
    })


@user_passes_test(is_staff, login_url='/admin-panel/login/')
def lead_detail(request, pk):
    lead = get_object_or_404(Lead, pk=pk)
    if request.method == 'POST':
        lead.status = request.POST.get('status', lead.status)
        lead.notes = request.POST.get('notes', lead.notes)
        if lead.status == 'contacted' and not lead.contacted_at:
            lead.contacted_at = timezone.now()
        lead.save()
        messages.success(request, "Lead updated.")
        return redirect('analytics:lead_detail', pk=pk)
    return render(request, 'admin_panel/lead_detail.html', {
        'lead': lead, 'statuses': Lead.STATUS_CHOICES
    })


# -------- Sales updates --------
@user_passes_test(is_staff, login_url='/admin-panel/login/')
def updates_list(request):
    qs = SalesUpdate.objects.all().order_by('-publish_at')
    return render(request, 'admin_panel/updates_list.html', {
        'page_obj': Paginator(qs, 20).get_page(request.GET.get('page')),
    })


@user_passes_test(is_staff, login_url='/admin-panel/login/')
def updates_form(request, pk=None):
    update = get_object_or_404(SalesUpdate, pk=pk) if pk else None
    if request.method == 'POST':
        data = request.POST
        if not update:
            update = SalesUpdate(author=request.user)
        update.title = data.get('title', '')
        update.excerpt = data.get('excerpt', '')
        update.content = data.get('content', '')
        update.is_published = data.get('is_published') == 'on'
        publish_at = data.get('publish_at')
        if publish_at:
            update.publish_at = publish_at
        if request.FILES.get('cover_image'):
            update.cover_image = request.FILES['cover_image']
        update.save()
        messages.success(request, f"Update '{update.title}' saved.")
        return redirect('analytics:updates_list')
    return render(request, 'admin_panel/updates_form.html', {'update': update})


@user_passes_test(is_staff, login_url='/admin-panel/login/')
def updates_delete(request, pk):
    update = get_object_or_404(SalesUpdate, pk=pk)
    if request.method == 'POST':
        update.delete()
        messages.success(request, "Update deleted.")
    return redirect('analytics:updates_list')


# -------- Videos --------
@user_passes_test(is_staff, login_url='/admin-panel/login/')
def videos_list(request):
    qs = Video.objects.all().order_by('-created_at')
    return render(request, 'admin_panel/videos_list.html', {
        'page_obj': Paginator(qs, 20).get_page(request.GET.get('page'))
    })


@user_passes_test(is_staff, login_url='/admin-panel/login/')
def videos_form(request, pk=None):
    video = get_object_or_404(Video, pk=pk) if pk else None
    if request.method == 'POST':
        data = request.POST
        if not video:
            video = Video()
        video.title = data.get('title', '')
        video.description = data.get('description', '')
        video.source = data.get('source', 'youtube')
        video.video_url = data.get('video_url', '')
        video.duration = data.get('duration', '')
        video.category = data.get('category', 'property')
        video.orientation = data.get('orientation', 'horizontal')
        video.highlights = data.get('highlights', '')
        video.is_featured = data.get('is_featured') == 'on'
        video.is_published = data.get('is_published') == 'on'
        if request.FILES.get('thumbnail'):
            video.thumbnail = request.FILES['thumbnail']
        if request.FILES.get('video_file'):
            video.video_file = request.FILES['video_file']
        video.save()
        prop_ids = request.POST.getlist('related_properties')
        video.related_properties.set(Property.objects.filter(pk__in=prop_ids))
        messages.success(request, "Video saved.")
        return redirect('analytics:videos_list')
    return render(request, 'admin_panel/videos_form.html', {
        'video': video,
        'sources': Video.SOURCE_CHOICES,
        'categories': Video.CATEGORY_CHOICES,
        'orientations': Video.ORIENTATION_CHOICES,
        'all_properties': Property.objects.filter(is_published=True).select_related('location').order_by('title'),
    })


@user_passes_test(is_staff, login_url='/admin-panel/login/')
def videos_delete(request, pk):
    video = get_object_or_404(Video, pk=pk)
    if request.method == 'POST':
        video.delete()
        messages.success(request, "Video deleted.")
    return redirect('analytics:videos_list')


# -------- Downloadable forms --------
@user_passes_test(is_staff, login_url='/admin-panel/login/')
def forms_list(request):
    qs = DownloadableForm.objects.all()
    return render(request, 'admin_panel/forms_list.html', {'forms': qs})


@user_passes_test(is_staff, login_url='/admin-panel/login/')
def forms_form(request, pk=None):
    form_obj = get_object_or_404(DownloadableForm, pk=pk) if pk else None
    if request.method == 'POST':
        data = request.POST
        if not form_obj:
            form_obj = DownloadableForm()
        form_obj.title = data.get('title', '')
        form_obj.description = data.get('description', '')
        form_obj.require_email = data.get('require_email') == 'on'
        form_obj.is_active = data.get('is_active') == 'on'
        if request.FILES.get('file'):
            form_obj.file = request.FILES['file']
        if request.FILES.get('cover'):
            form_obj.cover = request.FILES['cover']
        form_obj.save()
        messages.success(request, "Form saved.")
        return redirect('analytics:forms_list')
    return render(request, 'admin_panel/forms_form.html', {'form_obj': form_obj})


@user_passes_test(is_staff, login_url='/admin-panel/login/')
def forms_delete(request, pk):
    form_obj = get_object_or_404(DownloadableForm, pk=pk)
    if request.method == 'POST':
        form_obj.delete()
        messages.success(request, "Form deleted.")
    return redirect('analytics:forms_list')


# -------- Landing pages --------
@user_passes_test(is_staff, login_url='/admin-panel/login/')
def landing_list(request):
    qs = LandingPage.objects.all().order_by('-created_at')
    return render(request, 'admin_panel/landing_list.html', {'pages': qs})


@user_passes_test(is_staff, login_url='/admin-panel/login/')
def landing_form(request, pk=None):
    page = get_object_or_404(LandingPage, pk=pk) if pk else None
    if request.method == 'POST':
        data = request.POST
        if not page:
            page = LandingPage(created_by=request.user)
        for f in ['title', 'slug', 'headline', 'subheadline', 'cta_text', 'cta_phone',
                  'body_html', 'meta_title', 'meta_description', 'theme_color', 'location_short']:
            if data.get(f) is not None:
                setattr(page, f, data.get(f))
        sp = data.get('starting_price', '').strip()
        page.starting_price = sp if sp else None
        page.is_published = data.get('is_published') == 'on'
        page.show_inquiry_form = data.get('show_inquiry_form') == 'on'
        page.show_chatbot = data.get('show_chatbot') == 'on'
        if request.FILES.get('hero_image'):
            page.hero_image = request.FILES['hero_image']
        page.save()
        prop_ids = request.POST.getlist('properties')
        page.properties.set(Property.objects.filter(pk__in=prop_ids))
        messages.success(request, f"Landing page '/p/{page.slug}/' saved.")
        return redirect('analytics:landing_list')
    return render(request, 'admin_panel/landing_form.html', {
        'page': page,
        'all_properties': Property.objects.filter(is_published=True),
    })


@user_passes_test(is_staff, login_url='/admin-panel/login/')
def landing_delete(request, pk):
    page = get_object_or_404(LandingPage, pk=pk)
    if request.method == 'POST':
        page.delete()
        messages.success(request, "Landing page deleted.")
    return redirect('analytics:landing_list')


# -------- Chatbot KB --------
@user_passes_test(is_staff, login_url='/admin-panel/login/')
def chatbot_kb_list(request):
    return render(request, 'admin_panel/chatbot_kb_list.html', {
        'items': ChatbotKnowledge.objects.all()
    })


@user_passes_test(is_staff, login_url='/admin-panel/login/')
def chatbot_kb_form(request, pk=None):
    item = get_object_or_404(ChatbotKnowledge, pk=pk) if pk else None
    if request.method == 'POST':
        data = request.POST
        if not item:
            item = ChatbotKnowledge()
        item.question = data.get('question', '')
        item.answer = data.get('answer', '')
        item.keywords = data.get('keywords', '')
        item.is_active = data.get('is_active') == 'on'
        item.save()
        messages.success(request, "Knowledge entry saved.")
        return redirect('analytics:chatbot_kb_list')
    return render(request, 'admin_panel/chatbot_kb_form.html', {'item': item})


@user_passes_test(is_staff, login_url='/admin-panel/login/')
def chatbot_kb_delete(request, pk):
    item = get_object_or_404(ChatbotKnowledge, pk=pk)
    if request.method == 'POST':
        item.delete()
        messages.success(request, "Entry deleted.")
    return redirect('analytics:chatbot_kb_list')


# -------- Site settings --------
@user_passes_test(is_staff, login_url='/admin-panel/login/')
def site_settings_view(request):
    site = SiteSetting.get()
    if request.method == 'POST':
        data = request.POST
        for f in ['site_name', 'tagline', 'hero_title', 'hero_subtitle', 'about_short',
                  'phone', 'phone_secondary', 'email', 'whatsapp_number', 'address',
                  'facebook', 'instagram', 'twitter', 'linkedin', 'youtube', 'tiktok',
                  'popup_title', 'popup_subtitle', 'popup_cta',
                  'chatbot_name', 'chatbot_greeting']:
            if data.get(f) is not None:
                setattr(site, f, data.get(f))
        for f in ['clients_count', 'properties_sold', 'years_experience', 'locations_covered']:
            v = data.get(f)
            if v and str(v).isdigit():
                setattr(site, f, int(v))
        site.popup_enabled = data.get('popup_enabled') == 'on'
        site.chatbot_enabled = data.get('chatbot_enabled') == 'on'
        if request.FILES.get('hero_image'):
            site.hero_image = request.FILES['hero_image']
        site.save()
        messages.success(request, "Site settings updated.")
        return redirect('analytics:site_settings')
    return render(request, 'admin_panel/site_settings.html', {'site': site})


@user_passes_test(is_staff, login_url='/admin-panel/login/')
def subscribers_list(request):
    qs = Subscriber.objects.all().order_by('-subscribed_at')
    return render(request, 'admin_panel/subscribers_list.html', {
        'page_obj': Paginator(qs, 50).get_page(request.GET.get('page'))
    })


# -------- Visitor logs --------
@user_passes_test(is_staff, login_url='/admin-panel/login/')
def visitors_list(request):
    qs = VisitorProfile.objects.select_related('lead').order_by('-last_seen')

    # Filters
    converted = request.GET.get('converted', '')
    device = request.GET.get('device', '')
    q = request.GET.get('q', '').strip()

    if converted == '1':
        qs = qs.filter(converted=True)
    elif converted == '0':
        qs = qs.filter(converted=False)
    if device:
        qs = qs.filter(device_type=device)
    if q:
        qs = qs.filter(
            Q(email__icontains=q) | Q(name__icontains=q) |
            Q(phone__icontains=q) | Q(ip_address__icontains=q)
        )

    paginator = Paginator(qs, 50)
    return render(request, 'admin_panel/visitors_list.html', {
        'page_obj': paginator.get_page(request.GET.get('page')),
        'converted': converted,
        'device': device,
        'q': q,
        'total': qs.count(),
        'identified': qs.filter(Q(email__gt='') | Q(name__gt='')).count(),
        'converted_count': qs.filter(converted=True).count(),
    })


@user_passes_test(is_staff, login_url='/admin-panel/login/')
def visitor_detail(request, pk):
    profile = get_object_or_404(VisitorProfile, pk=pk)
    page_visits = PageVisit.objects.filter(
        session_key=profile.session_key
    ).order_by('visited_at')
    return render(request, 'admin_panel/visitor_detail.html', {
        'profile': profile,
        'page_visits': page_visits,
    })
