import nested_admin
from django import forms
from django.contrib import admin
from django.utils.html import format_html

from .models import (
    ArchiveCategory,
    PortfolioItem,
    PortfolioMedia,
    PortfolioMediaAnnotation,
    SiteSettings,
)


admin.site.site_header = "Valentinos Archive Administration"
admin.site.site_title = "Valentinos Archive Admin"
admin.site.index_title = "Website and archive content"


def image_preview(image_field, *, max_height=150):
    """Return a consistent square-corner image preview for Django admin forms."""
    if not image_field:
        return format_html(
            '<span style="color:{};">{}</span>',
            "#6b7280",
            "No image has been uploaded.",
        )

    return format_html(
        '<a href="{}" target="_blank" rel="noopener">'
        '<img src="{}" alt="" '
        'style="display:block; max-height:{}px; max-width:100%; '
        'border:1px solid #d1d5db; object-fit:cover;" />'
        "</a>",
        image_field.url,
        image_field.url,
        max_height,
    )


class SiteSettingsAdminForm(forms.ModelForm):
    class Meta:
        model = SiteSettings
        fields = "__all__"
        labels = {
            "home_banner_image": "Homepage hero banner",
            "menu_banner_image": "Full-screen menu image",
        }
        help_texts = {
            "home_banner_image": (
                "Site-wide image shown in the large hero section at the top of "
                "the homepage."
            ),
            "menu_banner_image": (
                "Site-wide image shown on the right side of the full-screen menu."
            ),
        }


@admin.register(SiteSettings)
class SiteSettingsAdmin(admin.ModelAdmin):
    form = SiteSettingsAdminForm
    save_on_top = True
    fieldsets = (
        (
            "Global website images",
            {
                "description": (
                    "These images belong to the website as a whole. They are not "
                    "connected to a category or an individual archive item."
                ),
                "fields": (
                    "home_banner_image",
                    "home_banner_preview",
                    "menu_banner_image",
                    "menu_banner_preview",
                ),
            },
        ),
    )
    readonly_fields = (
        "home_banner_preview",
        "menu_banner_preview",
    )

    def has_add_permission(self, request):
        return not SiteSettings.objects.exists()

    def has_delete_permission(self, request, obj=None):
        return False

    @admin.display(description="Current homepage hero banner")
    def home_banner_preview(self, obj):
        return image_preview(obj.home_banner_image if obj else None, max_height=180)

    @admin.display(description="Current full-screen menu image")
    def menu_banner_preview(self, obj):
        return image_preview(obj.menu_banner_image if obj else None, max_height=180)


class ArchiveCategoryAdminForm(forms.ModelForm):
    class Meta:
        model = ArchiveCategory
        fields = "__all__"
        labels = {
            "name": "Category name",
            "slug": "URL slug",
            "category_type": "Category browsing experience",
            "description": "Category description",
            "banner_image": "Homepage category image",
            "timeline_banner_image": "Category timeline page banner",
            "decade_banner_image": "Period item-list page banner",
        }
        help_texts = {
            "category_type": (
                "Choose Timeline for normal archive categories. Choose 3D Models "
                "to open all items directly without periods or displayed dates."
            ),
            "banner_image": (
                "Shown with this category on the homepage. For a 3D Models "
                "category, this image is also used as its listing-page banner."
            ),
            "timeline_banner_image": (
                "Used only by standard timeline categories. Leave empty to use "
                "the homepage category image."
            ),
            "decade_banner_image": (
                "Used only by standard timeline categories on period item-list pages."
            ),
        }


