"""Storefront hull-section tests."""

from django.test import TestCase
from django.urls import reverse

from shop.models import HULL, HullListing, Shop
from shop.tests.test_stock import make_owner_character, make_ship_type
from shop.tests.test_views_backoffice import no_manifest_static


@no_manifest_static
class StorefrontHullsTests(TestCase):
    def setUp(self):
        self.user, self.char = make_owner_character()
        self.ship = make_ship_type()
        self.shop = Shop.objects.create(
            slug="pub",
            name="Pub",
            created_by=self.user,
            is_published=True,
            enabled_sections=[HULL],
        )
        HullListing.objects.create(shop=self.shop, eve_type=self.ship, price=0, stock=0)
        self.url = f"/shop/{self.shop.slug}/hulls/"

    def test_hull_card_and_group_render(self):
        resp = self.client.get(self.url, SERVER_NAME="localhost")
        self.assertEqual(resp.status_code, 200)
        self.assertContains(resp, "Erebus")
        self.assertContains(resp, "Titan")  # group header
        self.assertContains(resp, "Build to order")  # stock 0
        self.assertContains(resp, "Ask")  # price 0

    def test_table_view_renders_table(self):
        resp = self.client.get(self.url + "?view=table", SERVER_NAME="localhost")
        self.assertEqual(resp.status_code, 200)
        self.assertContains(resp, "<table")
        self.assertContains(resp, "Erebus")

    def test_hulls_section_404_when_disabled(self):
        self.shop.enabled_sections = []
        self.shop.save()
        resp = self.client.get(self.url, SERVER_NAME="localhost")
        self.assertEqual(resp.status_code, 404)

    def test_description_rendered_above_listings(self):
        self.shop.description = "**Welcome** to my shop"
        self.shop.save(update_fields=["description"])
        resp = self.client.get(self.url, SERVER_NAME="localhost")
        self.assertContains(resp, "shop-description")
        self.assertContains(resp, "<strong>Welcome</strong>")

    def test_no_description_block_when_blank(self):
        resp = self.client.get(self.url, SERVER_NAME="localhost")
        self.assertNotContains(resp, "shop-description")

    def test_grid_card_links_to_detail(self):
        listing = HullListing.objects.get(shop=self.shop, eve_type=self.ship)
        url = reverse("storefront:item", args=[self.shop.slug, listing.pk])
        resp = self.client.get(self.url, SERVER_NAME="localhost")
        self.assertContains(resp, f'href="{url}"')

    def test_featured_ordered_by_featured_at(self):
        from datetime import timedelta

        from django.utils import timezone

        # Two ships in the SAME group so only featured_at (not group/name) drives order.
        apex = make_ship_type(
            type_id=588, name="Apex", group_id=26, group_name="Cruiser"
        )
        zephyr = make_ship_type(
            type_id=589, name="Zephyr", group_id=26, group_name="Cruiser"
        )
        a = HullListing.objects.create(shop=self.shop, eve_type=apex, price=0, stock=1)
        z = HullListing.objects.create(
            shop=self.shop, eve_type=zephyr, price=0, stock=1
        )
        now = timezone.now()
        z.featured = True
        z.featured_at = now - timedelta(hours=1)
        z.save()
        a.featured = True
        a.featured_at = now
        a.save()
        resp = self.client.get(self.url, SERVER_NAME="localhost")
        body = resp.content.decode()
        # Zephyr featured first -> before Apex despite alphabetical order.
        self.assertLess(body.index("Zephyr"), body.index("Apex"))

    def test_featured_section_absent_when_none_starred(self):
        resp = self.client.get(self.url, SERVER_NAME="localhost")
        self.assertNotContains(resp, "Featured")

    def test_featured_section_present_and_dedup(self):
        # Second ship in a different group; feature the first (Erebus/Titan).
        rifter = make_ship_type(
            type_id=587, name="Rifter", group_id=25, group_name="Frigate"
        )
        HullListing.objects.create(shop=self.shop, eve_type=rifter, price=0, stock=0)
        listing = HullListing.objects.get(shop=self.shop, eve_type=self.ship)
        listing.featured = True
        listing.save(update_fields=["featured"])
        resp = self.client.get(self.url, SERVER_NAME="localhost")
        self.assertContains(resp, "Featured")  # featured heading present
        self.assertContains(resp, "Erebus")  # featured card
        self.assertContains(resp, "Rifter")  # normal group card
        self.assertContains(resp, "Frigate")  # Rifter's group header
        # Titan group header should NOT render: its only member is featured-out.
        self.assertNotContains(resp, "Titan")

    def test_table_view_marks_featured(self):
        listing = HullListing.objects.get(shop=self.shop, eve_type=self.ship)
        listing.featured = True
        listing.save(update_fields=["featured"])
        resp = self.client.get(self.url + "?view=table", SERVER_NAME="localhost")
        self.assertContains(resp, "ti-star-filled")

    def test_table_view_is_sortable_and_paginated(self):
        # The table view opts into the shared enhancer with the Tailwind style,
        # a pager mount, sortable columns, and numeric sort keys.
        resp = self.client.get(self.url + "?view=table", SERVER_NAME="localhost")
        self.assertContains(resp, "data-table")
        self.assertContains(resp, 'data-table-style="tailwind"')
        self.assertContains(resp, 'data-table-hidden-class="hidden"')
        self.assertContains(resp, "data-table-pager")
        self.assertContains(resp, 'data-sort="text"')  # Name / Group
        self.assertContains(resp, 'data-sort="num"')  # Price / Stock
        self.assertContains(resp, "data-sort-value=")  # numeric cell keys

    def test_table_view_has_no_default_sort_arrow(self):
        # Default order is featured-first then alphabetical — not a single-column
        # sort — so no column advertises itself as the default sorted one.
        resp = self.client.get(self.url + "?view=table", SERVER_NAME="localhost")
        self.assertNotContains(resp, "data-sort-default")

    def test_table_view_search_owned_by_controller(self):
        # In table view the enhancer owns search (so pagination sees the matched
        # set); the base [data-search] filter must stay out of it.
        resp = self.client.get(self.url + "?view=table", SERVER_NAME="localhost")
        # Target the input element itself — the base filter's inline script always
        # mentions [data-search-input] by name, so match on the attribute in context.
        self.assertContains(resp, 'autocomplete="off" data-table-search')
        self.assertNotContains(resp, 'autocomplete="off" data-search-input')

    def test_grid_view_search_owned_by_base_filter(self):
        # Grid view is unchanged: the base [data-search] filter owns search.
        resp = self.client.get(self.url, SERVER_NAME="localhost")
        self.assertContains(resp, 'autocomplete="off" data-search-input')
        self.assertNotContains(resp, 'autocomplete="off" data-table-search')


