import string
import random
from apps.authentication.models import User, Organization
from apps.pos_device.models import POSFreeProducts
from apps.product import models as product_models
from apps.pos_device.models import Device
from apps.herd.models import Rancher
from apps.core.models import BaseModel
from django.db import models


class InventoryEntry(BaseModel):
    entry_identity = models.CharField(max_length=50, null=True)
    distribution = models.ForeignKey(
        product_models.QuotaDistribution,
        on_delete=models.CASCADE,
        related_name='inventory_entry',
        null=True
    )
    organization = models.ForeignKey(
        product_models.Organization,
        on_delete=models.CASCADE,
        related_name="inventory",
        null=True
    )
    weight = models.PositiveBigIntegerField(default=0)
    balance = models.PositiveBigIntegerField(default=0)
    lading_number = models.CharField(max_length=50, null=True)
    delivery_address = models.TextField(blank=True, null=True)
    document = models.CharField(max_length=250, null=True)
    is_confirmed = models.BooleanField(default=False)
    notes = models.TextField(blank=True, null=True)

    def generate_entry_identity(self):  # noqa
        """ generate identity for every device """
        # prefix = "POS"
        while True:
            number_part = ''.join(random.choices(string.digits, k=6))
            code = f"{self.distribution.quota.quota_id}{number_part}"
            if not InventoryEntry.objects.filter(entry_identity=code).exists():
                return code

    @property
    def total_sold(self):
        return self.inventory_sales.aggregate(total=models.Sum('weight'))['total'] or 0

    @property
    def remaining_weight(self):
        return self.weight - self.total_sold

    def __str__(self):
        return f"distribution: {self.distribution.distribution_id}-{self.organization.name}"

    def save(self, *args, **kwargs):
        if not self.entry_identity:
            self.entry_identity = self.generate_entry_identity()
        super(InventoryEntry, self).save(*args, **kwargs)


class InventoryQuotaSaleTransaction(BaseModel):
    rancher = models.ForeignKey(
        Rancher,
        on_delete=models.CASCADE,
        related_name='transactions',
        null=True
    )
    rancher_fullname = models.CharField(max_length=150, null=True)
    rancher_mobile = models.CharField(max_length=25, null=True)
    pos_device = models.ForeignKey(
        Device,
        on_delete=models.CASCADE,
        related_name='transactions',
        null=True
    )
    transaction_id = models.CharField(max_length=50, null=True)
    seller_organization = models.ForeignKey(
        product_models.Organization,
        on_delete=models.CASCADE,
        related_name='inventory_sales',
        null=True
    )
    quota_distribution = models.ForeignKey(
        product_models.QuotaDistribution,
        on_delete=models.CASCADE,
        related_name='inventory_sales',
        null=True
    )
    inventory_entry = models.ForeignKey(
        InventoryEntry,
        on_delete=models.CASCADE,
        related_name='inventory_sales',
        null=True
    )
    weight = models.PositiveBigIntegerField(default=0)
    delivery_address = models.TextField(blank=True, null=True)
    transaction_price = models.PositiveBigIntegerField(default=0)
    price_paid = models.PositiveBigIntegerField(default=0)
    type_of_price = (
        ('card', 'CARD'),
        ('cash', 'CASH'),
        ('credit', 'CREDIT'),
        ('check', 'CHECK'),
    )
    price_type = models.CharField(choices=type_of_price, max_length=50, null=True)
    description = models.TextField(blank=True, null=True)
    product_type_choices = (
        ('gov', 'government'),
        ('free', 'free'),
    )
    product_type = models.CharField(max_length=20, choices=product_type_choices, default='free')
    herd_owners_number = models.PositiveBigIntegerField(default=0)
    transactions_number = models.PositiveBigIntegerField(default=0)
    status_type = (
        ('success', 'SUCCESS'),
        ('waiting', 'WAITING'),
        ('failed', 'Failed'),
    )
    transaction_status = models.CharField(choices=status_type, max_length=25, null=True)
    transaction_status_code = models.IntegerField(default=0)
    result_text = models.TextField(null=True)
    ref_num = models.CharField(max_length=50, null=True)
    terminal = models.CharField(max_length=50, null=True)
    payer_cart = models.CharField(max_length=50, null=True)
    pos_date = models.PositiveBigIntegerField(default=0)
    transaction_date = models.DateTimeField(auto_now_add=True, null=True)
    free_sale_state = models.BooleanField(default=False)
    pre_sale_state = models.BooleanField(default=False)
    additional = models.JSONField(default=dict)

    @property
    def total_weight(self):
        """ summation of total sold product weight """
        return sum(item.weight for item in self.items.all)

    def __str__(self):
        return f"Inventory Sale: {self.transaction_id}-{self.quota_distribution.distribution_id}"

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


