from decimal import Decimal
from django.db import models
from django.conf import settings
from django.utils import timezone
from django.core.validators import MinValueValidator

ZERO=Decimal('0')
class Branch(models.Model):
    name=models.CharField('نام شعبه',max_length=120,unique=True)
    is_workshop=models.BooleanField('کارگاه تولیدی است',default=False)
    active=models.BooleanField('فعال',default=True)
    created_at=models.DateTimeField('تاریخ ایجاد',auto_now_add=True)
    class Meta: verbose_name='شعبه';verbose_name_plural='شعب'
    def __str__(self): return self.name

class Profile(models.Model):
    ROLES=[('admin','مدیر کل'),('buyer','مسئول خرید'),('branch','مدیر شعبه'),('workshop','مسئول کارگاه')]
    user=models.OneToOneField(settings.AUTH_USER_MODEL,on_delete=models.CASCADE,related_name='samshaf_profile',verbose_name='کاربر')
    role=models.CharField('نقش',max_length=12,choices=ROLES,default='branch')
    branch=models.ForeignKey(Branch,on_delete=models.PROTECT,verbose_name='شعبه مربوط',null=True,blank=True)
    class Meta: verbose_name='نقش و دسترسی کاربر';verbose_name_plural='نقش‌ها و دسترسی‌ها'
    def __str__(self):return f'{self.user.username} / {self.get_role_display()}'

class Category(models.Model):
    name=models.CharField('نام دسته',max_length=160)
    parent=models.ForeignKey('self',on_delete=models.PROTECT,related_name='children',null=True,blank=True,verbose_name='دسته والد')
    slug=models.SlugField('شناسه لاتین',max_length=90,unique=True)
    supplier=models.CharField('تأمین‌کننده',max_length=150,blank=True)
    order_note=models.CharField('راهنمای زمان سفارش و تحویل (نمایشی)',max_length=300,blank=True)
    position=models.PositiveIntegerField('ترتیب',default=0)
    active=models.BooleanField('فعال',default=True)
    class Meta: verbose_name='دسته‌بندی';verbose_name_plural='دسته‌بندی‌ها';ordering=['position','id']
    def __str__(self): return f'{self.parent.name} ← {self.name}' if self.parent_id else self.name

class Product(models.Model):
    category=models.ForeignKey(Category,on_delete=models.PROTECT,related_name='products',verbose_name='دسته')
    name=models.CharField('نام کالا',max_length=240)
    unit=models.CharField('واحد',max_length=60,default='عدد')
    minimum=models.DecimalField('حداقل موجودی',max_digits=12,decimal_places=2,default=ZERO,validators=[MinValueValidator(ZERO)])
    estimated_price=models.DecimalField('قیمت حدودی هر واحد (تومان)',max_digits=15,decimal_places=0,default=ZERO,validators=[MinValueValidator(ZERO)])
    note=models.CharField('توضیح و تبدیل واحد',max_length=280,blank=True)
    active=models.BooleanField('فعال',default=True)
    position=models.PositiveIntegerField('ترتیب',default=0)
    created_at=models.DateTimeField('ساخته‌شده',auto_now_add=True)
    class Meta: verbose_name='کالا';verbose_name_plural='کالاها';ordering=['category__position','position','id']
    def __str__(self):return self.name

class Stock(models.Model):
    branch=models.ForeignKey(Branch,on_delete=models.PROTECT,related_name='stocks',verbose_name='شعبه')
    product=models.ForeignKey(Product,on_delete=models.PROTECT,related_name='stocks',verbose_name='محصول')
    quantity=models.DecimalField('موجودی فعلی',max_digits=13,decimal_places=2,default=ZERO,validators=[MinValueValidator(ZERO)])
    updated_at=models.DateTimeField('آخرین ثبت',auto_now=True)
    updated_by=models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.SET_NULL,null=True,blank=True)
    class Meta: verbose_name='موجودی شعبه';verbose_name_plural='موجودی شعب';constraints=[models.UniqueConstraint(fields=['branch','product'],name='one_stock_per_branch_product')]
    def __str__(self):return f'{self.branch} / {self.product}: {self.quantity}'

class StockHistory(models.Model):
    stock=models.ForeignKey(Stock,on_delete=models.CASCADE,related_name='history')
    old_qty=models.DecimalField(max_digits=13,decimal_places=2)
    new_qty=models.DecimalField(max_digits=13,decimal_places=2)
    actor=models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.SET_NULL,null=True)
    changed_at=models.DateTimeField(auto_now_add=True,db_index=True)
    class Meta: verbose_name='تاریخچه موجودی';verbose_name_plural='تاریخچه موجودی‌ها';ordering=['-changed_at']

