from django.db import models
from django.contrib.auth.models import User
from django.utils import timezone
from django.core.exceptions import ValidationError
from django_jalali.db import models as jmodels
import jdatetime

class Role(models.Model):

    ROLE_CHOICES = [
        ('ادمین_اصلی', 'ادمین_اصلی'),
        ('فرماندهی', 'فرماندهی'),
        ('جانشین','جانشین'),
        ('اعضای_کانون', 'اعضای_کانون'),
        ('نیرو_انسانی', 'نیرو_انسانی'),
        ('امام_جماعت', 'امام_جماعت'),
        ('ورزشی_و_اردویی', 'ورزشی_و_اردویی'),
        ('تعلیم_و_تربیت', 'تعلیم_و_تربیت'),
        ('علمی_و_آموزشی', 'علمی_و_آموزشی'),
        ("حفاظت", "حفاظت"),
        ( 'سرگروه', 'سرگروه'),
        ("خانواده", "خانواده"),
        ('اعضای_شورا', 'اعضای_شورا'),


    ]

    name = models.CharField(
        max_length=50, choices=ROLE_CHOICES, verbose_name='عنوان (نام)')
    description = models.TextField(
        blank=True, null=True, verbose_name='توضیحات')
    can_views_self = models.BooleanField(
        default=False, verbose_name="دیدن اطلاعات خود؟")
    can_views_ReportCard = models.BooleanField(
        default=False, verbose_name="دیدن کارنامه خود؟")
    can_views_users = models.BooleanField(
        default=False, verbose_name="دیدن اطلاعات کاربران؟")
    can_add_user = models.BooleanField(
        default=False, verbose_name="اضافه کردن کاربر؟")
    can_edit_user = models.BooleanField(
        default=False, verbose_name="ویرایش کردن کاربر؟")
    can_delete_user = models.BooleanField(
        default=False, verbose_name="حذف کردن کاربر؟")
    can_define_roles = models.BooleanField(
        default=False, verbose_name="تعریف کردن نقش؟")
    can_add_ReportCard = models.BooleanField(
        default=False, verbose_name="اضافه کردن کارنامه؟")
    can_Cold_storage = models.BooleanField(
        default=False, verbose_name="اعطا سردوشی؟")
    can_task = models.BooleanField(
        default=False, verbose_name="اضافه کردن ماموریت؟")
    can_add_ring = models.BooleanField(
        default=False, verbose_name="اضافه کردن حلقه؟")

    class Meta:
        verbose_name = 'نقش'
        verbose_name_plural = 'نقش ها'

    def __str__(self):
        return self.name


class Person(models.Model):
    user = models.OneToOneField(
        User, on_delete=models.CASCADE, verbose_name='کاربر'  )
    role = models.ManyToManyField(Role, verbose_name='نقش')
    national_code = models.CharField( unique=True ,max_length=10, verbose_name='کدملی')
    
    class Meta:
        verbose_name = 'شخص'
        verbose_name_plural = 'اشخاص'

    def __str__(self):
        return f"{self.user.first_name} {self.user.last_name}"