class InventoryQuotaSaleItem(BaseModel):
    transaction = models.ForeignKey(
        InventoryQuotaSaleTransaction,
        on_delete=models.CASCADE,
        related_name='items',
        null=True
    )
    quota_distribution = models.ForeignKey(
        product_models.QuotaDistribution,
        on_delete=models.CASCADE,
        related_name='sale_items',
        null=True
    )
    gov_product = models.ForeignKey(
        product_models.Product,
        on_delete=models.CASCADE,
        related_name='sale_items',
        null=True
    )
    free_product = models.ForeignKey(
        POSFreeProducts,
        on_delete=models.CASCADE,
        related_name='sale_items',
        null=True
    )
    image = models.CharField(max_length=150, null=True)
    name = models.CharField(max_length=150, null=True)
    price_type = models.CharField(max_length=150, null=True)
    delivery_type = models.CharField(max_length=150, null=True)
    paid_type = models.CharField(max_length=150, null=True)
    item_type = models.CharField(max_length=150, null=True)
    unit = models.CharField(max_length=50, null=True)
    weight = models.PositiveBigIntegerField(default=0)
    unit_price = models.PositiveBigIntegerField(default=0)
    total_price = models.PositiveBigIntegerField(default=0)
    paid_price = models.PositiveBigIntegerField(default=0)
    is_extra = models.BooleanField(default=False)
    is_pre_sale = models.BooleanField(default=False)
    additional = models.JSONField(default=dict)
    livestock_statistic = models.JSONField(default=dict)
    item_share = models.JSONField(default=list)
    inventory_calculation = models.BooleanField(default=False)

    @property
    def product(self):
        return self.gov_product or self.free_product

    def __str__(self):
        return f'Item {self.product} - {self.weight} Kg - {self.total_price}'

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


class ExtraSale(BaseModel):
    organization = models.ForeignKey(
        Organization,
        on_delete=models.CASCADE,
        related_name='extra_sales',
        null=True
    )
    distribution = models.ForeignKey(
        product_models.QuotaDistribution,
        on_delete=models.CASCADE,
        related_name='extra_sales',
        null=True
    )
    transaction = models.ForeignKey(
        InventoryQuotaSaleTransaction,
        on_delete=models.CASCADE,
        related_name='transactions',
        null=True
    )
    sale_item = models.ForeignKey(
        InventoryQuotaSaleItem,
        on_delete=models.CASCADE,
        related_name='sale_items',
        null=True
    )
    weight = models.IntegerField(default=0)

    def __str__(self):
        return f'Extra Sale on {self.organization.name} - {self.distribution.distribution_id}'

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


class QuotaPreSaleItem(BaseModel):
    organization = models.ForeignKey(
        Organization,
        on_delete=models.CASCADE,
        related_name='pre_sales',
        null=True
    )
    distribution = models.ForeignKey(
        product_models.QuotaDistribution,
        on_delete=models.CASCADE,
        related_name='pre_sales',
        null=True
    )
    transaction = models.ForeignKey(
        InventoryQuotaSaleTransaction,
        on_delete=models.CASCADE,
        related_name='pre_sales',
        null=True
    )
    sale_item = models.ForeignKey(
        InventoryQuotaSaleItem,
        on_delete=models.CASCADE,
        related_name='pre_sale',
        null=True
    )
    weight = models.IntegerField(default=0)
    settlement_state = models.BooleanField(default=False)

    def __str__(self):
        return f'Distribution {self.distribution.distribution_id} - Transaction {self.transaction.transaction_id}'

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