class PurchaseRequest(models.Model):
    STATUSES=[('pending','در انتظار بررسی'),('approved','تأییدشده'),('preparing','در حال تهیه / تولید'),('ready','آماده ارسال'),('dispatched','ارسال‌شده'),('partial','تحویل ناقص'),('delivered','تحویل‌شده'),('rejected','ردشده')]
    branch=models.ForeignKey(Branch,on_delete=models.PROTECT,related_name='purchase_requests',verbose_name='شعبه درخواست‌دهنده')
    category=models.ForeignKey(Category,on_delete=models.PROTECT,related_name='purchase_requests',verbose_name='دسته')
    requested_by=models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.SET_NULL,null=True,related_name='purchase_requests')
    note=models.TextField('توضیح',blank=True)
    client_token=models.CharField('شناسه جلوگیری از ثبت تکراری',max_length=36,unique=True,null=True,blank=True,editable=False)
    status=models.CharField('وضعیت',max_length=15,choices=STATUSES,default='pending')
    created_at=models.DateTimeField('ثبت درخواست',auto_now_add=True,db_index=True)
    updated_at=models.DateTimeField('آخرین تغییر',auto_now=True)
    class Meta: verbose_name='درخواست خرید';verbose_name_plural='درخواست‌های خرید';ordering=['-created_at']
    def __str__(self):return f'درخواست #{self.pk} / {self.branch}'
    @property
    def estimated_total(self):
        return sum((i.approved_or_requested_qty*i.price_snapshot for i in self.items.all()),ZERO)
    @property
    def has_unpriced(self):
        return any(i.price_snapshot==0 for i in self.items.all())

class RequestItem(models.Model):
    request=models.ForeignKey(PurchaseRequest,on_delete=models.CASCADE,related_name='items')
    product=models.ForeignKey(Product,on_delete=models.PROTECT)
    quantity=models.DecimalField('تعداد درخواستی',max_digits=13,decimal_places=2,validators=[MinValueValidator(Decimal('0.01'))])
    approved_qty=models.DecimalField('مقدار تأییدشده',max_digits=13,decimal_places=2,null=True,blank=True,validators=[MinValueValidator(ZERO)])
    received_qty=models.DecimalField('تحویل‌گرفته‌شده',max_digits=13,decimal_places=2,default=ZERO,validators=[MinValueValidator(ZERO)])
    price_snapshot=models.DecimalField('قیمت هنگام ثبت (تومان)',max_digits=15,decimal_places=0,default=ZERO)
    unit_snapshot=models.CharField('واحد هنگام ثبت',max_length=60)
    class Meta: verbose_name='قلم درخواست';verbose_name_plural='اقلام درخواست';constraints=[models.UniqueConstraint(fields=['request','product'],name='unique_product_per_request')]
    @property
    def approved_or_requested_qty(self):return self.approved_qty if self.approved_qty is not None else self.quantity
    @property
    def line_total(self):return self.approved_or_requested_qty*self.price_snapshot

class Notification(models.Model):
    recipient=models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE,related_name='samshaf_notifications')
    title=models.CharField(max_length=150)
    message=models.CharField(max_length=400,blank=True)
    url=models.CharField(max_length=240,default='/orders/')
    is_read=models.BooleanField(default=False,db_index=True)
    created_at=models.DateTimeField(auto_now_add=True)
    class Meta: verbose_name='اعلان';verbose_name_plural='اعلان‌ها';ordering=['-created_at']

class SystemLog(models.Model):
    LEVELS=[('INFO','رویداد'),('WARNING','هشدار'),('ERROR','خطا')]
    level=models.CharField('سطح',max_length=10,choices=LEVELS,default='INFO')
    event=models.CharField('نوع رویداد',max_length=80)
    message=models.TextField('شرح')
    actor=models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.SET_NULL,null=True,blank=True)
    path=models.CharField('مسیر',max_length=240,blank=True)
    created_at=models.DateTimeField('تاریخ',auto_now_add=True,db_index=True)
    class Meta: verbose_name='لاگ سامانه';verbose_name_plural='لاگ‌های سامانه';ordering=['-created_at']
    def __str__(self):return f'{self.level} / {self.event} / {self.created_at}'

class RuntimeSetting(models.Model):
    key=models.CharField(max_length=80,unique=True)
    value=models.CharField(max_length=250,blank=True)
    class Meta: verbose_name='تنظیم داخلی';verbose_name_plural='تنظیمات داخلی'