@no_manifest_static
class ItemDetailTests(TestCase):
    def setUp(self):
        self.user, self.char = make_owner_character()
        self.ship = make_ship_type()
        self.shop = Shop.objects.create(
            slug="pub",
            name="Pub",
            created_by=self.user,
            is_published=True,
            enabled_sections=[HULL],
        )
        self.listing = HullListing.objects.create(
            shop=self.shop,
            eve_type=self.ship,
            price=5000000,
            stock=3,
            description="**great ship**",
        )

    def _url(self):
        return reverse("storefront:item", args=[self.shop.slug, self.listing.pk])

    def test_renders_detail(self):
        resp = self.client.get(self._url(), SERVER_NAME="localhost")
        self.assertEqual(resp.status_code, 200)
        self.assertContains(resp, "Erebus")
        # Qty + Add-to-order are hidden until the order flow ships.
        self.assertNotContains(resp, "Add to order")
        self.assertNotContains(resp, 'name="quantity"')
        self.assertContains(resp, "<strong>great ship</strong>")
        self.assertContains(resp, "in stock")

    def test_build_to_order_when_no_stock(self):
        self.listing.stock = 0
        self.listing.save(update_fields=["stock"])
        resp = self.client.get(self._url(), SERVER_NAME="localhost")
        self.assertContains(resp, "Build to order")

    def test_unpublished_404_for_anonymous(self):
        self.shop.is_published = False
        self.shop.save(update_fields=["is_published"])
        resp = self.client.get(self._url(), SERVER_NAME="localhost")
        self.assertEqual(resp.status_code, 404)

    def test_wrong_shop_404(self):
        other = Shop.objects.create(
            slug="other", name="Other", created_by=self.user, is_published=True
        )
        url = reverse("storefront:item", args=[other.slug, self.listing.pk])
        resp = self.client.get(url, SERVER_NAME="localhost")
        self.assertEqual(resp.status_code, 404)


@no_manifest_static
class SectionNavTests(TestCase):
    def setUp(self):
        self.user, self.char = make_owner_character()
        self.ship = make_ship_type()
        self.shop = Shop.objects.create(
            slug="pub",
            name="Pub",
            created_by=self.user,
            is_published=True,
            enabled_sections=["hulls", "modules"],
        )

    def test_root_redirects_to_first_section(self):
        resp = self.client.get("/shop/pub/", SERVER_NAME="localhost")
        self.assertRedirects(resp, "/shop/pub/hulls/", fetch_redirect_response=False)

    def test_modules_section_renders(self):
        resp = self.client.get("/shop/pub/modules/", SERVER_NAME="localhost")
        self.assertEqual(resp.status_code, 200)
        self.assertContains(resp, "No items listed yet.")

    def test_unknown_section_404(self):
        resp = self.client.get("/shop/pub/nope/", SERVER_NAME="localhost")
        self.assertEqual(resp.status_code, 404)

    def test_tab_bar_lists_enabled_only(self):
        resp = self.client.get("/shop/pub/hulls/", SERVER_NAME="localhost")
        self.assertContains(resp, "/shop/pub/modules/")  # enabled tab
        self.assertNotContains(resp, "/shop/pub/bpc/")  # disabled tab absent

    def test_no_sections_empty_state(self):
        self.shop.enabled_sections = []
        self.shop.save()
        resp = self.client.get("/shop/pub/", SERVER_NAME="localhost")
        self.assertEqual(resp.status_code, 200)
        self.assertContains(resp, "No sections")
