"""
Image-related rendering helpers for the gallery image view.
"""

# Standard library imports.
from pathlib import Path
import datetime

# Django imports.
from django.http import HttpResponseNotFound
from django.shortcuts import render
from django.conf import settings
from django.utils import timezone

# Third-party
from PIL import Image

# Project imports.
from .models import Image as Im

from .common import (
    normalize_sort,
    normalize_theme,
    build_query,
    gallery_url,
    append_query,
    sort_images,
    build_sort_options,
    build_breadcrumbs,
    get_first_image_thumbnail_url,
    is_image_file,
    make_thumbnail,
)
from .specials import get_special_paths, special_name


def render_image(request, path_text, full_path, special=None):
    """
    Renders the view corresponding to an image file.
    """

    try:
        img = Im.objects.get(path=full_path, user=request.user)

        if request.method == "POST":
            img.favorite = not img.favorite

    except Im.DoesNotExist:
        img = Im(path=full_path, user=request.user)

    finally:
        img.last_visited = timezone.now()
        img.visits = img.visits + 1
        img.save()

    # Search remains a GET parameter. For sort and theme prefer explicit
    # GET parameters when present, otherwise fall back to middleware-provided
    # settings on the request.
    search_text = request.GET.get("search", "").strip()
    sort_key = normalize_sort(
        request.GET.get("sort") or getattr(request, "sort", None) or "abc"
    )
    theme = normalize_theme(
        request.GET.get("theme") or getattr(request, "theme", None) or "dark"
    )
    query_state = build_query(search_text)

    image = Path("/imgs/").joinpath(path_text)
    img_dir = full_path.parent

    if special is not None:
        # Use the special gallery ordering for prev/next navigation
        images_sorted = get_special_paths(request.user, special)
        # If favorites, respect client sort; otherwise keep DB ordering
        if special == "favorites":
            images_sorted = sort_images(images_sorted, sort_key)
    else:
        try:
            entries = [
                entry
                for entry in img_dir.iterdir()
                if entry.is_file() and not entry.is_symlink() and is_image_file(entry)
            ]
        except OSError:
            return HttpResponseNotFound("Not found")

        # Sort siblings according to requested sort mode
        images_sorted = sort_images(entries, sort_key)

    # Find index of current image within the resolved list
    try:
        index = next(i for i, p in enumerate(images_sorted) if p.name == full_path.name)
    except StopIteration:
        return HttpResponseNotFound("Not found")

    prev_path = images_sorted[index - 1] if index > 0 else None
    next_path = images_sorted[index + 1] if index < len(images_sorted) - 1 else None

    # Helper to produce thumb url for a Path or None
    def thumb_for(path_obj):
        if path_obj is None:
            return None
        try:
            make_thumbnail(path_obj)
            rel = path_obj.relative_to(settings.GALLERY_ROOT)
            thumb_path = settings.THUMBNAILS_ROOT.joinpath(rel)
            if thumb_path.exists():
                return "/thumbs/" + str(rel).replace("\\", "/")
        except Exception:
            pass
        return None

    # Build URLs (preserving query state)
    prev_url = None
    next_url = None
    if prev_path is not None:
        rel = prev_path.relative_to(settings.GALLERY_ROOT)
        # When viewing from a special gallery, route prev/next through the
        # special gallery URL so subsequent navigation preserves the special
        # gallery context. Otherwise use the normal gallery URL for the file.
        if special is not None:
            rel_text = str(rel).replace("\\", "/")
            prev_url = append_query(f"/gallery/{special}/{rel_text}/", query_state)
        else:
            prev_url = gallery_url(rel, False, query_state)

    if next_path is not None:
        rel = next_path.relative_to(settings.GALLERY_ROOT)
        if special is not None:
            rel_text = str(rel).replace("\\", "/")
            next_url = append_query(f"/gallery/{special}/{rel_text}/", query_state)
        else:
            next_url = gallery_url(rel, False, query_state)

    # Back (directory) and Home (root) links and thumbnails
    dir_rel = None
    try:
        # derive directory path text relative to gallery root
        dir_rel = full_path.parent.relative_to(settings.GALLERY_ROOT)
        dir_text = str(dir_rel).replace("\\", "/")
    except Exception:
        dir_text = ""

    # Back (directory) and Home (root) links and thumbnails
    # For special galleries we still want to show a Back link that points
    # to the special gallery root — populate `back_thumb` with the
    # thumbnail of the first image in that special gallery so the UI can
    # display a representative image. For non-special views keep the
    # existing behavior (thumbnail for parent directory).
    if special is not None:
        back_url = None
        # images_sorted is already the special list in the requested order
        try:
            first_image = images_sorted[0] if len(images_sorted) > 0 else None
            back_thumb = thumb_for(first_image)
        except Exception:
            back_thumb = None
    else:
        back_url = gallery_url(
            Path(dir_text) if dir_text != "" else None, True, query_state
        )
        back_thumb = get_first_image_thumbnail_url(full_path.parent)
    home_url = gallery_url(None, True, query_state)
    home_thumb = get_first_image_thumbnail_url(settings.GALLERY_ROOT)

    # Prev/next thumbnails
    prev_thumb = thumb_for(prev_path)
    next_thumb = thumb_for(next_path)

    # Image metadata
    width = height = None
    filesize = None
    created_ts = None
    modified_ts = None
    try:
        img_file = full_path
        with Image.open(img_file) as im:
            width, height = im.size
    except Exception:
        pass

    try:
        stat = full_path.stat()
        filesize = stat.st_size
        created_ts = getattr(stat, "st_birthtime", stat.st_ctime)
        modified_ts = stat.st_mtime
    except Exception:
        pass

    def human_size(bytes_val):
        if bytes_val is None:
            return None
        kb = 1024.0
        if bytes_val < kb * 1024:
            return f"{bytes_val / kb:.2f} KB"
        return f"{bytes_val / (kb * kb):.2f} MB"

    def fmt_ts(ts):
        if ts is None:
            return None
        try:
            return datetime.datetime.fromtimestamp(ts).strftime("%c")
        except Exception:
            return None

    # Breadcrumbs
    if special is not None:
        # SPECIAL NAME / IMAGE
        from .specials import special_root_url

        breadcrumbs = [
            {
                "label": special_name(special),
                "path": special_root_url(special, query_state),
            },
            {"label": full_path.name, "path": None},
        ]
    else:
        # include directory breadcrumbs then append file name as label-only
        # build_breadcrumbs expects a path_text representing directories only
        dir_path_text = dir_text if dir_text != "" else ""
        breadcrumbs = build_breadcrumbs(dir_path_text, query_state)
        breadcrumbs.append({"label": full_path.name, "path": None})

    next_theme = "light" if theme == "dark" else "dark"
    theme_query = {
        "next": request.get_full_path(),
        "sort": sort_key,
        "theme": next_theme,
    }
    if search_text != "":
        theme_query["next"] = request.get_full_path()

    context = {
        "image_path": image,
        # keep legacy prev/next names for tests
        "prev": prev_path.name if prev_path is not None else None,
        "next": next_path.name if next_path is not None else None,
        # new richer values
        "prev_url": prev_url,
        "next_url": next_url,
        "prev_thumb": prev_thumb,
        "next_thumb": next_thumb,
        "back_url": back_url,
        "back_thumb": back_thumb,
        "home_url": home_url,
        "home_thumb": home_thumb,
        "image_meta": {
            "filename": full_path.name,
            "width": width,
            "height": height,
            "filesize": human_size(filesize),
            "created": fmt_ts(created_ts),
            "modified": fmt_ts(modified_ts),
            "visits": img.visits,
            "visited": fmt_ts(img.last_visited.timestamp()),
            "favorite": img.favorite,
        },
        "breadcrumbs": breadcrumbs,
        "theme": theme,
        "sort_key": sort_key,
        "sort_label": "",
        "sort_options": build_sort_options(request, search_text, sort_key, theme),
        "theme_toggle_url": append_query("/gallery/toggle-settings/", theme_query),
        "path": path_text,
        "is_special": special is not None,
    }

    from .common import SORT_LABELS

    context["sort_label"] = SORT_LABELS.get(sort_key, "")

    return render(request, "image_view.html", context)
