"""ORM classes for the dmd-warehouse database
"""
from dmd import common
from sqlalchemy.orm import declarative_base
from sqlalchemy import (
    Column,
    Integer,
    String,
    Float,
    BigInteger,
    SmallInteger,
    ForeignKey,
    Date,
    Boolean
)
from sqlalchemy.orm import relationship
from datetime import datetime

Base = declarative_base()


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class DmdVersion(Base):
    """A representation of the ``dmd_version`` table.

    Parameters
    ----------
    dmd_version_id : `int`
        auto-incremented index
    version_day : `int`
        The number of days between the the DM+D database version release date
        and 1/1/2000.
    version_name : `str`
        The name of the DM+D database, this is the zip file name without the
        zip extension.
    dmd_id : `dmd.warehouse.orm.DmdId`
        The relationship to the `dmd_id` table
    dmd_name : `dmd.warehouse.orm.DmdName`
        The relationship to the `dmd_name` table
    """
    __tablename__ = 'dmd_version'

    dmd_version_id = Column(
        Integer, nullable=False, primary_key=True,
        doc="auto-incremented index"
    )
    version_day = Column(
        Integer, nullable=False,
        doc="The number of days between the the DM+D database version "
        "release date and 1/1/2000."
    )
    version_name = Column(
        String(255), nullable=False,
        doc="The name of the DM+D database, this is the zip file name without"
        " the zip extension."
    )

    # -------------------------------------------------------------------------#
    dmd_code = relationship(
        "DmdCode",
        back_populates='dmd_version'
    )
    dmd_name = relationship(
        "DmdName",
        back_populates='dmd_version'
    )
    unit_dose = relationship(
        "UnitDose",
        back_populates='dmd_version'
    )
    ingredient = relationship(
        "Ingredient",
        back_populates='dmd_version'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class DmdCode(Base):
    """A representation of the ``dmd_ids`` table.

    Parameters
    ----------
    dmd_id_pk : `int`
        auto-incremented index
    dmd_version_id : `int`
        The reference to the DM+D version ID where the ``dmd_id`` was first
        observed.
    dmd_id : `int`
        The DM+D ID, this is either a VMP or an AMP
    is_amp : `bool`
        The ID is an actual medicinal product not a virtual medicinal product.
    vmp_id : `int`
        The vmp_id that this maps to
    unit_dose_form_size : `float`
        Size of a single dose?
    """
    __tablename__ = 'dmd_code'

    dmd_id = Column(
        Integer, nullable=False, primary_key=True,
        doc="The ID (either AMP or VMP IDs)."
    )
    dmd_version_id = Column(
        Integer, ForeignKey('dmd_version.dmd_version_id'),
        nullable=False, index=True,
        doc="The primary key of the dmd_version table"
    )
    is_amp = Column(
        Boolean, nullable=False,
        doc="Is the dmd_id an actual medicinal product?"
    )
    is_removed = Column(
        Boolean, nullable=False, default=False,
        doc="Has the ID been removed the current DM+D?"
    )
    vmp_id = Column(
        Integer, nullable=False, index=True,
        doc="The VMP ID."
    )
    # vtm_id = Column(
    #     Integer, nullable=True,
    #     doc="The virtual therapeutic moiety ID."
    # )
    # unit_dose_form_size = Column(
    #     Float,
    #     doc="Size of a single dose?"
    # )

    # -------------------------------------------------------------------------#
    dmd_version = relationship(
        "DmdVersion",
        back_populates='dmd_code'
    )
    dmd_name = relationship(
        "DmdName",
        back_populates='dmd_code'
    )
    unit_dose = relationship(
        "UnitDose",
        back_populates='dmd_code'
    )
    ingredient = relationship(
        "Ingredient",
        back_populates='dmd_code'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class DmdName(Base):
    """A representation of the ``dmd_ids`` table.

    Parameters
    ----------
    dmd_name_id : `int`
        auto-incremented index
    dmd_id : `int`
        The dmd_id (either AMP ID or VMP ID). References the ``dmd_id`` table.
    dmd_version_id : `int`
        The reference to the DM+D version ID where the ``dmd_id`` was first
        observed.
    is_latest : `bool`
        Is the name/version combination the latest one.
    dmd_name : `str`
        The reference to the DM+D version ID where the ``dmd_id`` was first
        observed.
    dmd_name_type : `str`
        The DM+D ID, this is either a VMP or an AMP
    """
    __tablename__ = 'dmd_name'

    dmd_name_id = Column(
        Integer, nullable=False, primary_key=True,
        doc="auto-incremented index"
    )
    dmd_id = Column(
        Integer, ForeignKey('dmd_code.dmd_id'), nullable=False, index=True,
        doc="The dmd_id (either AMP ID or VMP ID). References the dmd_id"
        " table."
    )
    dmd_version_id = Column(
        Integer, ForeignKey('dmd_version.dmd_version_id'),
        nullable=False, index=True,
        doc="The primary key of the dmd_version table"
    )
    is_latest = Column(
        Boolean, nullable=False, default=False,
        doc="Is the name/version combination the latest one."
    )
    dmd_name = Column(
        String(700, collation='NOCASE'), nullable=False, index=True,
        doc="A name for the DMD ID."
    )
    dmd_name_type = Column(
        String(5), nullable=False,
        doc="The type of the name. either: name, short, long, prev"
    )

    # -------------------------------------------------------------------------#
    dmd_version = relationship(
        "DmdVersion",
        back_populates='dmd_name'
    )
    dmd_code = relationship(
        "DmdCode",
        back_populates='dmd_name'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class UnitDose(Base):
    """A representation of the ``unit_dose`` table.

    Parameters
    ----------
    dmd_name_id : `int`
        auto-incremented index
    dmd_id : `int`
        The dmd_id (either AMP ID or VMP ID). References the ``dmd_id`` table.
    dmd_version_id : `int`
        The reference to the DM+D version ID where the ``dmd_id`` was first
        observed.
    is_latest : `bool`
        Is the name/version combination the latest one.
    dmd_name : `str`
        The reference to the DM+D version ID where the ``dmd_id`` was first
        observed.
    dmd_name_type : `str`
        The DM+D ID, this is either a VMP or an AMP
    """
    __tablename__ = 'unit_dose'

    unit_dose_id = Column(
        Integer, nullable=False, primary_key=True,
        doc="auto-incremented index"
    )
    dmd_id = Column(
        Integer, ForeignKey('dmd_code.dmd_id'), nullable=False, index=True,
        doc="The dmd_id (either AMP ID or VMP ID). References the dmd_id"
        " table."
    )
    dmd_version_id = Column(
        Integer, ForeignKey('dmd_version.dmd_version_id'),
        nullable=False, index=True,
        doc="The primary key of the dmd_version table"
    )
    is_latest = Column(
        Boolean, nullable=False, default=False,
        doc="Is the name/version combination the latest one."
    )
    dose_form_ind = Column(
        String(255), nullable=False,
        doc="The dose form indicator string ``virt_med_prod.dose_form_ind_cd``"
    )
    unit_dose_form_size = Column(
        Float, nullable=True,
        doc="The ``virt_med_prod.unit_dose_form_size``. The size of what "
        "is considered a single unit dose"
    )
    unit_dose_form_units = Column(
        String(255),
        doc="The units of the unit_dose_form_size. "
        "``virt_med_prod.unit_meas_ud_cd``"
    )
    unit_dose_form_type = Column(
        String(255),
        doc="The super-unit of a single dose: ``virt_med_prod.unit_meas_cd``"
    )

    # -------------------------------------------------------------------------#
    dmd_version = relationship(
        "DmdVersion",
        back_populates='unit_dose'
    )
    dmd_code = relationship(
        "DmdCode",
        back_populates='unit_dose'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class Ingredient(Base):
    """A representation of the ``ingredient`` table.

    Parameters
    ----------
    dmd_name_id : `int`
        auto-incremented index
    dmd_id : `int`
        The dmd_id (either AMP ID or VMP ID). References the ``dmd_id`` table.
    dmd_version_id : `int`
        The reference to the DM+D version ID where the ``dmd_id`` was first
        observed.
    is_latest : `bool`
        Is the name/version combination the latest one.
    dmd_name : `str`
        The reference to the DM+D version ID where the ``dmd_id`` was first
        observed.
    dmd_name_type : `str`
        The DM+D ID, this is either a VMP or an AMP
    """
    __tablename__ = 'ingredient'

    ing_pk = Column(
        Integer, nullable=False, primary_key=True,
        doc="auto-incremented index"
    )
    dmd_id = Column(
        Integer, ForeignKey('dmd_code.dmd_id'), nullable=False, index=True,
        doc="The dmd_id (either AMP ID or VMP ID). References the dmd_id"
        " table."
    )
    dmd_version_id = Column(
        Integer, ForeignKey('dmd_version.dmd_version_id'),
        nullable=False, index=True,
        doc="The primary key of the dmd_version table"
    )
    is_latest = Column(
        Boolean, nullable=False, default=False,
        doc="Is the name/version combination the latest one."
    )
    ing_id = Column(
        Integer, nullable=False,
        doc="The DM+D vmp_ingredient_id."
    )
    ing_name = Column(
        String(255, collation='NOCASE'), nullable=False,
        doc="The DM+D vmp_ingredient_id."
    )
    stren_val_num = Column(
        Float, nullable=True,
        doc="The ``virt_med_prod.unit_dose_form_size``. The size of what "
        "is considered a single unit dose"
    )
    stren_val_num_unit = Column(
        String(255), nullable=True,
        doc="The ``virt_med_prod.unit_dose_form_size``. The size of what "
        "is considered a single unit dose"
    )
    stren_val_den = Column(
        Float, nullable=True,
        doc="The ``virt_med_prod.unit_dose_form_size``. The size of what "
        "is considered a single unit dose"
    )
    stren_val_den_unit = Column(
        String(255), nullable=True,
        doc="The ``virt_med_prod.unit_dose_form_size``. The size of what "
        "is considered a single unit dose"
    )

    # -------------------------------------------------------------------------#
    dmd_version = relationship(
        "DmdVersion",
        back_populates='ingredient'
    )
    dmd_code = relationship(
        "DmdCode",
        back_populates='ingredient'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)