# اطلاعات شخصی
class PersonPrivateInfo(models.Model):
    EDU_CHOICES = (
        ('زیر سیکل', 'زیر سیکل'),
        ( 'سیکل', 'سیکل'),
        ('دیپلم', 'دیپلم'),
        ('فوق دیپلم', 'فوق دیپلم'),
        ('لیسانس', 'لیسانس'),
        ( 'فوق لیسانس', 'فوق لیسانس'),
        ('دکتری', 'دکتری'),
    )

    GENDER_CHOICES = (
        ('آقا', 'آقا'),
        ( 'خانم', 'خانم'),
    )

    Ansewr_CHOICE= (
        ('بله','بله'),
        ('خیر','خیر'),
        )
    
    person = models.OneToOneField(Person,
                                  on_delete=models.CASCADE,
                                  verbose_name='کاربر',
                                   related_name='person_private_info')
    pic = models.ImageField(upload_to='media/persons/',
                            verbose_name='تصویر',
                            null=True,
                            blank=True)
    birthday = jmodels.jDateField( verbose_name='تاریخ تولد*',max_length=10,
                                    null=False,
                                    blank=False)
    birth_place = models.CharField(max_length=100,
                                   verbose_name='محل تولد',
                                   null=True,
                                   blank=True,default= "کرج")
    gender = models.CharField(verbose_name="جنسیت",
                              null=True,
                              blank=True,
                              max_length=10,
                              choices=GENDER_CHOICES,default = "آقا")
    phone = models.CharField(max_length=11,
                             verbose_name="شماره موبایل",
                             null=True,
                             blank=True,default = "-")
    father_name = models.CharField(max_length=110,
                                   verbose_name="نام پدر",
                                   null=False,
                                   blank=False)
    father_phone = models.CharField(max_length=11,
                                    verbose_name="شماره تماس پدر",
                                    null=True,
                                    blank=True,default = "-")
    fatherIsAlive = models.CharField(verbose_name="پدر در قید حیات است؟",
                              null=True,
                              blank=True,
                              max_length=10,
                              choices=Ansewr_CHOICE,default = "بله")
    father_grade = models.CharField(
        max_length=100, choices=EDU_CHOICES, verbose_name="تحصیلات پدر", null=True, blank=True,default = "-")
    fatherJob = models.CharField(
        max_length=150, verbose_name="شغل پدر", null=True, blank=True,default = "-")
    motherIsAlive = models.CharField(verbose_name="مادر در قید حیات است؟",
                              null=True,
                              blank=True,
                              max_length=10,
                              choices=Ansewr_CHOICE,default = "بله")
    mother_phone = models.CharField(
        max_length=11, verbose_name="شماره تماس مادر", null=True, blank=True,default = "-")
    mother_name = models.CharField(
        max_length=150, verbose_name="نام و نام خانوادگی مادر", null=True, blank=True,default = "-")
    mother_grade = models.CharField(
        max_length=100, choices=EDU_CHOICES, verbose_name="تحصیلات مادر", null=True, blank=True,default = "-")
    motherJob = models.CharField(
        max_length=150, verbose_name="شغل مادر", null=True, blank=True,default = "-")
    

    class Meta:
        verbose_name = 'اطلاعات شخصی'
        verbose_name_plural = 'اطلاعات شخصی'

    def __str__(self):
        return f"{self.person.user.first_name}_{self.person.user.last_name}"
    


class PersonAddress(models.Model):
    TYPE_CHOICES = (
        ( 'محل سکونت', 'محل سکونت'),
        ('محل کار', 'محل کار'),
        ( 'محل کار پدر', 'محل کار پدر'),
    )
    person = models.ForeignKey(Person,
                               on_delete=models.CASCADE,
                               related_name='person_address',
                               verbose_name='کاربر')
    typee = models.CharField(max_length=100,
                             verbose_name='عنوان آدرس',
                             choices=TYPE_CHOICES,
                               null=True,
                               blank=True )
    address = models.CharField(max_length=250,
                               verbose_name='آدرس',
                               null=True,
                               blank=True)
    postal_code = models.CharField(max_length=10,
                                   verbose_name='کدپستی',
                                   null=True,
                                   blank=True)
    tell = models.CharField(max_length=11,
                            verbose_name='تلفن ثابت',
                            null=True,
                            blank=True)
    location = models.CharField(max_length=250,
                                verbose_name='موقعیت',
                                null=True,
                                blank=True)

    class Meta:
        verbose_name = 'آدرس'
        verbose_name_plural = 'آدرس‌ها'

    def __str__(self):
        return f"{self.person.user.first_name} {self.person.user.last_name}_{self.typee}"


