"""Shared model scaffolding: section/mode constants, the permissions meta model,
and the FeaturedListing mixin reused by every section's listing."""

from decimal import Decimal

from django.core.validators import RegexValidator
from django.db import models

SLUG_VALIDATOR = RegexValidator(
    regex=r"^[a-z0-9]+(-[a-z0-9]+)*$",
    message="Slug may contain lowercase letters, numbers and single dashes only.",
)

HULL = "hulls"
MODULES = "modules"
BPC = "bpc"
FITTED = "fitted"
SECTION_CHOICES = [
    (HULL, "Hulls"),
    (MODULES, "Modules"),
    (BPC, "BPC"),
    (FITTED, "Fitted Ships"),
]

# Stock modes
AUTO_STOCK = "auto"
FIXED_STOCK = "fixed"
STOCK_MODE_CHOICES = [(AUTO_STOCK, "Auto"), (FIXED_STOCK, "Fixed")]

# Price modes ("Ask" is not a mode: Fixed price 0 renders as Ask)
FIXED_PRICE = "fixed"
JITA_BUY_PCT = "jita_buy_pct"
JITA_SELL_PCT = "jita_sell_pct"
PRICE_MODE_CHOICES = [
    (FIXED_PRICE, "Fixed"),
    (JITA_BUY_PCT, "% Jita Buy"),
    (JITA_SELL_PCT, "% Jita Sell"),
]
PCT_MODES = (JITA_BUY_PCT, JITA_SELL_PCT)


def format_price_rule(price_mode, price_pct, price=None) -> str:
    """Human label for a price rule. Fixed shows 'Ask' at 0 (or when price is
    unknown, e.g. a stockroom's default), else 'Fixed'; pct modes show 'Jita Buy 90%'.
    """
    if price_mode == FIXED_PRICE:
        return "Ask" if (price is None or price == 0) else "Fixed"
    label = "Jita Buy" if price_mode == JITA_BUY_PCT else "Jita Sell"
    # normalize() strips trailing zeros but yields sci-notation (9E+1); "f" fixes it.
    pct = format((price_pct or Decimal(0)).normalize(), "f")
    return f"{label} {pct}%"


class General(models.Model):
    """Meta model that only carries app-level permissions."""

    class Meta:
        managed = False
        default_permissions = ()
        permissions = (
            ("basic_access", "Can access the shop app"),
            ("manage_corporation_shops", "Can manage corporation shops"),
        )


class FeaturedListing(models.Model):
    """Mixin: a listing that can be starred to feature it first on the storefront."""

    featured = models.BooleanField(
        default=False
    )  # starred: shown first + larger on the storefront
    featured_at = models.DateTimeField(
        null=True, blank=True
    )  # set on star; orders featured items

    class Meta:
        abstract = True

    def toggle_featured(self, save=True):
        """Flip featured, stamping/clearing featured_at. Saves by default."""
        from django.utils import timezone

        self.featured = not self.featured
        self.featured_at = timezone.now() if self.featured else None
        if save:
            self.save(update_fields=["featured", "featured_at"])
