from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.core.exceptions import PermissionDenied
from django.db import transaction
from django.shortcuts import get_object_or_404, redirect, render

from accounts.permissions import admin_required, any_authenticated
from core.project_utils import get_current_project
from flats.forms import BuildingForm, FloorForm, FlatForm
from flats.models import Building, Floor, Flat


def _current_project(request):
    return get_current_project(request)


def _project_flat(pk, project):
    return get_object_or_404(Flat, pk=pk, floor__building__project=project)


@login_required
@any_authenticated
def flat_list(request):
    project = _current_project(request)
    buildings = Building.objects.filter(project=project).prefetch_related("floors__flats__owner") if project else Building.objects.none()
    return render(request, "flats/flat_list.html", {"buildings": buildings, "project": project})


@login_required
@admin_required
def building_create(request):
    project = _current_project(request)
    if not project:
        return redirect("dashboard:home")
    form = BuildingForm(request.POST or None)
    if request.method == "POST" and form.is_valid():
        building = form.save(commit=False)
        building.project = project
        building.created_by = request.user
        building.updated_by = request.user
        building.save()
        messages.success(request, f"Building '{building.name}' was added.")
        return redirect("flats:flat_list")
    return render(request, "flats/building_form.html", {"form": form, "project": project, "title": "Add Building"})


@login_required
@admin_required
def building_edit(request, pk):
    project = _current_project(request)
    building = get_object_or_404(Building, pk=pk, project=project)
    form = BuildingForm(request.POST or None, instance=building)
    if request.method == "POST" and form.is_valid():
        building = form.save(commit=False)
        building.updated_by = request.user
        building.save()
        messages.success(request, "Building updated successfully.")
        return redirect("flats:flat_list")
    return render(request, "flats/building_form.html", {"form": form, "project": project, "title": "Edit Building", "building": building})


@login_required
@admin_required
def building_delete(request, pk):
    project = _current_project(request)
    building = get_object_or_404(Building, pk=pk, project=project)
    if request.method == "POST":
        if building.floors.filter(flats__isnull=False).exists():
            messages.error(request, "This building contains flats. Delete its flats/floors first.")
        else:
            building.delete()
            messages.success(request, "Building deleted successfully.")
        return redirect("flats:flat_list")
    return render(request, "flats/confirm_delete.html", {"object": building, "object_type": "building", "project": project})


@login_required
@admin_required
def floor_create(request, building_pk):
    project = _current_project(request)
    building = get_object_or_404(Building, pk=building_pk, project=project)
    form = FloorForm(request.POST or None)
    if request.method == "POST" and form.is_valid():
        floor = form.save(commit=False)
        floor.building = building
        floor.save()
        messages.success(request, f"Floor '{floor.floor_name}' was added to {building.name}.")
        return redirect("flats:flat_list")
    return render(request, "flats/floor_form.html", {"form": form, "building": building, "project": project, "title": "Add Floor"})


@login_required
@admin_required
def floor_edit(request, pk):
    project = _current_project(request)
    floor = get_object_or_404(Floor, pk=pk, building__project=project)
    form = FloorForm(request.POST or None, instance=floor)
    if request.method == "POST" and form.is_valid():
        form.save()
        messages.success(request, "Floor updated successfully.")
        return redirect("flats:flat_list")
    return render(request, "flats/floor_form.html", {"form": form, "building": floor.building, "project": project, "title": "Edit Floor", "floor": floor})


@login_required
@admin_required
def floor_delete(request, pk):
    project = _current_project(request)
    floor = get_object_or_404(Floor, pk=pk, building__project=project)
    if request.method == "POST":
        if floor.flats.exists():
            messages.error(request, "This floor contains flats. Delete the flats first.")
        else:
            floor.delete()
            messages.success(request, "Floor deleted successfully.")
        return redirect("flats:flat_list")
    return render(request, "flats/confirm_delete.html", {"object": floor, "object_type": "floor", "project": project})


@login_required
@admin_required
def flat_create(request, floor_pk):
    project = _current_project(request)
    floor = get_object_or_404(Floor, pk=floor_pk, building__project=project)
    form = FlatForm(request.POST or None)
    if request.method == "POST" and form.is_valid():
        flat = form.save(commit=False)
        flat.floor = floor
        flat.created_by = request.user
        flat.updated_by = request.user
        flat.save()
        messages.success(request, f"Unit {flat.flat_no} was added.")
        return redirect("flats:flat_list")
    return render(request, "flats/flat_form.html", {"form": form, "floor": floor, "project": project, "title": "Add Flat / Unit"})


@login_required
@admin_required
def flat_edit(request, pk):
    project = _current_project(request)
    flat = _project_flat(pk, project)
    form = FlatForm(request.POST or None, instance=flat)
    if request.method == "POST" and form.is_valid():
        flat = form.save(commit=False)
        flat.updated_by = request.user
        flat.save()
        messages.success(request, f"Unit {flat.flat_no} updated successfully.")
        return redirect("flats:flat_list")
    return render(request, "flats/flat_form.html", {"form": form, "floor": flat.floor, "project": project, "title": "Edit Flat / Unit", "flat": flat})


@login_required
@admin_required
def flat_delete(request, pk):
    project = _current_project(request)
    flat = _project_flat(pk, project)
    if request.method == "POST":
        if hasattr(flat, "sale"):
            messages.error(request, "This unit has a sale record. Delete/cancel the sale first.")
        else:
            flat.delete()
            messages.success(request, "Flat/unit deleted successfully.")
        return redirect("flats:flat_list")
    return render(request, "flats/confirm_delete.html", {"object": flat, "object_type": "flat/unit", "project": project})