@admin.register(ArchiveCategory)
class ArchiveCategoryAdmin(admin.ModelAdmin):
    form = ArchiveCategoryAdminForm
    save_on_top = True
    list_display = (
        "name",
        "slug",
        "category_experience",
        "has_homepage_image",
        "timeline_banner_status",
        "period_banner_status",
    )
    list_filter = ("category_type",)
    search_fields = ("name", "description")
    prepopulated_fields = {"slug": ("name",)}

    standard_fieldsets = (
        (
            "Category information",
            {
                "fields": (
                    "name",
                    "slug",
                    "category_type",
                    "description",
                ),
            },
        ),
        (
            "1. Homepage category image",
            {
                "description": (
                    "This image appears on the homepage and is the fallback image "
                    "for this category."
                ),
                "fields": (
                    "banner_image",
                    "homepage_image_preview",
                ),
            },
        ),
        (
            "2. Category timeline page banner",
            {
                "description": (
                    "Used only for standard categories that open a chronological "
                    "timeline."
                ),
                "fields": (
                    "timeline_banner_image",
                    "timeline_banner_preview",
                ),
            },
        ),
        (
            "3. Period item-list page banner",
            {
                "description": (
                    "Used only for standard categories on decade or period pages."
                ),
                "fields": (
                    "decade_banner_image",
                    "period_banner_preview",
                ),
            },
        ),
    )

    three_d_fieldsets = (
        (
            "3D Models category information",
            {
                "description": (
                    "This category opens its items directly. It does not use a "
                    "timeline, periods, or displayed dates."
                ),
                "fields": (
                    "name",
                    "slug",
                    "category_type",
                    "description",
                ),
            },
        ),
        (
            "Category image and listing banner",
            {
                "description": (
                    "The same image appears on the homepage and at the top of the "
                    "3D models listing page."
                ),
                "fields": (
                    "banner_image",
                    "homepage_image_preview",
                ),
            },
        ),
    )

    readonly_fields = (
        "homepage_image_preview",
        "timeline_banner_preview",
        "period_banner_preview",
    )

    def get_fieldsets(self, request, obj=None):
        if obj and obj.is_3d_models:
            return self.three_d_fieldsets
        return self.standard_fieldsets

    @admin.display(description="Browsing experience")
    def category_experience(self, obj):
        return obj.get_category_type_display()

    @admin.display(description="Homepage image", boolean=True)
    def has_homepage_image(self, obj):
        return bool(obj.banner_image)

    @admin.display(description="Timeline banner")
    def timeline_banner_status(self, obj):
        if obj.is_3d_models:
            return "Not used"
        return "Yes" if obj.timeline_banner_image else "No"

    @admin.display(description="Period-list banner")
    def period_banner_status(self, obj):
        if obj.is_3d_models:
            return "Not used"
        return "Yes" if obj.decade_banner_image else "No"

    @admin.display(description="Current homepage category image")
    def homepage_image_preview(self, obj):
        return image_preview(obj.banner_image if obj else None)

    @admin.display(description="Current category timeline banner")
    def timeline_banner_preview(self, obj):
        return image_preview(obj.timeline_banner_image if obj else None)

    @admin.display(description="Current period item-list banner")
    def period_banner_preview(self, obj):
        return image_preview(obj.decade_banner_image if obj else None)


class PortfolioMediaAnnotationAdminForm(forms.ModelForm):
    class Meta:
        model = PortfolioMediaAnnotation
        fields = "__all__"
        labels = {
            "title": "Hotspot title",
            "description": "Hotspot description",
            "x_percent": "Horizontal position (%)",
            "y_percent": "Vertical position (%)",
            "media_file": "Optional hotspot file",
            "link": "Optional hotspot link",
            "sort_order": "Display order",
            "is_active": "Visible",
        }


class PortfolioMediaAnnotationInline(nested_admin.NestedTabularInline):
    model = PortfolioMediaAnnotation
    form = PortfolioMediaAnnotationAdminForm
    extra = 0
    verbose_name = "Image annotation / hotspot"
    verbose_name_plural = "Image annotations / hotspots"
    classes = ("collapse",)
    fields = (
        "title",
        "description",
        "x_percent",
        "y_percent",
        "media_file",
        "link",
        "sort_order",
        "is_active",
    )


class PortfolioMediaAdminForm(forms.ModelForm):
    class Meta:
        model = PortfolioMedia
        fields = "__all__"
        labels = {
            "file": "Item image",
            "title": "Image title or caption",
            "is_primary": "Use as the main item image",
        }
        help_texts = {
            "is_primary": (
                "The main image is shown first and is used as the item's primary "
                "thumbnail where applicable."
            ),
        }


class PortfolioMediaInline(nested_admin.NestedStackedInline):
    model = PortfolioMedia
    form = PortfolioMediaAdminForm
    extra = 1
    inlines = [PortfolioMediaAnnotationInline]
    verbose_name = "Item gallery image"
    verbose_name_plural = "Item gallery images"
    fields = (
        ("file", "preview"),
        ("title", "is_primary"),
    )
    readonly_fields = ("preview",)

    @admin.display(description="Current image preview")
    def preview(self, obj):
        return image_preview(obj.file if obj else None, max_height=130)


