from django.db import models
from django.contrib.auth import get_user_model
from common.models import NameSlugModel, BaseModel
from simple_history.models import HistoricalRecords
from django.core.exceptions import ValidationError
from decimal import Decimal
from django.utils import timezone
from django.core.validators import MinValueValidator
from django.conf import settings
from _helpers.utils import jalali_converter2

User = get_user_model()

class Item(NameSlugModel):
    """مدل آیتم‌های پیش‌فرض"""
    description = models.TextField(verbose_name="توضیحات", blank=True)
    unit_price = models.DecimalField(
        max_digits=15, 
        decimal_places=2, 
        verbose_name="قیمت واحد"
    )
    is_special = models.BooleanField(default=False, verbose_name='ویژه برای فاکتور نهایی')
    default_quantity = models.PositiveIntegerField(
        default=1, 
        verbose_name="تعداد پیش‌فرض"
    )
    is_default_in_quotes = models.BooleanField(
        default=False, 
        verbose_name="پیش‌فرض در پیش‌فاکتورها",
        help_text="این آیتم به صورت پیش‌فرض در همه پیش‌فاکتورها قرار می‌گیرد"
    )
    created_by = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="ایجاد کننده")
    history = HistoricalRecords()

    class Meta:
        verbose_name = "آیتم"
        verbose_name_plural = "آیتم‌ها"
        ordering = ['name']

    def __str__(self):
        return f"{self.name} - {self.unit_price} ریال"

class Quote(NameSlugModel):
    """مدل پیش‌فاکتور"""
    process_instance = models.ForeignKey(
        'processes.ProcessInstance', 
        on_delete=models.CASCADE, 
        verbose_name="نمونه فرآیند"
    )
    customer = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="مشترک")
    status = models.CharField(
        max_length=20,
        choices=[
            ('draft', 'پیش‌نویس'),
            ('sent', 'ارسال شده'),
            ('accepted', 'تایید شده'),
            ('rejected', 'رد شده'),
            ('expired', 'منقضی شده'),
        ],
        default='draft',
        verbose_name="وضعیت"
    )
    total_amount = models.DecimalField(
        max_digits=15, 
        decimal_places=2, 
        default=0, 
        verbose_name="مبلغ کل"
    )
    discount_percent = models.DecimalField(
        max_digits=5, 
        decimal_places=2, 
        default=0, 
        verbose_name="درصد تخفیف"
    )
    discount_amount = models.DecimalField(
        max_digits=15, 
        decimal_places=2, 
        default=0, 
        verbose_name="مبلغ تخفیف"
    )
    final_amount = models.DecimalField(
        max_digits=15, 
        decimal_places=2, 
        default=0, 
        verbose_name="مبلغ نهایی"
    )
    notes = models.TextField(verbose_name="یادداشت‌ها", blank=True)
    valid_until = models.DateField(verbose_name="معتبر تا")
    created_by = models.ForeignKey(
        User, 
        on_delete=models.CASCADE, 
        verbose_name="ایجاد کننده",
        related_name='created_quotes'
    )
    
    history = HistoricalRecords()

    class Meta:
        verbose_name = "پیش‌فاکتور"
        verbose_name_plural = "پیش‌فاکتورها"
        ordering = ['-created']

    def __str__(self):
        return f"پیش‌فاکتور {self.name} - {self.customer.get_full_name()}"

    def calculate_totals(self):
        """محاسبه مبالغ کل"""
        total = sum(item.total_price for item in self.items.filter(is_deleted=False).all())
        self.total_amount = total
        
        # محاسبه تخفیف
        if self.discount_percent > 0:
            self.discount_amount = (total * self.discount_percent) / 100
        else:
            self.discount_amount = 0
        
        # محاسبه مبلغ نهایی با احتساب مالیات
        base_amount = self.total_amount - self.discount_amount
        try:
            vat_rate = Decimal(str(getattr(settings, 'VAT_RATE', 0)))
        except Exception:
            vat_rate = Decimal('0')
        vat_amount = base_amount * vat_rate
        self.final_amount = base_amount + vat_amount
        self.save()

    def get_status_display_with_color(self):
        """نمایش وضعیت با رنگ"""
        status_colors = {
            'draft': 'secondary',
            'sent': 'primary',
            'accepted': 'success',
            'rejected': 'danger',
            'expired': 'warning',
        }
        color = status_colors.get(self.status, 'secondary')
        return '<span class="badge bg-{}">{}</span>'.format(color, self.get_status_display())

    def get_paid_amount(self):
        """خالص پرداختی (دریافتی از مشتری منهای پرداختی به مشتری) برای این پیش‌فاکتور بر اساس پرداخت‌های فاکتور مرتبط"""
        invoice = Invoice.objects.filter(quote=self).first()
        if not invoice:
            return Decimal('0')
        return sum((p.amount if p.direction == 'in' else -p.amount) for p in invoice.payments.filter(is_deleted=False).all())

    def get_remaining_amount(self):
        """مبلغ باقی‌مانده بر اساس پرداخت‌ها"""
        paid = self.get_paid_amount()
        remaining = self.final_amount - paid
        if remaining < 0:
            remaining = Decimal('0')
        return remaining

    def get_vat_amount(self) -> Decimal:
        """محاسبه مبلغ مالیات به صورت جداگانه بر اساس VAT_RATE."""
        base_amount = (self.total_amount or Decimal('0')) - (self.discount_amount or Decimal('0'))
        try:
            vat_rate = Decimal(str(getattr(settings, 'VAT_RATE', 0)))
        except Exception:
            vat_rate = Decimal('0')
        return base_amount * vat_rate