class PersonCultural(models.Model):

    RASTE_CHOICES = (
        ('ورزشی و اردویی', 'ورزشی و اردویی'),
        ('هییت', 'هییت'),
        ('مالی', 'مالی'),
        ('فرهنگی', 'فرهنگی'),
        ('علمی و آموزشی', 'علمی و آموزشی'),
        ('حفا', 'حفا'),
        ('تعلیم و تربیت', 'تعلیم و تربیت'),
        ('اداری', 'اداری'),
        ( 'اجتماعی', 'اجتماعی'),
        ('عملیات', 'عملیات'),
        ('جانشین', 'جانشین'),
        ('فرماندهی', 'فرماندهی'),
        ('اطلاعات','اطلاعات'),
    

    )

    TARBYAT_CHOICES = (
        ('رابط', 'رابط'),
        ( 'سرگروه', 'سرگروه'),
        ('مربی', 'مربی'),
        ('شورا ی سیاست گذاری','شورا ی سیاست گذاری')
    )
    OZVIAT_CHOICES = (
        ('عادی', 'عادی'),
        ('فعال', 'فعال'),
        ('کادر', 'کادر'),
    )
    SARDOSHI_CHOICES = (
        ('محب', 'محب'),
        ('صابر', 'صابر'),
        ( 'خادم', 'خادم'),
        ('جاهد', 'جاهد'),
        ('معین', 'معین'),
        ( 'شاهد', 'شاهد'),
    )
    person = models.OneToOneField(Person,
                                  on_delete=models.CASCADE,
                                  related_name='person_cultural',
                                  verbose_name='کاربر')
    raste_categories = models.CharField(max_length=20,
                                        verbose_name='رسته',
                                        choices=RASTE_CHOICES,null=True,blank=True,default = "اداری")
    ozviat_categories = models.CharField(max_length=20,
                                         verbose_name='عضویت',
                                         choices=OZVIAT_CHOICES,null=True,blank=True,default = "عادی")
    tarbyat_categories = models.CharField(max_length=20,
                                          verbose_name='رده‌تربیتی',
                                          choices=TARBYAT_CHOICES,null=True,blank=True,default = "رابط")
    sardoshi_categories = models.CharField(max_length=20,
                                           verbose_name='سردوشی',
                                           choices=SARDOSHI_CHOICES,null=True,blank=True,default = "محب")

    date_enter = jmodels.jDateField(verbose_name='تاریخ ورود به مسجد',
                                      null=True,
                                      blank=True)
    Psychological_test = models.FileField(upload_to='media/Psychological_test/',
                            verbose_name='نتیجه تست',
                            null=True,
                            blank=True,default = "-")
    first_major_name = models.CharField(max_length=100,
                                        verbose_name='نام اولین مربی',
                                        null=True,
                                        blank=True,default = "-")
    enter_type = models.CharField(max_length=100,
                                  verbose_name='نحوه جذب',
                                  null=True,
                                  blank=True,default = "-")
    description = models.TextField(
        verbose_name='توضیحات',
        null=True,
        blank=True,default = "-")

    class Meta:
        verbose_name = 'مشخصات‌ فرهنگی'
        verbose_name_plural = 'مشخصات‌ فرهنگی'

    def __str__(self):
        return f"{self.person}"


class PersonEDU(models.Model):
    EDU_CHOICES = (
        ('نامعلوم', 'نامعلوم'),
        ( 'ترک‌ تحصیل', 'ترک‌ تحصیل'),
        ('دانش‌آموز', 'دانش‌آموز'),
        ( 'دانشجو', 'دانشجو'),
        ('طلبه', 'طلبه'),
        ( 'فارغ التحصیل', 'فارغ التحصیل'),


    )
    person = models.OneToOneField(Person,
                                  on_delete=models.CASCADE,
                                  related_name='person_edu',
                                  verbose_name='کاربر' ,null=True,
                                  blank=True,)
    typee = models.CharField(max_length=20,
                             verbose_name='وضعیت تحصیلی',
                             choices=EDU_CHOICES,default='نامعلوم', null=True,
                                  blank=True,)
    place_name = models.CharField(max_length=250,
                                  verbose_name='نام محل تحصیل',
                                  null=True,
                                  blank=True,default = "-")
    edu_name = models.CharField(max_length=250,
                                verbose_name='رشته تحصیلی',
                                null=True,
                                blank=True,default = "-")
    term_name = models.CharField(max_length=250,
                                 verbose_name='ترم/پایه تحصیلی',
                                 null=True,
                                 blank=True,default = "-")
    otherClass = models.TextField(max_length=300,
                                  verbose_name='کلاس خارج از مدرسه',
                                  null=True,
                                  blank=True,default = "-")
    place_address = models.TextField(verbose_name='آدرس محل تحصیل',
                                     null=True,
                                     blank=True,default = "-")

    class Meta:
        verbose_name = 'مشخصات‌ تحصیلی'
        verbose_name_plural = 'مشخصات‌ تحصیلی'

    def __str__(self):
        return f"{self.person}_{self.typee}"


