# properties/views.py

from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.utils import timezone
from django.db.models import Sum
from accounts.models import User
from core.models import ActivityLog
from payments.models import Payment, Invoice
from properties.models import Unit, UnitTenantHistory, UnitRentHistory, Building
from tenants.models import TenantProfile


def is_tenant_onboarded(profile):
    return profile and profile.id_image


# =========================
# BUILDINGS
# =========================

@login_required
def building_list(request):

    if request.user.role == "landlord":
        buildings = Building.objects.filter(landlord=request.user)
    elif request.user.role == "caretaker":
        buildings = Building.objects.filter(caretaker=request.user)
    else:
        buildings = Building.objects.none()

    return render(request, "properties/building_list.html", {
        "buildings": buildings
    })


@login_required
def building_add(request):

    if request.user.role != "landlord":
        return redirect("building_list")

    if request.method == "POST":
        name = request.POST.get("name")
        location = request.POST.get("location")
        caretaker_id = request.POST.get("caretaker")

        caretaker = None
        if caretaker_id:
            caretaker = get_object_or_404(User, id=caretaker_id, role="caretaker")

        Building.objects.create(
            name=name,
            location=location,
            landlord=request.user,
            caretaker=caretaker
        )

        return redirect("building_list")

    caretakers = User.objects.filter(role="caretaker")

    return render(request, "properties/building_form.html", {
        "caretakers": caretakers
    })


# =========================
# UNITS
# =========================

@login_required
def unit_list(request):

    if request.user.role == "landlord":
        units = Unit.objects.filter(building__landlord=request.user)
    elif request.user.role == "caretaker":
        units = Unit.objects.filter(building__caretaker=request.user)
    else:
        units = Unit.objects.none()

    building_id = request.GET.get("building")

    if building_id:
        units = units.filter(building_id=building_id)

    # 🔥 FORCE DB ANNOTATION (REAL FIX)
    occupied_count = units.filter(
        tenant_history__is_current=True
    ).distinct().count()

    vacant_count = units.count() - occupied_count

    return render(request, "properties/unit_list.html", {
        "units": units,
        "occupied_count": occupied_count,
        "vacant_count": vacant_count,
    })

@login_required
def unit_add(request):

    if request.method == "POST":

        building_id = request.POST.get("building")
        building = get_object_or_404(Building, id=building_id)

        if request.user != building.landlord and request.user != building.caretaker:
            return redirect("unit_list")

        Unit.objects.create(
            building=building,
            unit_number=request.POST.get("unit_number"),
            unit_type=request.POST.get("unit_type"),
            rent_amount=request.POST.get("rent_amount"),
            deposit=request.POST.get("deposit"),
            created_by=request.user  # ✅ FIXED
        )

        return redirect("unit_list")

    if request.user.role == "landlord":
        buildings = Building.objects.filter(landlord=request.user)
    elif request.user.role == "caretaker":
        buildings = Building.objects.filter(caretaker=request.user)
    else:
        buildings = Building.objects.none()

    return render(request, "properties/unit_form.html", {
        "buildings": buildings
    })


@login_required
def unit_update(request, unit_id):
    unit = get_object_or_404(Unit, id=unit_id)

    if request.user != unit.building.landlord:
        return redirect("unit_list")

    if request.method == "POST":

        # ✅ FIXED
        if unit.tenant_history.exists():
            unit.unit_number = request.POST.get("unit_number")
            unit.rent_amount = request.POST.get("rent_amount")
        else:
            unit.unit_number = request.POST.get("unit_number")
            unit.unit_type = request.POST.get("unit_type")
            unit.rent_amount = request.POST.get("rent_amount")
            unit.deposit = request.POST.get("deposit")

        unit.save()
        return redirect("unit_list")

    return render(request, "properties/unit_form.html", {
        "unit": unit
    })



@login_required
def unit_detail(request, unit_id):
    unit = get_object_or_404(Unit, id=unit_id)

    # 🔥 FORCE FRESH STATUS UPDATE (CRITICAL FIX)
    for invoice in unit.invoices.all():
        invoice.update_status()

    payments = Payment.objects.filter(
        unit=unit
    ).select_related("invoice", "tenant").order_by('-created_at')[:10]

    tenant_history = unit.tenant_history.select_related("tenant").order_by("-start_date")
    rent_history = unit.rent_history.order_by("-changed_at")

    outstanding_invoices = unit.invoices.exclude(
        status="paid"
    ).order_by("-due_date")

    # 🔥 REAL BALANCE CALCULATION (NOT TEMPLATE DEPENDENT)
    total_due = unit.invoices.aggregate(total=Sum("amount"))["total"] or 0
    total_paid = Payment.objects.filter(unit=unit).aggregate(total=Sum("amount"))["total"] or 0
    balance = total_due - total_paid

    return render(request, "properties/unit_detail.html", {
        "unit": unit,
        "payments": payments,
        "tenant_history": tenant_history,
        "rent_history": rent_history,
        "outstanding_invoices": outstanding_invoices,
        "total_due": total_due,
        "total_paid": total_paid,
        "balance": balance,
    })