class QuoteItem(BaseModel):
    """مدل آیتم‌های پیش‌فاکتور"""
    quote = models.ForeignKey(Quote, on_delete=models.CASCADE, related_name='items', verbose_name="پیش‌فاکتور")
    item = models.ForeignKey(Item, on_delete=models.CASCADE, verbose_name="آیتم")
    quantity = models.PositiveIntegerField(verbose_name="تعداد")
    unit_price = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="قیمت واحد")
    total_price = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="قیمت کل")
    notes = models.TextField(verbose_name="یادداشت‌ها", blank=True)
    history = HistoricalRecords()

    class Meta:
        verbose_name = "آیتم پیش‌فاکتور"
        verbose_name_plural = "آیتم‌های پیش‌فاکتور"
        ordering = ['quote', 'item__name']

    def __str__(self):
        return f"{self.item.name} - {self.quantity} عدد"

    def save(self, *args, **kwargs):
        """محاسبه قیمت کل"""
        self.total_price = self.quantity * self.unit_price
        super().save(*args, **kwargs)
        # بروزرسانی مبالغ پیش‌فاکتور
        self.quote.calculate_totals()

class Invoice(NameSlugModel):
    """مدل فاکتور نهایی"""
    quote = models.ForeignKey(
        Quote, 
        on_delete=models.CASCADE, 
        verbose_name="پیش‌فاکتور مربوطه",
        null=True, 
        blank=True
    )
    process_instance = models.ForeignKey(
        'processes.ProcessInstance', 
        on_delete=models.CASCADE, 
        verbose_name="نمونه فرآیند"
    )
    customer = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="مشترک")
    status = models.CharField(
        max_length=20,
        choices=[
            ('draft', 'پیش‌نویس'),
            ('sent', 'ارسال شده'),
            ('paid', 'پرداخت شده'),
            ('partially_paid', 'نیمه پرداخت شده'),
            ('overdue', 'معوق'),
            ('cancelled', 'لغو شده'),
        ],
        default='draft',
        verbose_name="وضعیت"
    )
    total_amount = models.DecimalField(
        max_digits=15, 
        decimal_places=2, 
        default=0, 
        verbose_name="مبلغ کل"
    )
    discount_percent = models.DecimalField(
        max_digits=5, 
        decimal_places=2, 
        default=0, 
        verbose_name="درصد تخفیف"
    )
    discount_amount = models.DecimalField(
        max_digits=15, 
        decimal_places=2, 
        default=0, 
        verbose_name="مبلغ تخفیف"
    )
    final_amount = models.DecimalField(
        max_digits=15, 
        decimal_places=2, 
        default=0, 
        verbose_name="مبلغ نهایی"
    )
    due_date = models.DateField(verbose_name="تاریخ سررسید")
    notes = models.TextField(verbose_name="یادداشت‌ها", blank=True)
    created_by = models.ForeignKey(
        User, 
        on_delete=models.CASCADE, 
        verbose_name="ایجاد کننده",
        related_name='created_invoices'
    )
    history = HistoricalRecords()

    class Meta:
        verbose_name = "فاکتور"
        verbose_name_plural = "فاکتورها"
        ordering = ['-created']

    def __str__(self):
        return f"فاکتور {self.name} - {self.customer.get_full_name()}"

    def calculate_totals(self):
        """محاسبه مبالغ کل"""
        total = sum(item.total_price for item in self.items.all())
        self.total_amount = total
        
        # محاسبه تخفیف
        if self.discount_percent > 0:
            self.discount_amount = (total * self.discount_percent) / 100
        else:
            self.discount_amount = 0
        
        # محاسبه مبلغ نهایی با احتساب مالیات
        base_amount = self.total_amount - self.discount_amount
        try:
            vat_rate = Decimal(str(getattr(settings, 'VAT_RATE', 0)))
        except Exception:
            vat_rate = Decimal('0')
        vat_amount = base_amount * vat_rate
        self.final_amount = base_amount + vat_amount
        
        # وضعیت بر اساس مانده خالص (استفاده از تابع‌ها)
        paid = self.get_paid_amount()
        net_due = self.final_amount - paid
        
        if net_due == 0:
            self.status = 'paid'
        elif net_due > 0:
            # مشتری هنوز باید پرداخت کند
            self.status = 'partially_paid' if paid > 0 else 'sent'
        else:
            # شرکت باید به مشتری پرداخت کند
            self.status = 'partially_paid'
        
        self.save()

    def get_paid_amount(self):
        """مبلغ پرداخت شده بر اساس پرداخت‌ها (مثل Quote)"""
        return sum((p.amount if p.direction == 'in' else -p.amount) for p in self.payments.filter(is_deleted=False).all())

    def get_remaining_amount(self):
        """مبلغ باقی‌مانده بر اساس پرداخت‌ها (مثل Quote)"""
        paid = self.get_paid_amount()
        remaining = self.final_amount - paid
        return remaining

    def get_vat_amount(self) -> Decimal:
        """محاسبه مبلغ مالیات به صورت جداگانه بر اساس VAT_RATE."""
        base_amount = (self.total_amount or Decimal('0')) - (self.discount_amount or Decimal('0'))
        try:
            vat_rate = Decimal(str(getattr(settings, 'VAT_RATE', 0)))
        except Exception:
            vat_rate = Decimal('0')
        return base_amount * vat_rate


    def get_status_display_with_color(self):
        """نمایش وضعیت با رنگ"""
        status_colors = {
            'draft': 'secondary',
            'sent': 'primary',
            'paid': 'success',
            'partially_paid': 'info',
            'overdue': 'danger',
            'cancelled': 'warning',
        }
        color = status_colors.get(self.status, 'secondary')
        return '<span class="badge bg-{}">{}</span>'.format(color, self.get_status_display())

