"""Dashboard default model: display-PC-IP -> display role (+ business unit).

A single "display" PC image resolves what it should show from its own IP: the
role (shopfloor dashboard, lobby slideshow, or 3D-parts kiosk) and, for the
dashboard role, which business unit. Powers the visitor-location + display-role
lookups the kiosks call at launch.
"""

from shopdb.extensions import db
from .base import BaseModel

# Display role -> the frontend kiosk path it maps to. Kept here so the API and
# any consumer resolve a role to a URL the same way.
DISPLAY_ROLE_PATHS = {
    'dashboard': '/shopfloor',
    'lobby': '/tv',
    'partskiosk': '/parts-kiosk',
}
DISPLAY_ROLES = tuple(DISPLAY_ROLE_PATHS.keys())

# GE device naming: a PC's DNS name is 'F' + its BIOS serial under the device
# domain, e.g. FABC1234.device.geaerospace.net. The domain is a setting so other
# sites can point elsewhere; the collector already reports the serial, so the
# server derives the stable FQDN without the kiosk having to report it.
DEFAULT_DISPLAY_FQDN_DOMAIN = 'device.geaerospace.net'


def derive_display_fqdn(serialnumber):
    """FQDN for a display PC from its BIOS serial: F<serial>.<domain> (lower).

    Returns None when there is no serial. Domain from the display_fqdn_domain
    setting, falling back to DEFAULT_DISPLAY_FQDN_DOMAIN.
    """
    serial = (serialnumber or '').strip()
    if not serial:
        return None
    from .setting import Setting
    domain = (Setting.get('display_fqdn_domain', DEFAULT_DISPLAY_FQDN_DOMAIN)
              or DEFAULT_DISPLAY_FQDN_DOMAIN).strip().strip('.')
    return f'F{serial}.{domain}'.lower()


class DashboardDefault(BaseModel):
    """Maps a display PC (by FQDN, or IP) to its display role (+ location)."""
    __tablename__ = 'dashboarddefaults'

    dashboarddefaultid = db.Column(db.Integer, primary_key=True)
    # A mapping is keyed by FQDN (stable, DHCP-proof) and/or IP. At least one is
    # required (enforced in the API). FQDN is preferred; IP is the fallback for a
    # manual entry or a PC not yet reporting a serial.
    # 191 = the utf8mb4-safe unique-index length (191*4 < 767) so the index does
    # not depend on innodb_large_prefix; FQDNs (F<serial>.<domain>) fit easily.
    fqdn = db.Column(db.String(191), unique=True, nullable=True, index=True)
    ipaddress = db.Column(db.String(50), unique=True, nullable=True)
    # Which display the mapping drives. Only the dashboard role uses businessunitid.
    displayrole = db.Column(db.String(20), nullable=False, default='dashboard')
    businessunitid = db.Column(
        db.Integer,
        db.ForeignKey('businessunits.businessunitid'),
        nullable=True
    )
    description = db.Column(db.String(255))

    businessunit = db.relationship('BusinessUnit')

    @property
    def displaypath(self):
        return DISPLAY_ROLE_PATHS.get(self.displayrole)

    def __repr__(self):
        return f"<DashboardDefault {self.fqdn or self.ipaddress} -> {self.displayrole}>"