# =========================
# TENANT ASSIGNMENT
# =========================
@login_required
def assign_tenant_to_unit(request, unit_id, tenant_id):

    unit = get_object_or_404(Unit, id=unit_id)
    tenant = get_object_or_404(User, id=tenant_id, role="tenant")
    profile = get_object_or_404(TenantProfile, user=tenant)

    if request.method == "POST":

        if not is_tenant_onboarded(profile):
            messages.error(request, "Tenant must complete onboarding first")
            return redirect("unit_detail", unit.id)

        if unit.is_full():
            messages.error(request, "Unit is already full")
            return redirect("unit_detail", unit.id)

        # END OLD TENANCY
        old_history = UnitTenantHistory.objects.filter(
            tenant=tenant,
            is_current=True
        ).first()

        if old_history:
            old_history.end_tenancy()

        # ASSIGN UNIT
        profile.unit = unit
        profile.save()

        UnitTenantHistory.objects.create(
            unit=unit,
            tenant=tenant
        )

        # =========================
        # 🔥 FIX: CREATE INITIAL BILLING PROPERLY
        # =========================
        from payments.models import Invoice
        from django.utils import timezone

        today = timezone.now().date()
        month_start = today.replace(day=1)

        due_date = month_start.replace(day=2)

        first_invoice_exists = Invoice.objects.filter(
            tenant=tenant,
            unit=unit
        ).exists()

        if not first_invoice_exists:

            Invoice.objects.create(
                tenant=tenant,
                unit=unit,
                amount=unit.rent_amount + (unit.deposit or 0),
                due_date=due_date,
                status="pending"
            )

        messages.success(request, "Tenant assigned and billed successfully")
        return redirect("unit_detail", unit.id)

    return render(request, "properties/assign_tenant.html", {
        "unit": unit,
        "tenant": tenant
    })

@login_required
def select_tenants_for_unit(request, unit_id):
    unit = get_object_or_404(Unit, id=unit_id)

    tenants = User.objects.filter(role="tenant")

    tenant_data = []
    for tenant in tenants:
        profile = TenantProfile.objects.filter(user=tenant).first()

        tenant_data.append({
            "user": tenant,
            "profile": profile,
            "is_ready": is_tenant_onboarded(profile)
        })

    if request.method == "POST":
        selected_ids = request.POST.getlist("tenants")

        for tenant_id in selected_ids:
            tenant = User.objects.get(id=tenant_id)
            profile = TenantProfile.objects.filter(user=tenant).first()

            if not is_tenant_onboarded(profile):
                messages.error(request, f"{tenant.get_full_name()} is not onboarded")
                continue

            if profile and not unit.is_full():

                # ✅ END OLD TENANCY
                old_history = UnitTenantHistory.objects.filter(
                    tenant=tenant,
                    is_current=True
                ).first()
                if old_history:
                    old_history.end_tenancy()

                profile.unit = unit
                profile.save()

                UnitTenantHistory.objects.create(
                    unit=unit,
                    tenant=tenant
                )

                ActivityLog.objects.create(
                    user=request.user,
                    action="tenant_assigned_bulk",
                    description=f"{tenant.get_full_name()} assigned to Unit {unit.unit_number}"
                )

        messages.success(request, "Tenants assigned successfully")
        return redirect("unit_detail", unit.id)

    return render(request, "properties/select_tenants.html", {
        "unit": unit,
        "tenant_data": tenant_data
    })

@login_required
def assign_tenant_finalize(request, tenant_id, unit_id):

    tenant = get_object_or_404(User, id=tenant_id)
    unit = get_object_or_404(Unit, id=unit_id)

    profile = TenantProfile.objects.filter(user=tenant).first()

    if not profile:
        messages.error(request, "Tenant has no profile")
        return redirect("tenant_list")

    if not is_tenant_onboarded(profile):
        messages.error(request, "Tenant must complete onboarding first")
        return redirect("tenant_list")

    if request.method == "POST":

        profile.unit = unit
        profile.save()

        UnitTenantHistory.objects.create(
            unit=unit,
            tenant=tenant
        )

        # ✅ BILL IMMEDIATELY
        from payments.models import Invoice
        from django.utils import timezone

        today = timezone.now().date()
        due_date = today.replace(day=2)

        if not Invoice.objects.filter(tenant=tenant, unit=unit).exists():
            Invoice.objects.create(
                tenant=tenant,
                unit=unit,
                amount=unit.rent_amount + (unit.deposit or 0),
                due_date=due_date,
                status="pending"
            )

        messages.success(request, "Tenant assigned and billed successfully")
        return redirect("unit_detail", unit.id)

    return render(request, "properties/assign_tenant.html", {
        "unit": unit,
        "tenant": tenant
    })

