"""Machines plugin models."""

from shopdb.api import db, BaseModel


class MachineType(BaseModel):
    """
    Machine type classification.

    Examples: CNC, CMM, Lathe, Grinder, EDM, Part Marker, etc.
    """
    __tablename__ = 'machinetypes'

    machinetypeid = db.Column(db.Integer, primary_key=True)
    machinetype = db.Column(db.String(100), unique=True, nullable=False)
    description = db.Column(db.Text)
    icon = db.Column(db.String(50), comment='Icon name for UI')
    color = db.Column(db.String(20), comment='CSS color for UI/map markers')

    def __repr__(self):
        return f"<MachineType {self.machinetype}>"


class Machine(BaseModel):
    """
    Machine-specific extension data.

    Links to core Asset table via assetid.
    Stores machine-specific fields like type, model, vendor, etc.
    """
    __tablename__ = 'machines'

    machineid = db.Column(db.Integer, primary_key=True)

    # Link to core asset
    assetid = db.Column(
        db.Integer,
        db.ForeignKey('assets.assetid', ondelete='CASCADE'),
        unique=True,
        nullable=False,
        index=True
    )

    # Machine classification
    machinetypeid = db.Column(
        db.Integer,
        db.ForeignKey('machinetypes.machinetypeid'),
        nullable=True
    )

    # Vendor and model
    vendorid = db.Column(
        db.Integer,
        db.ForeignKey('vendors.vendorid'),
        nullable=True
    )
    modelnumberid = db.Column(
        db.Integer,
        db.ForeignKey('models.modelnumberid'),
        nullable=True
    )

    # Machine-specific fields
    requiresmanualconfig = db.Column(
        db.Boolean,
        default=False,
        comment='Multi-PC machine needs manual configuration'
    )
    islocationonly = db.Column(
        db.Boolean,
        default=False,
        comment='Virtual location marker (not actual machine)'
    )

    # Maintenance tracking
    lastmaintenancedate = db.Column(db.DateTime, nullable=True)
    nextmaintenancedate = db.Column(db.DateTime, nullable=True)
    maintenanceintervaldays = db.Column(db.Integer, nullable=True)

    # Controller info (for CNC machines)
    controllervendorid = db.Column(
        db.Integer,
        db.ForeignKey('vendors.vendorid'),
        nullable=True,
        comment='Controller vendor (e.g., FANUC)'
    )
    controllermodelid = db.Column(
        db.Integer,
        db.ForeignKey('models.modelnumberid'),
        nullable=True,
        comment='Controller model (e.g., 31B)'
    )

    # Relationships
    asset = db.relationship(
        'Asset',
        backref=db.backref('machine', uselist=False, lazy='joined')
    )
    machinetype = db.relationship('MachineType', backref='machines')
    vendor = db.relationship('Vendor', foreign_keys=[vendorid], backref='machine_items')
    model = db.relationship('Model', foreign_keys=[modelnumberid], backref='machine_items')
    controllervendor = db.relationship('Vendor', foreign_keys=[controllervendorid], backref='machine_controllers')
    controllermodel = db.relationship('Model', foreign_keys=[controllermodelid], backref='machine_controller_models')

    __table_args__ = (
        db.Index('idx_machine_type', 'machinetypeid'),
        db.Index('idx_machine_vendor', 'vendorid'),
    )

    def __repr__(self):
        return f"<Machine {self.assetid}>"

    def to_dict(self):
        """Convert to dictionary with related names."""
        result = super().to_dict()

        # Add related object names
        if self.machinetype:
            result['machinetypename'] = self.machinetype.machinetype
        if self.vendor:
            result['vendorname'] = self.vendor.vendor
        if self.model:
            result['modelname'] = self.model.modelnumber
            if self.model.imageurl:
                result['imageurl'] = self.model.imageurl
            # The catalog model already knows its maker, so an asset that has a
            # model but no vendor of its own is showing a blank the database can
            # fill. Flagged rather than merged silently: the edit form still has
            # an empty vendor box, and a page implying otherwise would be lying.
            if not self.vendor and self.model.vendor:
                result['vendorname'] = self.model.vendor.vendor
                result['vendorfrommodel'] = True
            # Exposed under its OWN name. modeltypes is the catalog-wide list
            # covering every kind of asset, so it is not interchangeable with
            # this asset's own type and must never be substituted for it.
            if self.model.modeltype:
                result['modeltypename'] = self.model.modeltype.modeltype

        # Add controller info
        if self.controllervendor:
            result['controllervendorname'] = self.controllervendor.vendor
        if self.controllermodel:
            result['controllermodelname'] = self.controllermodel.modelnumber

        return result
