"""
_____________________________________________________________________.

:PROJECT: LARAsuite

*lara_django_base views *

:details: lara_django_base views module.
         - add app specific urls here
         -
:authors: mark doerr <mark.doerr@uni-greifswald.de>

________________________________________________________________________
"""

# from configparser import ConfigParser, NoOptionError, NoSectionError # this might be obsolete
from dataclasses import dataclass, field

import environ
from django import __version__ as django_version
from django.apps import apps
from django.conf import settings
from django.contrib.auth.forms import UserCreationForm
from django.http import HttpResponseRedirect
from django.shortcuts import redirect, render
from django.urls import reverse_lazy
from django.views import generic
from django.views.generic import CreateView, DeleteView, DetailView, TemplateView, UpdateView
from django_tables2 import SingleTableView
from lara_django_people.views import PeopleMenu
from lara_django_projects.models import Project

from . import __version__
from .forms import AddressCreateForm, AddressUpdateForm
from .models import Address
from .tables import AddressTable
from .views_mixins import HtmxResponseMixin


@dataclass
class ItemMenu:
    """Container for simple top-level menu items."""

    menu_items: list[dict] = field(
        default_factory=lambda: [
            {"name": "item1", "path": "lara_django_base:view1-name"},
            {"name": "item2", "path": "lara_django_base:view2-name"},
        ]
    )

@dataclass
class SidebarMenu:
    """Container for sidebar navigation items."""

    menu_items: list[dict] = field(
        default_factory=lambda: [
            {"name": "Home", "path": "/", "icon": "home", "hover_class": "hover:bg-gray-500"},
            {"name": "Dashboard", "path": "/dashboard/", "icon": "dashboard", "hover_class": "hover:bg-gray-500"},
            {"name": "Apps", "path": "/apps/", "icon": "apps", "hover_class": "hover:bg-gray-500"},
            {"name": "Projects", "path": "/projects/", "icon": "projects", "hover_class": "hover:bg-red-500"},
            {"name": "Processes", "path": "/processes/", "icon": "processes", "hover_class": "hover:bg-orange-500"},
            {"name": "Data", "path": "/data/", "icon": "data", "hover_class": "hover:bg-sky-500"},
            {
                "name": "Devices",
                "path": "/material-store/device/list/",
                "icon": "devices",
                "hover_class": "hover:bg-amber-500",
            },
            {
                "name": "Parts",
                "path": "/material-store/part/list/",
                "icon": "parts",
                "hover_class": "hover:bg-amber-500",
            },
            {
                "name": "Labware",
                "path": "/material-store/labware/list/",
                "icon": "labware",
                "hover_class": "hover:bg-amber-500",
            },
            {
                "name": "Substances",
                "path": "/substances/",
                "icon": "substances",
                "hover_class": "hover:bg-teal-500",
            },
            {"name": "Organisms", "path": "/organisms-store/", "icon": "organisms", "hover_class": "hover:bg-lime-500"},
            {"name": "People", "path": "/people/", "icon": "people", "hover_class": "hover:bg-blue-500"},
        ]
    )


class BaseTemplateSettingsMixin:
    """Mixin to provide common template settings for project views."""

    def get_context_data(self, **kwargs):  # noqa: D102
        context = super().get_context_data(**kwargs)
        projects = Project.objects.exclude(parent=None)
        context["projects"] = projects
        context["projects_latest"] = projects.order_by("-datetime_last_modified")  # projects_latest
        context["menu_items"] = []  # ItemMenu().menu_items
        context["app_color"] = "gray"
        context["sidebar_menu_items"] = SidebarMenu().menu_items
        # context["sparql_server_url"] = f"http://{settings.VIRTUOSO_HOST}:{settings.VIRTUOSO_ADMIN_PORT}/sparql/"

        return context


def app_version(app):
    """Return the version of a Django app module when available."""
    try:
        return __import__(app).__version__
    except AttributeError:
        return "version unknown"


env = environ.Env(
    # set casting, default value
    DEBUG=(bool, False)
)


def select_home_view(request):
    """Redirect the current user to their configured home screen."""
    # get the user, who is currently logged in

    current_user = request.user

    # TODO: might be obsolete, as the home screen url is now stored in the user model and not in the session
    # user = {
    #     "current_user": current_user,
    #     "authenticated": current_user.is_authenticated,
    #     "home_screen_url": current_user.home_screen_url,
    # }

    # context = {
    #     "user": user,
    # }

    defaut_home_screen_url = (
        current_user.home_screen_url
        if current_user.home_screen_url is not None and current_user.home_screen_url != ""
        else "lara_django_base:dashboard"
    )

    return redirect(defaut_home_screen_url)