# اطلاعات تکمیلی
class PersonOtherInfo(models.Model):
    WIFE_CHOICES = (
        ('مجرد', 'مجرد'),
        ('متاهل', 'متاهل'),
    )
    Ansewr_CHOICE= (
        ('بله','بله'),
        ('خیر','خیر'),
        )
    person = models.OneToOneField(Person,
                                  on_delete=models.CASCADE,
                                  related_name='person_other_info',
                                  verbose_name='کاربر')
    family_count = models.IntegerField(null=True,
                                       blank=True,
                                       verbose_name="تعداد اعضای خانواده")
    numberOfChild = models.IntegerField(null=True,
                                        blank=True,
                                        verbose_name="فرزند چندم")
    wife_type = models.CharField(
        max_length=10,
        verbose_name='وضعیت تاهل',
        choices=WIFE_CHOICES,default = "مجرد")
    is_employed = models.CharField(verbose_name="شاغل است؟",
                              null=True,
                              blank=True,
                              max_length=10,
                              choices=Ansewr_CHOICE,default = "خیر")
    job_type = models.CharField(null=True,
                                blank=True,
                                default='آزاد',
                                max_length=50,
                                verbose_name='نوع شغل')
    job_title = models.CharField(null=True,
                                 blank=True,
                                 max_length=250,
                                 verbose_name='عنوان شغل',default = "-")
    salary_month = models.IntegerField(null=True,
                                       blank=True,
                                       verbose_name='میزان درآمد ماهانه(تومان)')
    talents = models.TextField(
        null=True, blank=True, verbose_name="استعداد و توانایی ها",default = "-")

    class Meta:
        verbose_name = 'اطلاعات تکمیلی'
        verbose_name_plural = 'اطلاعات تکمیلی'

    def __str__(self):
        return f"{self.person}_{self.wife_type}"


class Ring(models.Model):
    TYPE_CHOICES = (
        ('مربیان', 'مربیان'),
        ('سرگروهین', 'سرگروهین'),
        ('رابط', 'رابط'),
    )

    major = models.ForeignKey(Person,
                              on_delete=models.CASCADE,
                              related_name='rings_major',
                              verbose_name='(سرگروه)مسئول')
    alternative = models.CharField(
        max_length=150, null=True, blank=True, verbose_name='جانشین حلقه')
    name = models.CharField(max_length=150, verbose_name='نام حلقه')
    typee = models.CharField(max_length=20,
                             choices=TYPE_CHOICES,
                             verbose_name='نوع حلقه')

    class Meta:
        verbose_name = 'حلقه'
        verbose_name_plural = 'حلقه‌ها'

    def __str__(self):
        return f"حلقه {self.name} | {self.major}"


class RingMember(models.Model):
    ring = models.ForeignKey(Ring,
                             on_delete=models.CASCADE,
                             related_name='members',
                             verbose_name='حلقه')

    person = models.OneToOneField(Person,
                               on_delete=models.CASCADE,
                               related_name='memberships',
                               verbose_name='اعضا')

    class Meta:
        verbose_name = 'عضو حلقه'
        verbose_name_plural = 'اعضاحلقه'

    def __str__(self):
        return f"{self.person} "
    
