"""Core models shared across sections: the Shop and its stockroom sources."""

from allianceauth.eveonline.models import EveCorporationInfo
from django.contrib.auth.models import User
from django.db import models

from .base import (
    FIXED_PRICE,
    PRICE_MODE_CHOICES,
    SECTION_CHOICES,
    SLUG_VALIDATOR,
    format_price_rule,
)


class Shop(models.Model):
    """A member's or corporation's shop."""

    class ShopType(models.TextChoices):
        PERSONAL = "personal", "Personal"
        CORPORATION = "corporation", "Corporation"

    slug = models.SlugField(
        max_length=50,
        unique=True,
        validators=[SLUG_VALIDATOR],
        help_text="Globally unique. Lowercase letters, numbers and dashes.",
    )
    name = models.CharField(max_length=100)
    shop_type = models.CharField(
        max_length=12, choices=ShopType.choices, default=ShopType.PERSONAL
    )
    is_published = models.BooleanField(default=False)
    corporation = models.ForeignKey(
        EveCorporationInfo,
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="shops",
    )
    created_by = models.ForeignKey(User, on_delete=models.CASCADE, related_name="shops")
    enabled_sections = models.JSONField(default=list, blank=True)
    description = models.TextField(blank=True, default="")
    discord_webhook = models.URLField(max_length=500, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.name

    def section_enabled(self, key) -> bool:
        return key in (self.enabled_sections or [])

    def enabled_section_choices(self):
        """(key, label) for each enabled section, in SECTION_CHOICES order."""
        return [(k, label) for k, label in SECTION_CHOICES if self.section_enabled(k)]

    def first_enabled_section(self):
        choices = self.enabled_section_choices()
        return choices[0][0] if choices else None

    @property
    def description_html(self) -> str:
        from ..markdown import render_markdown

        return render_markdown(self.description)

    @property
    def open_order_count(self):
        from .orders import Order

        return self.orders.filter(status__in=Order.OPEN_STATUSES).count()


class ShopSource(models.Model):
    """A stockroom for a shop section (corptools CharacterAudit → Station → Container).

    Section-scoped via `section`: a hull listing's stock is counted across the shop's
    sources where `section == "hulls"`. The same table serves every section.
    """

    shop = models.ForeignKey(Shop, on_delete=models.CASCADE, related_name="sources")
    section = models.CharField(max_length=20, choices=SECTION_CHOICES)
    character_audit = models.ForeignKey(
        "corptools.CharacterAudit",
        null=True,
        blank=True,
        on_delete=models.CASCADE,
        related_name="+",
    )
    corporation_audit = models.ForeignKey(
        "corptools.CorporationAudit",
        null=True,
        blank=True,
        on_delete=models.CASCADE,
        related_name="+",
    )
    location_id = models.BigIntegerField()
    container_item_id = models.PositiveBigIntegerField(null=True, blank=True)
    container_name = models.CharField(max_length=100, blank=True, default="")
    price_mode = models.CharField(
        max_length=20, choices=PRICE_MODE_CHOICES, default=FIXED_PRICE
    )
    price_pct = models.DecimalField(
        max_digits=5, decimal_places=2, null=True, blank=True
    )  # default price rule inherited by first-seen auto-listed hulls
    # Fitted-ship curation (in-game marking): only ships whose custom name contains
    # `name_filter` are listed (blank = list all in the hangar/division); the marker
    # is stripped from the buyer-facing label when `strip_marker` is set.
    name_filter = models.CharField(max_length=100, blank=True, default="")
    strip_marker = models.BooleanField(default=True)

    class Meta:
        constraints = [
            models.CheckConstraint(
                check=(
                    models.Q(
                        character_audit__isnull=False, corporation_audit__isnull=True
                    )
                    | models.Q(
                        character_audit__isnull=True, corporation_audit__isnull=False
                    )
                ),
                name="shopsource_exactly_one_owner",
            )
        ]

    def __str__(self):
        return (
            f"{self.shop_id}:{self.section}:"
            f"ca{self.character_audit_id}@loc{self.location_id}"
        )

    @property
    def location_display(self) -> str:
        """Resolved station/structure name (corptools EveLocation), else the raw id."""
        from ..sources import _location_name

        return _location_name(self.location_id)

    @property
    def owner_display(self) -> str:
        """Character name for a character source; corporation name for a corp source."""
        if self.corporation_audit_id is not None:
            return self.corporation_audit.corporation.corporation_name
        if self.character_audit_id is not None:
            return self.character_audit.character.character_name
        return ""

    @property
    def price_rule_display(self) -> str:
        """The default price rule applied to first-seen hulls (Fixed shows 'Ask')."""
        return format_price_rule(self.price_mode, self.price_pct)
