# Copyright © The Debusine Developers
# See the AUTHORS file at the top-level directory of this distribution
#
# This file is part of Debusine. It is subject to the license terms
# in the LICENSE file found in the top-level directory of this
# distribution. No part of Debusine, including this file, may be copied,
# modified, propagated, or distributed except according to the terms
# contained in the LICENSE file.

"""UI helpers for authentication models."""

from functools import cached_property

from django.core.exceptions import ImproperlyConfigured

from debusine.db.context import context
from debusine.db.models import Group, User
from debusine.db.models.auth import GroupMembership
from debusine.web.views.places import (
    PlaceValue,
    ResourceMainPlace,
    ResourceSubPlace,
)
from debusine.web.views.ui.base import UI


class UserUI(UI[User]):
    """UI helpers for User instances."""

    @cached_property
    def place(self) -> ResourceMainPlace[User]:
        """Return a place to show this user."""
        if full_name := self.instance.get_full_name():
            description = f"User {full_name} <{self.instance.username}>"
        else:
            description = f"User <{self.instance.username}>"
        place = ResourceMainPlace(
            ui=self,
            title=PlaceValue(
                self.instance.username,
                page=self.instance.get_full_name() or self.instance.username,
            ),
            url=self.instance.get_absolute_url(),
            description=description,
        )
        if context.scope is not None:
            place.parent = context.scope.ui(self.request).place
        return place


class GroupUI(UI[Group]):
    """UI helpers for Group instances."""

    @cached_property
    def place(self) -> ResourceMainPlace[Group]:
        """Return a place to show this group."""
        if not self.request.user.is_authenticated:
            raise ImproperlyConfigured(
                "GroupUI.place invoked by an anonymous user"
            )

        scope_ui = context.require_scope().ui(self.request)
        return ResourceMainPlace(
            ui=self,
            title=PlaceValue(
                self.instance.name_without_scope,
                page=f"Group {self.instance}",
                scoped=str(self.instance),
            ),
            url=self.instance.get_absolute_url(),
            parent=scope_ui.place_group_list,
        )

    @cached_property
    def place_audit_log(self) -> ResourceSubPlace[Group]:
        """Return a place to show this group's audit log."""
        return ResourceSubPlace(
            ui=self,
            title=PlaceValue(
                "audit log", page=f"Audit log for {self.instance}"
            ),
            url=self.instance.get_absolute_url_audit_log(),
            parent=self.place,
        )


class GroupMembershipUI(UI[GroupMembership]):
    """UI helpers for GroupMembership instances."""

    @cached_property
    def place_update(self) -> ResourceMainPlace[GroupMembership]:
        """Return a place to update this group membership."""
        group_ui = self.instance.group.ui(self.request)
        return ResourceMainPlace(
            ui=self,
            title=PlaceValue(
                str(self.instance),
                page=f"Manage membership of {self.instance.user}"
                f" in {self.instance.group}",
            ),
            url=self.instance.get_absolute_url_update(),
            parent=group_ui.place,
        )

    @cached_property
    def place_remove(self) -> ResourceSubPlace[GroupMembership]:
        """Return a place to remove this group membership."""
        group_ui = self.instance.group.ui(self.request)
        return ResourceSubPlace(
            ui=self,
            title=PlaceValue(
                str(self.instance),
                page=f"Remove {self.instance.user} from {self.instance.group}",
            ),
            url=self.instance.get_absolute_url_remove(),
            parent=group_ui.place,
        )
