from django.contrib.auth.decorators import login_not_required
import logging
from django.urls import reverse, reverse_lazy
from django.utils.decorators import method_decorator
from django.contrib.auth import login, authenticate
from django.http import HttpResponse
from django.shortcuts import redirect
from django.core.exceptions import PermissionDenied
from lariv.mixins import (
    ListViewMixin,
    DetailViewMixin,
    PostFormViewMixin,
    FormViewMixin,
    DeleteViewMixin,
    SelectionTableViewMixin,
)
from lariv.registry import ViewRegistry
from .models import User, Role

logger = logging.getLogger(__name__)


@ViewRegistry.register("users.UserList")
class UserList(ListViewMixin):
    model = User
    component = "users.UserTable"
    key = "users"

    def dispatch(self, request, *args, **kwargs):
        if not request.user.is_superuser:
            raise PermissionDenied("Only superusers can perform this action.")
        return super().dispatch(request, *args, **kwargs)


@ViewRegistry.register("users.UserView")
class UserView(DetailViewMixin):
    model = User
    component = "users.UserDetail"
    key = "user"

    def dispatch(self, request, *args, **kwargs):
        if not request.user.is_superuser:
            raise PermissionDenied("Only superusers can perform this action.")
        return super().dispatch(request, *args, **kwargs)


@ViewRegistry.register("users.UserCreate")
class UserCreate(PostFormViewMixin):
    model = User
    component = "users.UserCreateForm"
    key = "user"

    def dispatch(self, request, *args, **kwargs):
        if not request.user.is_superuser:
            raise PermissionDenied("Only superusers can perform this action.")
        return super().dispatch(request, *args, **kwargs)

    def get_success_url(self, obj):
        return reverse("users:detail", kwargs={"pk": obj.pk})


@ViewRegistry.register("users.UserUpdate")
class UserUpdate(PostFormViewMixin):
    model = User
    component = "users.UserUpdateForm"
    key = "user"

    def dispatch(self, request, *args, **kwargs):
        if not request.user.is_superuser:
            raise PermissionDenied("Only superusers can perform this action.")
        return super().dispatch(request, *args, **kwargs)

    def get_success_url(self, obj):
        return reverse("users:detail", kwargs={"pk": obj.pk})


@ViewRegistry.register("users.UserDelete")
class UserDelete(DeleteViewMixin):
    model = User
    component = "users.UserDeleteForm"
    key = "user"
    success_url = reverse_lazy("users:list")

    def dispatch(self, request, *args, **kwargs):
        if not request.user.is_superuser:
            raise PermissionDenied("Only superusers can perform this action.")
        return super().dispatch(request, *args, **kwargs)


@ViewRegistry.register("users.UserSelectionTable")
class UserSelectionTableView(SelectionTableViewMixin):
    model = User
    component = "users.UserSelectionTable"
    key = "users"

    def dispatch(self, request, *args, **kwargs):
        if not request.user.is_superuser:
            raise PermissionDenied("Only superusers can perform this action.")
        return super().dispatch(request, *args, **kwargs)


@ViewRegistry.register("users.UserMultiSelectionTable")
class UserMultiSelectionTableView(SelectionTableViewMixin):
    model = User
    component = "users.UserMultiSelectionTable"
    key = "users"

    def dispatch(self, request, *args, **kwargs):
        if not request.user.is_superuser:
            raise PermissionDenied("Only superusers can perform this action.")
        return super().dispatch(request, *args, **kwargs)


@ViewRegistry.register("users.RoleSelectionTable")
class RoleSelectionTableView(SelectionTableViewMixin):
    model = Role
    component = "users.RoleSelectionTable"
    key = "roles"

    def dispatch(self, request, *args, **kwargs):
        if not request.user.is_superuser:
            raise PermissionDenied("Only superusers can perform this action.")
        return super().dispatch(request, *args, **kwargs)