class PortfolioItemAdminForm(forms.ModelForm):
    class Meta:
        model = PortfolioItem
        fields = "__all__"
        labels = {
            "category": "Archive category",
            "inventory_id": "Inventory number",
            "title": "Item title",
            "year": "Year used for timeline grouping",
            "date_text": "Displayed date",
            "place_created": "Place created",
            "detail_banner_image": "Custom item-detail page banner",
            "model_viewer_url": "3D model viewer URL",
            "description": "Main description",
            "physical_description": "Physical description",
            "materials_and_techniques": "Materials and techniques",
            "dimensions": "Dimensions",
            "signature": "Signature",
            "marks_and_inscriptions": "Marks and inscriptions",
            "bibliographic_reference": "Bibliographic reference",
            "is_featured": "Featured item",
        }
        help_texts = {
            "year": (
                "Used only by normal timeline categories. It is not displayed for "
                "items in the 3D Models category."
            ),
            "date_text": (
                "The date visitors see for normal archive items. It is not displayed "
                "for 3D model items."
            ),
            "detail_banner_image": (
                "Optional banner for normal item-detail pages. It is not used by "
                "3D model items."
            ),
            "model_viewer_url": (
                "Required for the 3D Models category. A JPG/PNG URL opens in the "
                "built-in zoom viewer. GLB/GLTF files are interactive, and any other "
                "URL is embedded as an external viewer."
            ),
        }

    def clean(self):
        cleaned_data = super().clean()
        category = cleaned_data.get("category")
        model_viewer_url = cleaned_data.get("model_viewer_url")

        if category and category.is_3d_models and not model_viewer_url:
            self.add_error(
                "model_viewer_url",
                "Add the URL that should open inside the 3D model viewer.",
            )

        return cleaned_data


@admin.register(PortfolioItem)
class PortfolioItemAdmin(nested_admin.NestedModelAdmin):
    form = PortfolioItemAdminForm
    save_on_top = True
    list_display = (
        "title",
        "inventory_id",
        "category",
        "item_experience",
        "year",
        "is_featured",
        "updated_at",
    )
    list_filter = ("category", "category__category_type", "is_featured", "year")
    search_fields = (
        "title",
        "inventory_id",
        "date_text",
        "place_created",
        "description",
        "physical_description",
        "materials_and_techniques",
        "dimensions",
        "signature",
        "marks_and_inscriptions",
        "bibliographic_reference",
        "model_viewer_url",
    )
    autocomplete_fields = ("category",)
    inlines = [PortfolioMediaInline]
    readonly_fields = ("detail_banner_preview",)

    standard_fieldsets = (
        (
            "Item identification",
            {
                "fields": (
                    "category",
                    "inventory_id",
                    "title",
                    "is_featured",
                ),
            },
        ),
        (
            "Date and place",
            {
                "fields": (
                    "year",
                    "date_text",
                    "place_created",
                ),
            },
        ),
        (
            "3D model viewer",
            {
                "classes": ("collapse",),
                "description": (
                    "Complete this only when the selected archive category is the "
                    "3D Models category."
                ),
                "fields": ("model_viewer_url",),
            },
        ),
        (
            "Optional item-detail page banner",
            {
                "description": (
                    "A wide banner shown only at the top of a normal item's page. "
                    "Leave it empty to use the category image."
                ),
                "fields": (
                    "detail_banner_image",
                    "detail_banner_preview",
                ),
            },
        ),
        (
            "Main item content",
            {
                "description": (
                    "The main description is shown as a standard content card. The "
                    "remaining populated fields are shown in the details accordion."
                ),
                "fields": (
                    "description",
                    "physical_description",
                    "materials_and_techniques",
                    "dimensions",
                ),
            },
        ),
        (
            "Additional accordion details",
            {
                "fields": (
                    "signature",
                    "marks_and_inscriptions",
                    "bibliographic_reference",
                ),
            },
        ),
    )

    three_d_fieldsets = (
        (
            "3D model item",
            {
                "description": (
                    "3D model items do not display dates, gallery images, metadata "
                    "cards, descriptions, or accordions on the public page."
                ),
                "fields": (
                    "category",
                    "inventory_id",
                    "title",
                    "is_featured",
                ),
            },
        ),
        (
            "Viewer",
            {
                "description": (
                    "Paste the remote image, GLB/GLTF model, or embeddable viewer URL."
                ),
                "fields": ("model_viewer_url",),
            },
        ),
    )

    def get_fieldsets(self, request, obj=None):
        if obj and obj.is_3d_model_item:
            return self.three_d_fieldsets
        return self.standard_fieldsets

    def get_inline_instances(self, request, obj=None):
        if obj and obj.is_3d_model_item:
            return []
        return super().get_inline_instances(request, obj)

    @admin.display(description="Public item page")
    def item_experience(self, obj):
        if obj.is_3d_model_item:
            return "3D viewer" if obj.model_viewer_url else "3D viewer URL missing"
        return "Archive detail"

    @admin.display(description="Current custom item-page banner")
    def detail_banner_preview(self, obj):
        return image_preview(obj.detail_banner_image if obj else None, max_height=180)
