from sqlalchemy import Column, Integer, String, ForeignKey

from rdr_server.common.enums import SampleStatus
from rdr_server.model.base_model import BaseModel, ModelMixin, UTCDateTime, ModelEnum


class BiobankStoredSample(ModelMixin, BaseModel):
    """Physical sampels which have been reported as received at Biobank.

    Each participant has an associated list of samples. Biobank uploads a list of all received
    samples periodically, and we update our list of stored samples to match. The output is a
    reconciliation report of ordered and stored samples; see BiobankOrder.

    Note that additional columns appear in the CSV uploaded from Biobank but are not persisted since
    they are unused in the reconciliation report; we also only exclude child samples.

    Additional field information from biobank:

      A sample family (family_id) is created upon a parent tube being created. The family
      contains study, visit, parent specimen information and others. Knowing the study,
      visit and specimen information we are able to capture the test code value from the
      study build information.  Each sample is then linked to the family by their family id.

      Order Identifier (biobank_order_identifier.value) is the unique id generated for
      each order placed into MayoLink. This value has two different phases, before Aug
      2018 and after.

      Sample Order Id (biobank_ordered_sample.order_id) is the unique id generated by MayoLink as a
      internal primary key value.

      Sample Id (biobank_stored_sample_id) is the unique specimen id. Each sample created has a
      unique Id. Sample ids are contained within a family. Family is created at same time the
      parent tube is created.

      Specimen Id for this project now is the order id plus an extra 4 numeric values.
      First 2 represent study and the next two are identifying the test we are receiving.


    """
    __tablename__ = 'biobank_stored_sample'

    # A unique ID assigned by Biobank for the sample. (AKA "RLIMS Sample ID.)
    # We omit autoincrement=False to avoid warnings & instead validate clients provide an ID upstream.
    biobankStoredSampleId = Column('biobank_stored_sample_id', String(80), unique=True)

    # The participant the sample is associated to. We use Biobank's ID for streamlined importing.
    biobankId = Column('biobank_id', Integer, ForeignKey('participant.biobank_id'))

    # The biobank order identifier. to enable joining on reconciliation report.
    biobankOrderIdentifier = Column('biobank_order_identifier', String(80), nullable=False)
    # Which test was performed to produce this sample (ex: "1UR10" for blood draw). Rarely, the same
    # test may be performed multiple times for the same participant.
    test = Column('test', String(80), nullable=False)

    # Timestamp when Biobank finished receiving/preparing the sample (status changed from "In Prep"
    # to "In Circulation" in Mayo). This is the end time used for order-to-sample latency measurement.
    # We may receive samples before they are confirmed (and see a confirmed date added later).
    confirmed = Column('confirmed', UTCDateTime)

    # Timestamp when Biobank received / created the sample.
    # created = Column('created', UTCDateTime)

    # sample status, includes all the statuses from SampleStatus Enum.
    status = Column('status', ModelEnum(SampleStatus), default=SampleStatus.RECEIVED)

    # Timestamp sample was disposed.
    disposed = Column('disposed', UTCDateTime)

    # Sample family ID
    family_id = Column('family_id', String(80), nullable=True)
