from sqlalchemy import Column, Integer, String, ForeignKey, DateTime
from sqlalchemy.orm import declarative_base, relationship

Base = declarative_base()


class ScanTarget(Base):
    """ScanTarget DB Model

    Attributes
    -------
    id : Column(Integer)
        The ID in the database
    ip : Column(Integer), optional
        The integer represented IP Address in the database
    hostname : Column(String)
        The hostname in the database
    updated_at : Column(DateTime)
        The DateTime when the ScanTarget was last updated
    """

    __tablename__ = "scan_target"

    # Unique ID
    id = Column(Integer, primary_key=True, unique=True)

    # Integer representation of an IP Address
    ip = Column(Integer, index=True, unique=True)

    # Corresponding hostname
    hostname = Column(String, index=True, unique=True)

    # Updated At
    updated_at = Column(DateTime())

    def __repr__(self):
        """The string representation of the class."""
        return (
            f"ScanTarget(id={self.id!r}, ip={self.ip!r}, "
            f"hostname={self.hostname!r}, updated_at={self.updated_at!r})"
        )


class ScanHistory(Base):
    """ScanHistory DB Model

    Attributes
    -------
    id : Column(Integer)
        The ID in the database
    target_id : Column(Integer)
        The ScanTarget ID reference
    results : Column(String)
        The CSV delimited string representing all open ports.
    created_at : Column(DateTime)
        The DateTime when the ScanHistory was created
    status : Column(String)
        The status of the ScanHistory (IN_PROGRESS, COMPLETE, FAILED)
    error : Column(String)
        The error, if any, of the ScanHistory
    target : relationship
        The ScanTarget relationship reference
    """

    __tablename__ = "scan_history"

    # Unique ID
    id = Column(Integer, primary_key=True, unique=True)

    # Scan Target Reference
    target_id = Column(Integer, ForeignKey("scan_target.id"))

    # Results (53 TCP, 53 UDP)
    results = Column(String)

    # Created At
    created_at = Column(DateTime())

    # Status (IN_PROGRESS, COMPLETE, FAILED)
    status = Column(String)

    # Error Message (If applicable)
    error = Column(String)

    # Relationship
    target = relationship("ScanTarget", foreign_keys=[target_id])

    def __repr__(self):
        """The string representation of the class."""
        return (
            f"ScanHistory(id={self.id!r}, target_id={self.target_id!r}, "
            f"results={self.results!r}, created_at={self.created_at!r}, "
            f"status={self.status!r}, error={self.error!r})"
        )
