from django.test import TestCase

from shop.models import FittedListing, Shop, ShopSource
from shop.models.base import FITTED
from shop.sections import handler_for
from shop.tests._corptools import (
    make_asset,
    make_owner_character,
    make_ship_sde_type,
    make_ship_type,
)


class FittedHandlerTests(TestCase):
    STATION = 60003760

    def setUp(self):
        self.user, self.char = make_owner_character()
        self.shop = Shop.objects.create(slug="s", name="S", created_by=self.user)
        make_ship_sde_type(type_id=23773, category_id=6, group_id=30)
        make_ship_type(type_id=23773, name="Ragnarok")
        self.handler = handler_for(FITTED)

    def test_registered(self):
        self.assertIsNotNone(self.handler)
        self.assertEqual(self.handler.section, FITTED)
        self.assertIs(self.handler.featured_model, FittedListing)

    def test_stockroom_added_saves_filter_and_reconciles(self):
        make_asset(
            self.char,
            type_id=23773,
            item_id=9001,
            location_id=self.STATION,
            name="Rag [SALE]",
        )
        source = ShopSource.objects.create(
            shop=self.shop,
            section=FITTED,
            character_audit=self.char,
            location_id=self.STATION,
        )
        self.handler.stockroom_added(
            source, {"name_filter": "[SALE]", "strip_marker": True}
        )
        source.refresh_from_db()
        self.assertEqual(source.name_filter, "[SALE]")
        self.assertTrue(source.strip_marker)
        self.assertTrue(FittedListing.objects.filter(item_id=9001).exists())

    def test_stockroom_edited_updates_filter(self):
        source = ShopSource.objects.create(
            shop=self.shop,
            section=FITTED,
            character_audit=self.char,
            location_id=self.STATION,
            name_filter="[OLD]",
            strip_marker=True,
        )
        self.handler.stockroom_edited(
            source, {"name_filter": "[NEW]", "strip_marker": False}
        )
        source.refresh_from_db()
        self.assertEqual(source.name_filter, "[NEW]")
        self.assertFalse(source.strip_marker)

    def test_recompute_lists_and_removed_stockroom_cleans_up(self):
        ship = make_asset(
            self.char, type_id=23773, item_id=9002, location_id=self.STATION, name="Rag"
        )
        source = ShopSource.objects.create(
            shop=self.shop,
            section=FITTED,
            character_audit=self.char,
            location_id=self.STATION,
            name_filter="",
            strip_marker=True,
        )
        self.handler.recompute(self.shop)
        self.assertTrue(FittedListing.objects.filter(item_id=9002).exists())
        # deleting the STOCKROOM (no fitted sources left) cleans up now, no grace
        ship.delete()
        source.delete()
        self.handler.stockroom_removed(self.shop)
        self.assertFalse(FittedListing.objects.filter(item_id=9002).exists())

    def test_shops_to_recompute(self):
        ShopSource.objects.create(
            shop=self.shop,
            section=FITTED,
            character_audit=self.char,
            location_id=self.STATION,
        )
        self.assertIn(self.shop.pk, list(self.handler.shops_to_recompute()))


class FittedStorefrontHandlerTests(TestCase):
    def setUp(self):
        from shop.tests._corptools import make_ship_type

        self.user, self.char = make_owner_character()
        self.shop = Shop.objects.create(slug="s", name="S", created_by=self.user)
        self.hull = make_ship_type(type_id=23773, name="Ragnarok")
        self.handler = handler_for(FITTED)
        self.listing = FittedListing.objects.create(
            shop=self.shop,
            eve_type=self.hull,
            item_id=9001,
            ship_name="Doomsday",
            price=90_000_000_000,
            fit_json={"slots": [], "drones": [], "cargo": [], "manifest": []},
        )

    def test_build_order_line_caps_at_one(self):
        snap = self.handler.build_order_line(self.shop, self.listing.pk)
        self.assertEqual(snap["section"], FITTED)
        self.assertEqual(snap["eve_type"], self.hull)
        self.assertEqual(snap["unit_price"], 90_000_000_000)
        self.assertEqual(snap["listing_id"], self.listing.pk)
        self.assertEqual(snap["label"], "Doomsday")
        self.assertEqual(snap["available"], 1)

    def test_build_order_line_unknown_returns_none(self):
        self.assertIsNone(self.handler.build_order_line(self.shop, 99999))

    def test_build_order_line_build_to_order_has_no_cap(self):
        self.listing.stock = 0  # persisted, ship gone -> build to order
        self.listing.save()
        snap = self.handler.build_order_line(self.shop, self.listing.pk)
        self.assertIsNone(snap["available"])  # unlimited, not capped at 1

    def test_storefront_context_splits_featured(self):
        self.listing.featured = True
        self.listing.save()
        other = FittedListing.objects.create(
            shop=self.shop,
            eve_type=self.hull,
            item_id=9002,
            ship_name="Plain",
            fit_json={},
        )
        from django.test import RequestFactory

        ctx = self.handler.storefront_context(self.shop, RequestFactory().get("/"))
        self.assertEqual(
            [lst.pk for lst in ctx["featured_listings"]], [self.listing.pk]
        )
        self.assertEqual([lst.pk for lst in ctx["listings"]], [other.pk])
        self.assertEqual(ctx["view"], "grid")