class EmbeddedUIView(BaseTemplateSettingsMixin, TemplateView):
    """
    Generic view that embeds an external service in an iframe.

    Configure per URL via ``as_view(embed_url="http://...", title="My Service")``.
    htmx requests receive only the iframe partial; full-page requests get the
    shell template that triggers the htmx load automatically.
    """

    template_name = "lara_django_base/embedded_ui.html"
    embed_url: str = ""
    title: str = ""

    def get_template_names(self) -> list[str]:
        """
        Return the iframe partial for direct htmx requests, the full shell otherwise.

        hx-boost sets both HX-Request and HX-Boosted; the div's hx-get sets only
        HX-Request.  Boosted navigation must still receive the full shell so that
        the layout (navbar, sidebar, …) is preserved.
        """
        is_htmx = self.request.headers.get("HX-Request")
        is_boosted = self.request.headers.get("HX-Boosted")
        if is_htmx and not is_boosted:
            return ["lara_django_base/partials/iframe.html"]
        return [self.template_name]

    def get_context_data(self, **kwargs) -> dict:
        """Inject embed URL and title into the template context."""
        context = super().get_context_data(**kwargs)
        context["embed_url"] = self.embed_url
        context["title"] = self.title
        return context


class DrawerProjectsPartialView(TemplateView):
    """
    Htmx-only partial that renders the project navigation tree for the drawer.

    Returns HTTP 400 for plain (non-htmx) requests so the endpoint is not
    accidentally used as a full page.
    """

    template_name = "lara_django_base/partials/drawer_projects.html"

    def get(self, request, *args, **kwargs):
        """Enforce htmx-only access and return the project tree partial."""
        if not request.headers.get("HX-Request"):
            from django.http import HttpResponseBadRequest

            return HttpResponseBadRequest("htmx request required")
        return super().get(request, *args, **kwargs)

    def get_context_data(self, **kwargs) -> dict:
        """Load the project tree for the drawer partial."""
        context = super().get_context_data(**kwargs)
        context["projects"] = Project.objects.exclude(parent=None)
        return context



def add_data_monitor(request):
    """Handle data monitor form submissions."""
    if request.method == "POST":
        # Handle the form submission
        pass
    return render(request, "404.html")

class Dashboard(HtmxResponseMixin, BaseTemplateSettingsMixin, TemplateView):
    """Dashboard class view."""

    partial_template_name = "lara_django_base/partials/dashboard_content.html"
    page_title = "LARA Dashboard"

    def get_context_data(self, **kwargs):  # noqa: D102
        context = super().get_context_data(**kwargs)
        context["title"] = "Dashboard"
        return context


def _collect_lara_apps() -> list[dict]:
    """Collect and sort all installed LARA app descriptors."""
    lara_apps: list[dict] = []
    for app in apps.get_app_configs():
        try:
            lara_apps.append(
                {
                    "name": app.verbose_name_short,
                    "description": app.lara_app_description,
                    "icon": app.lara_app_icon,
                    "color": app.lara_app_color,
                    "class_apps": app.lara_class_apps,
                    "instance_apps": app.lara_instance_apps,
                }
            )
        except AttributeError:
            pass
    return sorted(lara_apps, key=lambda a: a["name"])


class AppsSelector(HtmxResponseMixin, BaseTemplateSettingsMixin, TemplateView):
    """Apps selector page — cards are lazy-loaded via a nested htmx request."""

    partial_template_name = "lara_django_base/partials/apps_content.html"
    page_title = "LARA Apps"

    def get_context_data(self, **kwargs) -> dict:
        """Return context for the apps page."""
        context = super().get_context_data(**kwargs)
        context["sparql_server_url"] = (
            f"http://{settings.VIRTUOSO_HOST}:{settings.VIRTUOSO_ADMIN_PORT}/sparql/"
        )
        return context


class AppsSelectorPartialView(TemplateView):
    """
    Htmx-only partial that returns the rendered list of app cards.

    Returns HTTP 400 for plain (non-htmx) requests.
    """

    template_name = "lara_django_base/partials/apps_list.html"

    def get(self, request, *args, **kwargs):
        """Enforce htmx-only access and return the apps-card partial."""
        if not request.headers.get("HX-Request"):
            from django.http import HttpResponseBadRequest

            return HttpResponseBadRequest("htmx request required")
        return super().get(request, *args, **kwargs)

    def get_context_data(self, **kwargs) -> dict:
        """Load sorted LARA app descriptors for the cards partial."""
        context = super().get_context_data(**kwargs)
        context["apps"] = _collect_lara_apps()
        return context


