"""BPC section handler — stockroom changes recompute variant stock (no price rule)."""

from ...models import BPC, BpcListing, BpcVariant, Shop, ShopSource
from ..base import SectionHandler, register
from .blueprints import blueprint_token, corp_blueprint_token
from .stock import recompute_bpc_stock


class BpcSectionHandler(SectionHandler):
    section = BPC
    # base AddStockroomForm (location only); BPC stockrooms carry no price rule.
    manage_template = "shop/manage_bpc.html"
    featured_model = BpcListing

    def build_order_line(self, shop, listing_id):
        """`listing_id` is a BpcVariant pk — one orderable item per variant."""
        variant = (
            BpcVariant.objects.filter(pk=listing_id, hidden=False, listing__shop=shop)
            .select_related("listing__eve_type")
            .first()
        )
        if variant is None:
            return None
        return {
            "section": BPC,
            "eve_type": variant.listing.eve_type,
            "unit_price": variant.price,
            "listing_id": variant.pk,
            "label": f"ME {variant.me} · TE {variant.te} · {variant.runs} runs",
            "available": variant.stock,  # copies on hand — capped at stock
        }

    def manage_context(self, shop, request):
        from ...sources import source_tree

        sources = shop.sources.filter(section=BPC).select_related(
            "character_audit__character", "corporation_audit__corporation"
        )
        missing = set()
        for s in sources:
            if s.corporation_audit_id is not None:
                if corp_blueprint_token(s.corporation_audit) is None:
                    missing.add(s.owner_display)
            elif blueprint_token(s.character_audit) is None:
                missing.add(s.owner_display)
        return {
            "listings": shop.bpc_listings.select_related("eve_type")
            .prefetch_related("variants")
            .order_by("eve_type__name"),
            "sources": sources,
            "source_tree": source_tree(request.user, shop),
            "missing_token_owners": sorted(missing),
        }

    def storefront_context(self, shop, request):
        view = request.GET.get("view", "grid")
        if view not in ("grid", "table"):
            view = "grid"
        # A listing surfaces only while it has at least one non-hidden variant.
        base = (
            shop.bpc_listings.filter(variants__hidden=False)
            .distinct()
            .select_related("eve_type")
            .prefetch_related("variants")
        )
        return {
            "featured_listings": list(
                base.filter(featured=True).order_by("featured_at", "eve_type__name")
            ),
            "bpc_listings": list(
                base.filter(featured=False).order_by("eve_type__name")
            ),
            "view": view,
        }

    def stockroom_added(self, source, cd):
        # Populate the ME/TE/runs mirror for this source before grouping, so a
        # freshly-added stockroom resolves its copies immediately (not next cron).
        from .blueprints import (
            refresh_character_blueprints,
            refresh_corporation_blueprints,
        )

        if source.corporation_audit_id is not None:
            refresh_corporation_blueprints(source.corporation_audit)
        else:
            refresh_character_blueprints(source.character_audit)
        recompute_bpc_stock(source.shop)

    def stockroom_removed(self, shop):
        recompute_bpc_stock(shop)

    def shops_to_recompute(self):
        return (
            Shop.objects.filter(sources__section=BPC)
            .values_list("pk", flat=True)
            .distinct()
        )

    def enqueue_source_refresh(self):
        """Refresh the ME/TE/runs blueprint mirror for each character/corporation
        backing a bpc stockroom. The per-shop recompute reads the freshened mirror."""
        from ...tasks import (
            TASK_PRIORITY,
            refresh_blueprints_for_character,
            refresh_blueprints_for_corporation,
        )

        base = ShopSource.objects.filter(section=BPC)
        character_pks = list(
            base.filter(character_audit__isnull=False)
            .values_list("character_audit_id", flat=True)
            .distinct()
        )
        for pk in character_pks:
            refresh_blueprints_for_character.apply_async(
                args=[pk], priority=TASK_PRIORITY
            )
        corporation_pks = list(
            base.filter(corporation_audit__isnull=False)
            .values_list("corporation_audit_id", flat=True)
            .distinct()
        )
        for pk in corporation_pks:
            refresh_blueprints_for_corporation.apply_async(
                args=[pk], priority=TASK_PRIORITY
            )
        return character_pks + corporation_pks

    def recompute(self, shop):
        recompute_bpc_stock(shop)


register(BpcSectionHandler())