class DateHalfMonth(models.Model):
    title = models.CharField(max_length=105, verbose_name='عنوان')
    start_date =  jmodels.jDateField(
        default=timezone.now, verbose_name='تاریخ شروع', null=True, blank=True
    )
    end_date =  jmodels.jDateField(
        verbose_name='تاریخ پایان', null=True, blank=True,default=timezone.now
    )

    def clean(self):
        """
        بررسی می‌کند که تاریخ پایان بعد از تاریخ شروع باشد.
        """
        if self.end_date and self.start_date and self.end_date < self.start_date:
            raise ValidationError("تاریخ پایان نمی‌تواند قبل از تاریخ شروع باشد.")

    def __str__(self):
        return f"{self.title}({self.start_date} - {self.end_date})"

    class Meta:
        verbose_name = 'بازه زمانی'
        verbose_name_plural = 'بازه‌های زمانی'




class DateHalfyear(models.Model):
    title = models.CharField(max_length=105, verbose_name='عنوان')
    start_date =  jmodels.jDateField(
        default=timezone.now, verbose_name='تاریخ شروع', null=True, blank=True
    )
    end_date =  jmodels.jDateField(
        verbose_name='تاریخ پایان', null=True, blank=True
        ,default=timezone.now
    )

    def clean(self):
        """
        بررسی می‌کند که تاریخ پایان بعد از تاریخ شروع باشد.
        """
        if self.end_date and self.start_date and self.end_date < self.start_date:
            raise ValidationError("تاریخ پایان نمی‌تواند قبل از تاریخ شروع باشد.")

    def __str__(self):
        start = self.start_date.strftime("%d-%m-%Y") if self.start_date else "نامشخص"
        end = self.end_date.strftime("%d-%m-%Y") if self.end_date else "نامشخص"
        
        return f"{self.title} {start} الی {end}"
    
    class Meta:
        verbose_name = 'بازه زمانی'
        verbose_name_plural = 'بازه‌های زمانی'
class ReportCard(models.Model):
    TITLE_CHOICES = (
        ('فرهنگی', 'فرهنگی'),
        ('مستمر', 'مستمر'),
        ('نهایی', 'نهایی'),
    )
    person = models.ForeignKey(Person, on_delete=models.CASCADE, verbose_name="شخص", null=True, blank=True, related_name="reportcards")
    ring = models.ForeignKey(Ring, on_delete=models.CASCADE, verbose_name="حلقه‌مربوطه", null=True, blank=True)
    date = models.ForeignKey(DateHalfyear, on_delete=models.SET_NULL, verbose_name='تاریخ', null=True, blank=True)
    title = models.CharField(max_length=100, choices=TITLE_CHOICES, verbose_name='عنوان کارنامه', null=True, blank=True)
    average_score = models.FloatField(default=0, verbose_name="میانگین نمرات", null=True, blank=True)  # فیلد میانگین

    def calculate_average_score(self):
        # گرفتن تمام جزئیات نمرات مربوط به این کارنامه
        reportcard_details = ReportCardDetail.objects.filter(reportcard=self)
        
        total_score = 0
        total_coefficient = 0

        for detail in reportcard_details:
            # محاسبه نمره ضربدر ضریب
            total_score += detail.score * detail.index.coefficient
            total_coefficient += detail.index.coefficient

        if total_coefficient > 0:
            average = total_score / total_coefficient
            return round(average, 2)  # میانگین با دو رقم اعشار
        return 0  # در صورتی که ضریبی نباشد، میانگین 0 را باز می‌گرداند

    def save(self, *args, **kwargs):
        # قبل از ذخیره کردن کارنامه میانگین را محاسبه و ذخیره می‌کنیم
        self.average_score = self.calculate_average_score()
        super().save(*args, **kwargs)

    def __str__(self):
        date_s = self.date.start_date if self.date and self.date.start_date else "بدون تاریخ"
        date_e = self.date.end_date if self.date and self.date.end_date else "بدون تاریخ"
        return f"{self.title or 'بدون عنوان'} - {date_s} {date_e}"

    class Meta:
        verbose_name = 'کارنامه'
        verbose_name_plural = 'کارنامه‌ها'
        ordering = ['-date__start_date']
        
      
