import random

from django.db import models
from jdatetime import datetime

from apps.authentication import models as auth_models
from apps.authentication.models import Organization
from apps.core.models import BaseModel
from apps.tag.tools import tag_code_serial_scanning


class Tag(BaseModel):
    country_code = models.IntegerField(default=364, help_text='it is static 364, iran country code')
    static_code = models.IntegerField(default=0, help_text='always a static number')
    ownership_code = models.IntegerField(default=0, help_text='ownership code of organizations like: 51, 52, etc')
    species_code = models.IntegerField(default=0, help_text='code of livestock type like: 1->sheep')
    serial = models.CharField(max_length=8, help_text='7 digit number as serial on tag code')
    tag_code = models.CharField(max_length=20, null=True)
    organization = models.ForeignKey(
        auth_models.Organization,
        on_delete=models.CASCADE,
        related_name='tag_organization',
        null=True
    )
    status_choices = (
        ('F', 'Free'),
        ('R', 'Reserved'),
        ('A', 'Assigned'),
    )
    status = models.CharField(max_length=20, default="F")

    def __str__(self):
        return f'{self.id}-{self.tag_code}'

    def save(self, *args, **kwargs):
        # set zeros for serial
        if not self.tag_code:
            self.serial = tag_code_serial_scanning(self.serial)
        if not self.tag_code:
            # set total tag code
            self.tag_code = f"{self.country_code}" \
                            f"{self.static_code}" \
                            f"{self.ownership_code}" \
                            f"{self.species_code}" \
                            f"{self.serial}"
        super(Tag, self).save(*args, **kwargs)


class TagBatch(BaseModel):
    batch_identity = models.CharField(
        unique=True,
        max_length=50,
        null=True
    )
    organization = models.ForeignKey(
        Organization,
        on_delete=models.CASCADE,
        related_name='tag_batches',
        null=True,
        help_text="creator org of tag batch"
    )
    request_number = models.CharField(
        max_length=50,
        default="0",
        null=True
    )

    tag = models.ManyToManyField(Tag, related_name='batches')
    species_code = models.IntegerField(default=0)
    serial_from = models.PositiveBigIntegerField(default=0)
    serial_to = models.PositiveBigIntegerField(default=0)

    status = models.CharField(
        max_length=20,
        choices=[
            ('created', 'CREATED'),
            ('distributed', 'DISTRIBUTED'),
        ],
        null=True,
        default='created'
    )
    description = models.TextField(null=True, blank=True)

    def __str__(self):
        return f'{self.id}-{self.request_number}-{self.organization.name}'

    def save(self, *args, **kwargs):
        return super(TagBatch, self).save(*args, **kwargs)


class TagDistribution(BaseModel):
    dist_identity = models.CharField(max_length=20, default="0", unique=True, null=True)
    batch = models.ForeignKey(
        TagBatch,
        on_delete=models.CASCADE,
        related_name='tag_distributions',
        null=True
    )
    tag = models.ManyToManyField(Tag, related_name='distributions')
    assigner_org = models.ForeignKey(
        Organization,
        on_delete=models.CASCADE,
        related_name='assigner_tag_dist',
        null=True
    )
    assigned_org = models.ForeignKey(
        Organization,
        on_delete=models.CASCADE,
        related_name='assigned_tag_dist',
        null=True
    )
    species_code = models.IntegerField(default=0)
    distributed_number = models.IntegerField(default=0)
    is_closed = models.BooleanField(default=False)

    def __str__(self):
        return f'{self.id}-{self.distributed_number}-{self.assigned_org.name}'

    def save(self, *args, **kwargs):
        return super(TagDistribution, self).save(*args, **kwargs)


class TagDistributionBatch(BaseModel):
    dist_batch_identity = models.CharField(max_length=20, default="0", unique=True, null=True)
    assigner_org = models.ForeignKey(
        Organization,
        on_delete=models.CASCADE,
        related_name='from_tag_distribution_batch',
        null=True
    )
    assigned_org = models.ForeignKey(
        Organization,
        on_delete=models.CASCADE,
        related_name="to_tag_distribution_batch",
        null=True
    )
    distribution_type = models.CharField(
        choices=(
            ('random', 'RANDOM'),
            ('batch', 'BATCH'),
        ),
        max_length=20,
        null=True,
        default='batch'
    )
    distributions = models.ManyToManyField(TagDistribution, related_name='tag_distribution_batch')
    total_tag_count = models.IntegerField(default=0)
    is_closed = models.BooleanField(default=False)

    def __str__(self):
        return f'{self.id}'

    def save(self, *args, **kwargs):
        return super(TagDistributionBatch, self).save(*args, **kwargs)


class TagAssignment(BaseModel):
    organization = models.ForeignKey(
        auth_models.Organization,
        on_delete=models.CASCADE,
        related_name='tag_assignment_org',
        null=True
    )
    document = models.CharField(max_length=150, null=True)
    serial_sender_part = models.IntegerField(default=0)
    serial_recipient_part = models.IntegerField(default=0)
    serial_date_part = models.CharField(max_length=3, null=True)
    serial_random_part = models.IntegerField(default=0)
    serial = models.CharField(max_length=20, null=True)
    status_choices = (
        ('A', 'Accept'),
        ('W', 'Waiting'),
        ('C', 'Cancel'),
        ('E', 'Exited'),
    )
    status = models.CharField(max_length=1, choices=status_choices, default="W")

    def __str__(self):
        return f'{self.serial}-{self.organization.name}'

    def save(self, *args, **kwargs):
        self.serial_recipient_part = self.organization.type.code
        self.serial_date_part = str(
            datetime.now().year
        )[3] + str(
            datetime.now().month
        )
        self.serial_random_part = random.randint(1000, 9999)
        if not self.serial:
            self.serial = f"" \
                          f"{self.serial_sender_part}" \
                          f"{self.serial_recipient_part}" \
                          f"{self.serial_date_part}" \
                          f"{self.serial_random_part}"
        super(TagAssignment, self).save(*args, **kwargs)


class AllocatedTags(BaseModel):
    tag = models.ForeignKey(
        Tag,
        on_delete=models.CASCADE,
        related_name='allocated_tags',
        null=True
    )
    assignment = models.ForeignKey(
        TagAssignment,
        on_delete=models.CASCADE,
        related_name='assigned_allocated_tags',
        null=True
    )
    species_code = models.IntegerField(default=0)
    status_choices = (
        ('A', 'Accept'),
        ('W', 'Waiting'),
        ('C', 'Cancel')
    )
    status = models.CharField(max_length=1, default='W')

    def __str__(self):
        return f'{self.tag.tag_code}-{self.assignment.serial}'

    def save(self, *args, **kwargs):
        super(AllocatedTags, self).save(*args, **kwargs)


class TemporaryTags(BaseModel):
    tag = models.CharField(max_length=150, null=True)
    herd_code = models.CharField(max_length=150, null=True)
    gender = models.CharField(max_length=150, null=True)
    birthdate = models.CharField(max_length=150, null=True)
    type = models.CharField(max_length=150, null=True)
    agent_code = models.CharField(max_length=150, null=True)
    agriculture_unique_id = models.CharField(max_length=150, null=True)
    keeper_agent = models.CharField(max_length=150, null=True)
    registerer_user = models.CharField(max_length=150, null=True)
    sync_status = models.CharField(max_length=150, null=True)

    def save(self, *args, **kwargs):
        super(TemporaryTags, self).save(*args, **kwargs)