class InvoiceItem(BaseModel):
    """مدل آیتم‌های فاکتور"""
    invoice = models.ForeignKey(Invoice, on_delete=models.CASCADE, related_name='items', verbose_name="فاکتور")
    item = models.ForeignKey(Item, on_delete=models.CASCADE, verbose_name="آیتم")
    quantity = models.PositiveIntegerField(verbose_name="تعداد")
    unit_price = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="قیمت واحد")
    total_price = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="قیمت کل")
    notes = models.TextField(verbose_name="یادداشت‌ها", blank=True)
    history = HistoricalRecords()

    class Meta:
        verbose_name = "آیتم فاکتور"
        verbose_name_plural = "آیتم‌های فاکتور"
        ordering = ['invoice', 'item__name']

    def __str__(self):
        return f"{self.item.name} - {self.quantity} عدد"

    def save(self, *args, **kwargs):
        """محاسبه قیمت کل"""
        self.total_price = self.quantity * self.unit_price
        super().save(*args, **kwargs)
        # بروزرسانی مبالغ فاکتور
        self.invoice.calculate_totals()

class Payment(BaseModel):
    """مدل پرداخت‌ها"""
    invoice = models.ForeignKey(Invoice, on_delete=models.CASCADE, related_name='payments', verbose_name="فاکتور")
    amount = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="مبلغ پرداخت")
    direction = models.CharField(
        max_length=3,
        choices=[('in', 'دریافتی'), ('out', 'پرداختی')],
        default='in',
        verbose_name='نوع تراکنش'
    )
    payment_method = models.CharField(
        max_length=20,
        choices=[
            ('cash', 'نقدی'),
            ('bank_transfer', 'انتقال بانکی'),
            ('check', 'چک'),
            ('card', 'کارت بانکی'),
            ('other', 'سایر'),
        ],
        default='cash',
        verbose_name="روش پرداخت"
    )
    reference_number = models.CharField(max_length=100, verbose_name="شماره مرجع", blank=True, unique=True)
    payment_date = models.DateField(verbose_name="تاریخ پرداخت")
    notes = models.TextField(verbose_name="یادداشت‌ها", blank=True)
    receipt_image = models.ImageField(upload_to='payments/%Y/%m/%d/', null=True, blank=True, verbose_name="تصویر فیش")
    created_by = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="ثبت کننده")
    history = HistoricalRecords()

    class Meta:
        verbose_name = "پرداخت"
        verbose_name_plural = "پرداخت‌ها"
        ordering = ['-payment_date']

    def __str__(self):
        return f"پرداخت {self.amount} ریال - {self.invoice.name}"

    def save(self, *args, **kwargs):
        """بروزرسانی مبالغ فاکتور"""
        super().save(*args, **kwargs)
        # فقط مجدداً calculate_totals را صدا کن (مثل Quote)
        self.invoice.calculate_totals()

    def delete(self, using=None, keep_parents=False):
        """حذف نرم و بروزرسانی مبالغ فاکتور پس از حذف"""
        result = super().delete(using=using, keep_parents=keep_parents)
        try:
            self.invoice.calculate_totals()
        except Exception:
            pass
        return result

    def jpayment_date(self):
        return jalali_converter2(self.payment_date)
