"""Top-level views module.

After refactor this file only keeps the minimal public view entry points and imports
helpers from the new `directory` and `image` modules. Also provides the
`toggle_settings` view used by template buttons to persist theme/sort.
"""

# Django imports.
from urllib.parse import urlparse
from django.http import HttpResponseNotFound
from django.conf import settings
from django.contrib.auth.decorators import login_required
from django.shortcuts import redirect
from django.core.exceptions import MultipleObjectsReturned

# Local helpers split into modules
from .directory import render_directory
from .image import render_image

from .models import UserSettings


SPECIALS = ['favorites', 'most-visited', 'recent']


@login_required
def index(request):
    return redirect("gallery_view_root")


@login_required
def gallery_view(request, path=None):
    """
    Shows a list of subdirectories and image files inside the given path.
    The path should be inside the GALLERY_ROOT path, otherwise a 404 error will be thrown.
    """

    root = settings.GALLERY_ROOT.resolve()

    try:
        candidate = root.joinpath(path).resolve() if path is not None else root
        candidate.relative_to(root)
    except Exception:
        return HttpResponseNotFound("Not found")

    if not candidate.exists():
        return HttpResponseNotFound("Not found")

    path_text = path if path is not None else ""

    if candidate.is_dir():
        return render_directory(request, path_text, candidate)

    return render_image(request, path_text, candidate)


@login_required
def special_gallery_view(request, gallery, path=None):
    """
    Shows a list of subdirectories and image files inside the given special gallery.
    Available special galleries are: (1) favorites; (2) most visited; (3) recently visited.
    """

    root = settings.GALLERY_ROOT.resolve()

    if gallery not in SPECIALS:
        return HttpResponseNotFound("Not found")

    try:
        candidate = root.joinpath(path).resolve() if path is not None else root
        candidate.relative_to(root)
    except Exception:
        return HttpResponseNotFound("Not found")

    path_text = path if path is not None else ""

    if path is not None:
        # Special galleries only have a logical root directory.
        # When there is a valid sub-directory path inside the gallery root
        # in the request then redirect to the base special gallery.
        if candidate.is_dir():
            return redirect('special_gallery_view_path', gallery, None, permanent=True)

    else:
        # When there is no path to render, then go to the corresponding special gallery root.
        return render_directory(request, path_text, candidate, gallery)

    # Fail if the requested image doesn' exist.
    if not candidate.exists():
        return HttpResponseNotFound("Not found")

    # Images are rendered normally, with a control to ensure the back, next and previous buttons
    # use the special gallery.
    return render_image(request, path_text, candidate, gallery)


@login_required
def toggle_settings(request):
    """Persist theme and/or sort for the current user and redirect back.

    Expected query params:
    - next: the URL to redirect back to (optional)
    - theme: optional, 'light' or 'dark'
    - sort: optional, one of allowed sort keys

    The view will obtain or create the UserSettings row for the user and set
    any provided values. If multiple UserSettings rows exist (shouldn't
    normally happen) the first is used.
    """

    next_url = request.GET.get("next") or "/gallery/"

    # Only allow in-site redirects for safety
    parsed = urlparse(next_url)
    if parsed.netloc and parsed.netloc != "":
        next_url = "/gallery/"

    user = getattr(request, "user", None)
    if not user or not getattr(user, "is_authenticated", False):
        return redirect(next_url)

    # Obtain or create the settings row
    try:
        settings_obj = UserSettings.objects.get(user=user)
    except UserSettings.DoesNotExist:
        settings_obj = UserSettings(user=user)
    except MultipleObjectsReturned:
        settings_obj = UserSettings.objects.filter(user=user).first()

    # Apply provided values
    theme = request.GET.get("theme")
    sort = request.GET.get("sort")

    if theme in ("light", "dark"):
        settings_obj.theme = theme

    if sort:
        settings_obj.sort = sort

    settings_obj.save()

    return redirect(next_url)