@ViewRegistry.register("users.ChangePassword")
class ChangePassword(FormViewMixin):
    model = User
    component = "users.ChangePasswordForm"
    key = "user"

    def dispatch(self, request, *args, **kwargs):
        if not request.user.is_superuser:
            raise PermissionDenied("Only superusers can perform this action.")
        return super().dispatch(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        user = self.get_object(kwargs.get("pk"))
        inputs = self.get_inputs()
        data = {comp.key: request.POST.get(comp.key) for comp in inputs}
        cleaned_data, errors = self.validate(data, inputs)

        new_password = cleaned_data.get("new_password")
        confirm_password = cleaned_data.get("confirm_password")

        if not errors and new_password != confirm_password:
            errors["confirm_password"] = "New passwords do not match."

        if errors:
            context = {"errors": errors, "user": user}
            return self.render_component(request, **context)

        user.set_password(new_password)
        user.save()
        return self.render_component(
            request, user=user, success="Password changed successfully!"
        )


@ViewRegistry.register("users.Login")
@method_decorator(login_not_required, name="dispatch")
class Login(FormViewMixin):
    model = User
    component = "users.LoginForm"
    key = "user"
    success_url = reverse_lazy("apps")

    def get(self, request, *args, **kwargs):
        # Redirect if already authenticated
        if request.user.is_authenticated:
            return redirect(self.success_url)
        return self.render_component(request=request)

    def post(self, request, *args, **kwargs):
        inputs = self.get_inputs()
        data = {comp.key: request.POST.get(comp.key) for comp in inputs}
        cleaned_data, errors = self.validate(data, inputs)

        username = cleaned_data.get("username", data.get("username"))
        password = cleaned_data.get("password", data.get("password"))

        if not errors:
            user = authenticate(request, username=username, password=password)
            if user is not None:
                login(request, user)
                if request.htmx:
                    return HttpResponse(
                        status=200,
                        headers={"HX-Redirect": self.success_url},
                    )
                return redirect(self.success_url)
            else:
                errors["Error"] = "Invalid email or password."

        # Re-render form with errors
        context = {"request": request, "errors": errors}
        for k, v in data.items():
            if v:
                context[k] = v
        return self.render_component(**context)


@ViewRegistry.register("users.Signup")
@method_decorator(login_not_required, name="dispatch")
class Signup(FormViewMixin):
    model = User
    component = "users.SignupForm"
    key = "user"
    success_url = reverse_lazy("apps")

    def get(self, request, *args, **kwargs):
        # Redirect if already authenticated
        if request.user.is_authenticated:
            return redirect(self.success_url)
        return self.render_component(request=request)

    def post(self, request, *args, **kwargs):
        inputs = self.get_inputs()
        data = {comp.key: request.POST.get(comp.key) for comp in inputs}
        cleaned_data, errors = self.validate(data, inputs)

        name = cleaned_data.get("name")
        email = cleaned_data.get("email")
        phone = cleaned_data.get("phone")
        password1 = cleaned_data.get("password1")
        password2 = cleaned_data.get("password2")
        terms_accepted = cleaned_data.get("terms_accepted")
        # Validate passwords match
        if password1 and password2 and password1 != password2:
            errors["password2"] = "Passwords do not match."
        # Validate terms accepted
        if not terms_accepted:
            errors["terms_accepted"] = "You must accept the terms and conditions."
        # Check for existing email/phone
        if email and User.objects.filter(email=email).exists():
            errors["email"] = "This email is already registered."
        if phone and User.objects.filter(phone=phone).exists():
            errors["phone"] = "This phone number is already registered."

        if not errors:
            # Create user with hashed password
            user = User(name=name, email=email, phone=phone)
            user.set_password(password1)
            user.save()
            # Log in the new user
            login(request, user)
            if request.htmx:
                return HttpResponse(
                    status=200,
                    headers={"HX-Redirect": self.success_url},
                )
            return redirect(self.success_url)

        # Re-render form with errors
        context = {"request": request, "errors": errors}
        for k, v in data.items():
            if v:
                context[k] = v
        return self.render_component(**context)