class Home(TemplateView):
    # class HomeMenu(TemplateView):
    """Home page view."""

    template_name = "lara_django_base/index.html"

    login_url = "accounts/login"

    def get_context_data(self, **kwargs):
        """Return context for the home page."""
        context = super().get_context_data(**kwargs)
        context["menu_items"] = [  # {'name': 'Material', 'path': 'lara_django_material:part-list'},
            #  {'name': 'Devices',
            #      'path': 'lara_django_material:device-list'},
            #  {'name': 'Part',
            #      'path': 'lara_django_material:part-list'},
            #  {'name': 'Labware',
            #   'path': 'lara_django_material:labware-list'},
            #  {'name': 'Substances',
            #   'path': 'lara_django_material:labware-list'}
        ]
        # context['sparql_server_url'] = f'http://{settings.VIRTUOSO_HOST}:{settings.VIRTUOSO_ADMIN_PORT}/sparql/'
        return context


class AboutView(HtmxResponseMixin, BaseTemplateSettingsMixin, TemplateView):
    """About page view."""

    partial_template_name = "lara_django_base/partials/about_content.html"
    page_title = "About LARA"

    def get_context_data(self, **kwargs):
        """Return context for the about page."""
        context = super().get_context_data(**kwargs)

        django_env = env("DJANGO_SETTINGS_MODULE")

        django_envs = {
            "lara_django.settings.development": "DEVELOPMENT",
            "lara_django.settings.production": "PRODUCTION",
            "lara_django.settings.staging": "STAGING",
        }

        try:
            django_environment = django_envs[django_env]
        except KeyError:
            django_environment = "UNKNOWN"

        # context["apps"] =

        context["lara_env"] = {
            "lara_version": __version__,
            "django_version": django_version,
            "lara_description": "The LARA-django is the comprehensive science database for the LARA suite",
            "django_environment": django_environment,
            "django_settings": django_env,
            "lara_authors": ["mark doerr (mark.doerr@uni-greifswald.de)", "benjamin lear"],
            "apps": [{"name": app, "version": app_version(app)} for app in settings.INSTALLED_APPS],
        }
        return context


class ContactView(HtmxResponseMixin, BaseTemplateSettingsMixin, TemplateView):
    """Contact page view."""

    partial_template_name = "lara_django_base/partials/contact_content.html"
    page_title = "Contact"

    def get_context_data(self, **kwargs):
        """Return context for the contact page."""
        context = super().get_context_data(**kwargs)
        return context


class SignUp(generic.CreateView):
    """User signup view."""

    form_class = UserCreationForm
    success_url = reverse_lazy("login")
    template_name = "signup.html"


class AddressDetailView(DetailView):
    """Detail view for a single address."""

    model = Address

    template_name = "lara_django_people/address_detail.html"

    def get_context_data(self, **kwargs):
        """Return context for the address detail page."""
        context = super().get_context_data(**kwargs)
        context["section_title"] = "Address - Details"
        context["update_link"] = "lara_django_people:address-update"
        context["menu_items"] = PeopleMenu().menu_items
        return context


class AddressesListView(SingleTableView):
    """Table view listing all addresses."""

    model = Address
    table_class = AddressTable

    template_name = "lara_django_people/list.html"

    def get_context_data(self, **kwargs):
        """Return context for the address list page."""
        context = super().get_context_data(**kwargs)
        context["section_title"] = "Addresses - List"
        context["create_link"] = "lara_django_people:address-create"
        context["menu_items"] = PeopleMenu().menu_items
        return context


class AddressCreateView(CreateView):
    """Create view for a new address."""

    model = Address
    template_name = "lara_django_people/create_form.html"
    form_class = AddressCreateForm
    success_url = "/people/addresses/list"

    def get_context_data(self, **kwargs):
        """Return context for the address creation page."""
        context = super().get_context_data(**kwargs)
        context["section_title"] = "Address - Creation"
        return context

    def form_valid(self, form):
        """Handle valid form submission for address creation."""
        print("**** form val")
        if "cancel" in self.request.POST:
            return HttpResponseRedirect(self.get_success_url())
        return super().form_valid(form)


class AddressUpdateView(UpdateView):
    """Update view for an existing address."""

    model = Address
    template_name = "lara_django_people/update_form.html"
    form_class = AddressUpdateForm
    success_url = "/people/addresses/list"

    def get_context_data(self, **kwargs):
        """Return context for the address update page."""
        context = super().get_context_data(**kwargs)
        context["section_title"] = "Address - Update"
        context["delete_link"] = "lara_django_people:address-delete"

        return context


class AddressDeleteView(DeleteView):
    """Delete view for an existing address."""

    model = Address
    template_name = "lara_django_people/delete_form.html"
    success_url = "/people/addresses/list"

    def get_context_data(self, **kwargs):
        """Return context for the address delete page."""
        context = super().get_context_data(**kwargs)
        context["section_title"] = "Address - Delete"
        context["delete_link"] = "lara_django_people:address-delete"
        return context
