import logging
from django.views import View
from django.http import HttpResponse
from lariv.mixins import BaseView
from lariv.registry import EnvironmentRegistry
from . import ui  # noqa: F401
from django.conf import settings
from django.apps import apps
from django.contrib.auth.decorators import login_not_required
from pwa.views import (
    manifest as pwa_manifest,
    offline as pwa_offline,
    service_worker as pwa_service_worker,
)
from lariv.registry import ViewRegistry, ConfigRegistry
from django.views.generic.base import RedirectView


logger = logging.getLogger(__name__)


service_worker = login_not_required(pwa_service_worker)
manifest = login_not_required(pwa_manifest)
offline = login_not_required(pwa_offline)


@ViewRegistry.register("lariv.IndexRedirectView")
class IndexRedirectView(RedirectView):
    pattern_name = "apps"
    permanent = True


@ViewRegistry.register("lariv.AppsPage")
class AppsPage(BaseView):
    component = "lariv.AppsPage"

    def get(self, request, *args, **kwargs):
        response = super().get(request, *args, **kwargs)
        if request.htmx and request.htmx.target:
            response["HX-Reswap"] = "outerHTML"
        return response

    def prepare_data(self, request, **kwargs):
        apps_dict = {}
        for app in settings.ENABLED_APPS:
            try:
                try:
                    app_config = ConfigRegistry.get(app)
                except ValueError:
                    app_config = apps.get_app_config(app)

                if not request.user.is_superuser:
                    if hasattr(app_config, "roles"):
                        if request.user.role.name not in app_config.roles:
                            continue

                url_prefix = getattr(app_config, "url_prefix", None)
                apps_dict[app] = {
                    "verbose_name": app_config.verbose_name,
                    "icon": getattr(app_config, "icon", "cube"),
                    "url": f"/app/{url_prefix}/" if url_prefix else "#",
                    "p_type": getattr(app_config, "p_type", None),
                }
            except Exception as e:
                logger.error(f"Error getting app config for {app}: {e}")
                continue
        return {
            "apps": apps_dict,
        }


@ViewRegistry.register("lariv.ComingSoon")
class ComingSoonPage(BaseView):
    component = "lariv.ComingSoon"

    def get(self, request, *args, **kwargs):
        response = super().get(request, *args, **kwargs)
        if request.htmx and request.htmx.target:
            response["HX-Reswap"] = "outerHTML"
        return response


@ViewRegistry.register("lariv.EnvironmentUpdateView")
class EnvironmentUpdateView(View):
    """
    View to update environment session values.
    Handles POST requests from environment field dropdowns.
    Returns the updated environment panel HTML for HTMX swap.
    """

    def post(self, request, *args, **kwargs):
        # Get the referer to determine which app we're in
        referer = request.META.get("HTTP_REFERER", "")
        app_name = self._extract_app_from_referer(referer)

        if not app_name:
            # Try to get from request header
            app_name = request.headers.get("X-App-Name", "")

        # Get all environment classes to find the field being updated
        all_envs = EnvironmentRegistry.all()

        # Process each POST field
        for key, value in request.POST.items():
            if key.startswith("env_"):
                continue  # Skip hidden fields

            # Find which environment has this field
            for env_key, env_class in all_envs.items():
                env_instance = env_class(request)
                for (
                    field_name,
                    field,
                ) in env_instance.get_fields().items():
                    if field.session_key == key:
                        if value:
                            try:
                                obj = field.model.objects.get(pk=value)
                                field.set_value_in_session(request.session, obj)
                            except field.model.DoesNotExist:
                                field.set_value_in_session(request.session, None)
                        else:
                            field.set_value_in_session(request.session, None)
                        break

        # Redirect to the environment's configured redirect_url
        # to avoid "object not found" errors on detail/edit views
        env_class = EnvironmentRegistry.get_for_app(app_name)
        redirect_url = None

        if env_class:
            redirect_url = env_class.get_redirect_url()

        if redirect_url:
            response = HttpResponse()
            response["HX-Redirect"] = str(redirect_url)
            return response

        # Fallback: refresh the page
        response = HttpResponse()
        response["HX-Refresh"] = "true"
        return response

    def _extract_app_from_referer(self, referer):
        """Extract app name from referer URL like /app/batches/..."""
        import re

        match = re.search(r"/app/([^/]+)/", referer)
        if match:
            return match.group(1)
        return None
