"""Location + LocationType models."""

from shopdb.extensions import db
from .base import BaseModel


def derive_locationcode(locationname):
    """Operation/short code for a location = leading token of its name.

    Locations have no dedicated code column, so the operation code is the
    leading whitespace-delimited token of the location name. Example:
    '0615 Blisk Inspection' -> '0615'. Blank/None name -> None. Used by
    printed labels that encode a tool's inspection operation rather than the
    tool itself.
    """
    if not locationname:
        return None
    parts = str(locationname).strip().split()
    return parts[0] if parts else None


class LocationType(BaseModel):
    """Location classification (ADR-001 shared reference data).

    Seeded values: section, cell, subcell, operation, meetingroom, lab,
    office, storage, hallway, networkcloset, building. Sites can extend.
    """
    __tablename__ = 'locationtypes'

    locationtypeid = db.Column(db.Integer, primary_key=True)
    locationtype = db.Column(db.String(50), unique=True, nullable=False)
    description = db.Column(db.Text)
    color = db.Column(db.String(20), comment='CSS color for UI')

    def __repr__(self):
        return f"<LocationType {self.locationtype}>"


class Location(BaseModel):
    """Physical location model."""
    __tablename__ = 'locations'

    locationid = db.Column(db.Integer, primary_key=True)
    locationname = db.Column(db.String(100), unique=True, nullable=False)
    building = db.Column(db.String(100))
    floor = db.Column(db.String(50))
    room = db.Column(db.String(50))
    description = db.Column(db.Text)

    # Classification + tree (ADR-001)
    locationtypeid = db.Column(
        db.Integer,
        db.ForeignKey('locationtypes.locationtypeid'),
        nullable=True
    )
    parentlocationid = db.Column(
        db.Integer,
        db.ForeignKey('locations.locationid'),
        nullable=True,
        comment='Parent location for the site location tree'
    )

    # Map configuration
    mapimage = db.Column(db.String(500), comment='Path to floor map image')
    mapwidth = db.Column(db.Integer)
    mapheight = db.Column(db.Integer)

    # Location-level position used as fallback when an asset has no own coords
    # and no inheritsposition relationship resolves. ADR-001 position resolution
    # chain priority 3.
    mapx = db.Column(db.Integer, comment='Default X coordinate for assets at this location')
    mapy = db.Column(db.Integer, comment='Default Y coordinate for assets at this location')
    # Which drawing those coordinates are pixels of (ADR-017). A location is on a
    # level as much as an asset is, and an asset with no position of its own
    # inherits BOTH the coordinates and the level from here - inheriting the
    # coordinates alone would draw them on whatever level the asset claims.
    levelid = db.Column(
        db.Integer, db.ForeignKey('maplevels.levelid'), nullable=True, index=True,
        comment='Which level mapx/mapy are pixels of (ADR-017)')

    # Relationships
    locationtype = db.relationship('LocationType')
    parent = db.relationship('Location', remote_side=[locationid])

    @property
    def locationcode(self):
        """Derived operation/short code (leading token of the name)."""
        return derive_locationcode(self.locationname)

    def to_dict(self):
        data = super().to_dict()
        data['locationtypename'] = self.locationtype.locationtype if self.locationtype else None
        data['parentlocationname'] = self.parent.locationname if self.parent else None
        data['locationcode'] = self.locationcode
        return data

    def __repr__(self):
        return f"<Location {self.locationname}>"