class Index(models.Model):
    role=models.ForeignKey(Role,on_delete=models.SET_NULL,verbose_name='نقش',null=True,blank=True)
    title=models.CharField(max_length=55,verbose_name='عنوان')
    coefficient=models.IntegerField(verbose_name='ضریب')

    def __str__(self):
        return f"{self.title}"
    
    class Meta:
        verbose_name = 'شاخصه'
        verbose_name_plural = 'مشخصات'
#جزعیات کارنامه منتشر شده توسط سرگروه یا خانواده
class ReportCardDetail(models.Model):
    reportcard = models.ForeignKey(ReportCard,
                                   on_delete=models.CASCADE,
                                   related_name='details',
                                   verbose_name='کارنامه'
                                   )
  
    index=models.ForeignKey(Index,on_delete=models.SET_NULL,verbose_name='شاخصه',null=True)
    score=models.IntegerField(verbose_name='نمره')
    date_created = jmodels.jDateField(auto_now_add=True,
        verbose_name='تاریخ ایجاد',null=True,blank=True)
    signature=models.ImageField(upload_to='signature',null=True,blank=True)


    class Meta:
        verbose_name = 'کارنامه جزعیات فرهنگی '
        verbose_name_plural = 'کارنامه جزعیات فرهنگی '

    def __str__(self):
        return f"{self.reportcard.title}"


from django.db.models import Avg

class ReportCardFinaly(models.Model):
    person = models.ForeignKey(Person, on_delete=models.CASCADE, related_name='final_report_cards', verbose_name='شخص')
    created_at =  jmodels.jDateField(auto_now_add=True, verbose_name='تاریخ ایجاد' , null=True, blank=True)
    title=models.ForeignKey(ReportCard,
                                   on_delete=models.CASCADE,
                                   related_name='fainaly',
                                   verbose_name='عنوان',)
    sargroh=models.IntegerField(null=True,blank=True)
    talimvatarbiat=models.IntegerField(null=True,blank=True)
    elmivaamozeshi=models.IntegerField(null=True,blank=True)
    varzeshivaordoee=models.IntegerField(null=True,blank=True)
    syasatgozari=models.IntegerField(null=True,blank=True)
    farmandehi=models.IntegerField(null=True,blank=True)
    emamjamaat=models.IntegerField(null=True,blank=True)
    upgrade_used = models.BooleanField(default=False, verbose_name='آیا ارتقاء استفاده شده است؟')
    created_at = models.DateTimeField(auto_now_add=True, verbose_name='تاریخ ایجاد',null=True,blank=True)

     
    class Meta:
        verbose_name = 'کارنامه نهایی'
        verbose_name_plural = ' کارنامه های نهایی  '


    def __str__(self):
        return f"{self.title}-{self.title.date}"
    
    def save(self, *args, **kwargs):
        # فقط در صورتی که یک نمونه جدید یا تغییراتی انجام شود
        if self.title.title in ["نهایی", "مستمر"]:  # اضافه کردن "مستمر"
            start_date = self.title.date.start_date
            end_date = self.title.date.end_date

            # پیدا کردن کارنامه‌های فرهنگی مربوطه
            cultural_reportcards = ReportCard.objects.filter(
                person=self.person,
                title="فرهنگی",
                date__start_date__gte=start_date,
                date__end_date__lte=end_date,
            )

            # محاسبه میانگین نمرات
            if cultural_reportcards.exists():
                avg_score = ReportCardDetail.objects.filter(
                    reportcard__in=cultural_reportcards
                ).aggregate(Avg('score'))['score__avg']

                # ذخیره در فیلد sargroh
                self.sargroh = avg_score or 0

        # ادامه ذخیره مدل
        super().save(*args, **kwargs)

    
class Family(models.Model):
    individual = models.OneToOneField(
        Person, 
        on_delete=models.CASCADE, 
        verbose_name='شخص', 
        related_name='individual_family'
    )
    child = models.ManyToManyField(
        Person, 
        verbose_name='نام فرزند', 
        related_name='child_family'
    )
    score = models.IntegerField(null=True,blank=True)
    
    class Meta:
        verbose_name = 'خانواده'
        verbose_name_plural = ' خانواده ها '


    def __str__(self):
        return f"{self.individual} خانواده‌ی دانش‌آموز "