# =========================
# EXIT FLOWS
# =========================

@login_required
def evict_tenant(request, tenant_id):

    tenant = get_object_or_404(User, id=tenant_id, role="tenant")
    profile = get_object_or_404(TenantProfile, user=tenant)

    if not profile.unit:
        messages.error(request, "Tenant is not assigned to any unit")
        return redirect("tenant_detail", tenant.id)

    unit = profile.unit

    if request.method == "POST":

        from properties.models import TenantExit

        TenantExit.objects.create(
            tenant=tenant,
            unit=unit,
            exit_type="eviction",
            reason=request.POST.get("reason"),
            notes=request.POST.get("notes"),
            inspection_notes=request.POST.get("inspection_notes"),
            inspection_image=request.FILES.get("inspection_image"),
            initiated_by=request.user
        )

        history = UnitTenantHistory.objects.filter(
            unit=unit,
            tenant=tenant,
            is_current=True
        ).first()

        if history:
            history.end_tenancy()

        profile.unit = None
        profile.save()

        ActivityLog.objects.create(
            user=request.user,
            action="tenant_evicted",
            description=f"{tenant.get_full_name()} evicted from Unit {unit.unit_number}"
        )

        messages.success(request, "Tenant evicted successfully")
        return redirect("tenant_detail", tenant.id)

    return render(request, "properties/evict_tenant.html", {
        "tenant": tenant,
        "unit": unit
    })


@login_required
def vacate_tenant(request, tenant_id):

    tenant = get_object_or_404(User, id=tenant_id, role="tenant")
    profile = get_object_or_404(TenantProfile, user=tenant)

    if not profile.unit:
        messages.error(request, "Tenant is not assigned to any unit")
        return redirect("tenant_detail", tenant.id)

    unit = profile.unit

    if request.method == "POST":

        from properties.models import TenantExit

        TenantExit.objects.create(
            tenant=tenant,
            unit=unit,
            exit_type="vacate",
            notes=request.POST.get("notes"),
            inspection_notes=request.POST.get("inspection_notes"),
            inspection_image=request.FILES.get("inspection_image"),
            initiated_by=request.user
        )

        history = UnitTenantHistory.objects.filter(
            unit=unit,
            tenant=tenant,
            is_current=True
        ).first()

        if history:
            history.end_tenancy()

        profile.unit = None
        profile.save()

        ActivityLog.objects.create(
            user=request.user,
            action="tenant_vacated",
            description=f"{tenant.get_full_name()} vacated Unit {unit.unit_number}"
        )

        messages.success(request, "Tenant vacated successfully")
        return redirect("tenant_detail", tenant.id)

    return render(request, "properties/vacate_tenant.html", {
        "tenant": tenant,
        "unit": unit
    })


@login_required
def tenant_vacate_self(request):

    if request.user.role != "tenant":
        return redirect("login")

    profile = get_object_or_404(TenantProfile, user=request.user)

    if not profile.unit:
        messages.error(request, "You are not assigned to any unit")
        return redirect("tenant_dashboard")

    unit = profile.unit

    if request.method == "POST":

        from properties.models import TenantExit

        TenantExit.objects.create(
            tenant=request.user,
            unit=unit,
            exit_type="vacate",
            notes=request.POST.get("notes"),
            initiated_by=request.user
        )

        history = UnitTenantHistory.objects.filter(
            unit=unit,
            tenant=request.user,
            is_current=True
        ).first()

        if history:
            history.end_tenancy()

        profile.unit = None
        profile.save()

        ActivityLog.objects.create(
            user=request.user,
            action="tenant_self_vacate",
            description=f"{request.user.get_full_name()} vacated Unit {unit.unit_number}"
        )

        messages.success(request, "You have successfully vacated")
        return redirect("tenant_dashboard")

    return render(request, "tenants/vacate_self.html", {
        "unit": unit
    })


@login_required
def inspection_history(request):

    if request.user.role not in ["landlord", "caretaker"]:
        return redirect("login")

    from properties.models import UnitInspection, TenantExit

    inspections = UnitInspection.objects.select_related("unit", "tenant").order_by("-created_at")
    exits = TenantExit.objects.select_related("unit", "tenant").order_by("-created_at")

    return render(request, "properties/inspection_history.html", {
        "inspections": inspections,
        "exits": exits
    })