"""Shop asset sourcing: enumerate a shop owner's memberaudit sources for the
stockroom picker, and query the assets located at a single source.
"""

from django.db.models import Sum
from memberaudit.models import Character, CharacterAsset


def source_assets(source):
    """Assets located at a single ShopSource (shared primitive across sections)."""
    qs = CharacterAsset.objects.filter(character_id=source.character_id)
    if source.container_item_id:
        return qs.filter(
            parent__character_id=source.character_id,
            parent__item_id=source.container_item_id,
        )
    # station hangar: top-level assets at the location
    return qs.filter(location_id=source.location_id, parent__isnull=True)


def source_qty(source, eve_type) -> int:
    """Quantity of `eve_type` available at a single source."""
    n = (
        source_assets(source)
        .filter(eve_type=eve_type)
        .aggregate(n=Sum("quantity"))["n"]
    )
    return n or 0


def owner_characters(user):
    """memberaudit Characters owned by `user`."""
    return Character.objects.filter(
        eve_character__character_ownership__user=user
    ).select_related("eve_character")


def container_name_for(character_id, item_id) -> str:
    """Display name of a character's container asset (custom name, else type name)."""
    if not item_id:
        return ""
    asset = (
        CharacterAsset.objects.filter(character_id=character_id, item_id=item_id)
        .select_related("eve_type")
        .first()
    )
    if asset is None:
        return ""
    return asset.name or asset.eve_type.name


def source_tree(user):
    """Nested character → stations → containers tree for the source picker."""
    tree = []
    for char in owner_characters(user):
        top = list(
            CharacterAsset.objects.filter(
                character=char, parent__isnull=True, location__isnull=False
            ).select_related("location", "eve_type")
        )
        # Containers = top-level assets that HOLD items and are NOT ships
        # (a fitted ship also "has children" — its modules — so exclude category 6).
        container_ids = set(
            CharacterAsset.objects.filter(
                character=char, parent__isnull=True, children__isnull=False
            )
            .exclude(eve_type__eve_group__eve_category_id=6)
            .values_list("id", flat=True)
        )
        stations = {}
        for asset in top:
            st = stations.setdefault(
                asset.location_id,
                {
                    "location_id": asset.location_id,
                    "name": asset.location.name,
                    "containers": [],
                },
            )
            if asset.id in container_ids:
                st["containers"].append(
                    {
                        "item_id": asset.item_id,
                        "name": asset.name or asset.eve_type.name,
                    }
                )
        for st in stations.values():
            st["containers"].sort(key=lambda c: c["name"].lower())
        if stations:
            tree.append(
                {
                    "character_id": char.id,
                    "character_name": char.eve_character.character_name,
                    "stations": sorted(
                        stations.values(), key=lambda s: s["name"].lower()
                    ),
                }
            )
    return tree
