from django.db import models
from django.contrib.auth.models import AbstractUser
from .modelcommon import AuditClass
from .UserManager import UserManager
from django.db.models.signals import post_save, post_delete
from django.dispatch import receiver
from datetime import datetime
from . import enums
from django.utils.text import slugify
from datetime import timedelta
import os

from django.conf import settings


# ********************* AUTH TABLES *********************


def number_generator(prefix, id):
    date = '{:%Y%m%d}'.format(datetime.now())
    id_num = '{:07}'.format(id)
    autogenerated_no = prefix + '-' + date + '-' + id_num

    return autogenerated_no


class Application(AuditClass):
    code = models.CharField(
        unique=True,
        max_length=255
    )
    name = models.CharField(unique=True, max_length=255)
    excel_code = models.CharField(max_length=255)

    class Meta:
        db_table = 'applications'

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

    def save(self, *args, **kwargs):
        super(Application, self).save(*args, **kwargs)
        code = enums.GenerateCode.APP.value
        code = number_generator(enums.GenerateCode.APP.value, self.id)
        Application.objects.filter(id=self.id).update(code=code)


class Module(AuditClass):
    application = models.ForeignKey(
        Application,
        to_field='code',
        related_name='modules',
        on_delete=models.PROTECT
    )
    code = models.CharField(
        unique=True,
        max_length=255,
        default='mod'
    )
    name = models.CharField(
        unique=True,
        max_length=255,
        blank=True,
        null=True
    )
    parent = models.ForeignKey(
        "Module",
        related_name='module_parent',
        on_delete=models.PROTECT,
        blank=True, null=True
    )
    sort_id = models.IntegerField()
    component = models.CharField(
        max_length=255,
        null=True,
        blank=True)

    class Meta:
        db_table = 'modules'

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

    def save(self, *args, **kwargs):
        super(Module, self).save(*args, **kwargs)
        if self.code == 'mod':
            code = enums.GenerateCode.APP.value
            code = number_generator(enums.GenerateCode.MODULE.value, self.id)
            Module.objects.filter(id=self.id).update(code=code)


class Delegation(AuditClass):
    code = models.CharField(
        unique=True,
        max_length=255
    )
    name = models.CharField(unique=True, max_length=255)
    
    class Meta:
        db_table = 'delegations'

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

    def save(self, *args, **kwargs):
        super(Delegation, self).save(*args, **kwargs)
        code = number_generator(enums.GenerateCode.DELEGATION.value, self.id)
        
        if self.code == '':
            self.code = code
            self.created = datetime.now()
            self.save()


class Company(AuditClass):
    code = models.CharField(
        unique=True,
        max_length=255,
        default='com'
    )
    name = models.CharField(unique=True, max_length=255)
    contact_details = models.TextField(blank=True, null=True)

    class Meta:
        db_table = 'companies'

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

    def save(self, *args, **kwargs):
        super(Company, self).save(*args, **kwargs)
        if self.code == 'com':
            code = enums.GenerateCode.APP.value
            code = number_generator(enums.GenerateCode.COMPANY.value, self.id)
            Company.objects.filter(id=self.id).update(code=code)


class Department(AuditClass):
    # parent = models.ForeignKey(
    #     'Department',
    #     related_name='departments_parent',
    #     on_delete=models.PROTECT,
    #     blank=True, null=True
    # )
    company = models.ForeignKey(
        Company,
        to_field='code',
        related_name='companies',
        on_delete=models.PROTECT
    )
    code = models.CharField(
        unique=True,
        max_length=255,
        default='dept'
    )
    name = models.CharField(max_length=255)
    delegation = models.ManyToManyField(
        Delegation,
        related_name='departments'
    )

    class Meta:
        db_table = 'departments'
        unique_together = ['company', 'name']
        

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

    def save(self, *args, **kwargs):
        super(Department, self).save(*args, **kwargs)
        if self.code == 'dept':
            code = enums.GenerateCode.APP.value
            code = number_generator(enums.GenerateCode.DEPARTMENT.value, self.id)
            Department.objects.filter(id=self.id).update(code=code)


# class Position(AuditClass):
#     parent = models.ForeignKey('Position',
#                                related_name='position_subs',
#                                on_delete=models.PROTECT,
#                                blank=True, null=True)
#     code = models.CharField(unique=True, max_length=255)
#     name = models.CharField(unique=True, max_length=255)
#     description = models.CharField(max_length=255, blank=True, null=True)

#     department = models.ForeignKey(Department,
#                                    related_name='positions',
#                                    on_delete=models.PROTECT)

#     class Meta:
#         db_table = 'positions'


class Role(AuditClass):
    description = models.CharField(
        max_length=255,
        blank=True,
        null=True
    )
    code = models.CharField(
        unique=True,
        max_length=255,
        default='role'
    )
    name = models.CharField(max_length=255)

    class Meta:
        db_table = 'roles'


class Permission(AuditClass):
    name = models.CharField(max_length=255, blank=False, null=True)
    code = models.CharField(
        unique=True,
        max_length=255,
        blank=True,
        null=True
    )
    description = models.CharField(
        max_length=255,
        blank=False,
        null=True
    )

    class Meta:
        db_table = 'permissions'


class RolePermission(AuditClass):
    role = models.ForeignKey(
        Role,
        related_name='role_permissions',
        on_delete=models.PROTECT
    )
    permission = models.ForeignKey(
        Permission,
        related_name='role_permissions',
        on_delete=models.PROTECT
    )

    class Meta:
        db_table = 'role_permissions'
        

class ExtractTransformLoad(AuditClass):
    file_name = models.CharField(max_length=255)
    model_type = models.CharField(
        choices=[(tag.value, tag.value) for tag in enums.GenerateCode],
        default=enums.GenerateCode.USER.value,
        max_length=100
    )
    code = models.CharField(
        unique=True,
        max_length=255,
        blank=True,
        null=True
    )

    class Meta:
        db_table = 'extract_transform_load'

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

    def save(self, *args, **kwargs):
        super(ExtractTransformLoad, self).save(*args, **kwargs)
        code = number_generator(enums.GenerateCode.ETL.value, self.id)
        print(type(self.code))


        if self.code == '' or self.code == None:
            self.code = code
            self.save()


class UserHistory(AuditClass):
    file_name = models.ForeignKey(
        ExtractTransformLoad,
        to_field='code',
        related_name='extract_transform_load',
        on_delete=models.DO_NOTHING,
        blank=True,
        null=True
    )
    name = models.CharField(max_length=255)
    username = models.CharField(max_length=255)
    email = models.EmailField(max_length=255, unique=False)
    password = models.CharField(max_length=255)
    sent = models.BooleanField(default=False)
    deleted = models.BooleanField(default=False)

    class Meta:
        db_table = 'extract_transform_load_user_history'


class User(AbstractUser):
    application = models.ManyToManyField(
        Application
    )
    department = models.ForeignKey(
        Department,
        to_field='code',
        related_name='department_users',
        on_delete=models.PROTECT,
        blank=True,
        null=True
    )
    # role = models.ForeignKey(
    #     Role,
    #     related_name='role_users',
    #     on_delete=models.PROTECT,
    #     default=1
    # )
    # default_app = models.CharField(blank=True, null=True, max_length=255)
    default_app = models.ForeignKey(
        Application,
        to_field='code',
        related_name='default_app',
        on_delete=models.PROTECT,
        blank=True,
        null=True
    )
    user_type = models.CharField(
        choices=[(tag.value, tag.value) for tag in enums.UserTypeEnum],
        default=enums.UserTypeEnum.USER.value,
        max_length=100
    )
    code = models.CharField(
        unique=True,
        max_length=255,
        default='acct'
    )
    name = models.CharField(max_length=255)
    username = models.CharField(max_length=255, unique=True)
    password = models.CharField(
        max_length=255,
        blank=True,
        null=True
    )
    doa = models.ForeignKey(
        'User',
        to_field='code',
        related_name='doa_users',
        on_delete=models.PROTECT,
        blank=True,
        null=True
    )
    contact_no = models.CharField(blank=True, null=True, max_length=255)
    email = models.EmailField(max_length=255, unique=False)
    objects = UserManager()

    class Meta:
        db_table = 'auth_user'

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

    def save(self, *args, **kwargs):
        super(User, self).save(*args, **kwargs)
        if self.code == 'acct':
            code = enums.GenerateCode.APP.value
            code = number_generator(enums.GenerateCode.USER.value, self.id)
            User.objects.filter(id=self.id).update(code=code)


class UserImage(AuditClass):
    user = models.ForeignKey(
        User,
        to_field='code',
        related_name='user_images',
        on_delete=models.CASCADE
    )
    name = models.CharField(blank=True, null=True, max_length=255)
    image = models.ImageField(upload_to='user_images/', null=True,
                              max_length=255)
    is_primary = models.BooleanField(default=True)

    class Meta:
        db_table = 'auth_user_images'


class Attachment(AuditClass):
    code = models.FileField(
        upload_to='file_attachments/',
        null=True,
        max_length=255
    )
    name = models.CharField(unique=True, max_length=255)
    description = models.CharField(
        max_length=255,
        blank=True,
        null=True
    )

    class Meta:
        db_table = 'attachments'


"""
**********************
*** UTILITY TABLES ***
**********************
"""


class AuthToken(models.Model):
    ref = models.CharField(max_length=255)
    token = models.TextField()
    passcode = models.CharField(max_length=255)
    is_active = models.BooleanField(default=False)
    user = models.ForeignKey(User, to_field='code',
                             related_name='auth_access_token',
                             on_delete=models.PROTECT)
    created = models.DateTimeField(blank=True, null=True)
    timeout_at = models.DateTimeField(blank=True, null=True)

    class Meta:
        db_table = 'auth_access_token'


class EntityLog(AuditClass):
    action = models.CharField(
        choices=[
            (tag.value, tag.value) for tag in enums.LogEnum],
        default=enums.LogEnum.ADD.value,
        max_length=50)
    entity = models.CharField(
        choices=[
            (tag.value, tag.value) for tag in enums.LogEntitiesEnum],
        default=enums.LogEnum.ADD.value,
        max_length=50)
    row_id = models.IntegerField()
    fromValue = models.TextField(blank=True, null=True)
    toValue = models.TextField(blank=True, null=True)

    def __str__(self):
        return self.entity

    class Meta:
        db_table = 'entity_logs'


"""
**********************
*** CHANGE REQUEST TABLES ***
**********************
"""

class BaseHeader(models.Model):

    requested_to_company = models.ForeignKey(
        Company,
        on_delete=models.PROTECT,
        to_field='code')
    requested_to_department = models.ForeignKey(
        Department,
        on_delete=models.PROTECT,
        to_field='code')
    requested_to_user = models.ForeignKey(
        User,
        on_delete=models.PROTECT,
        to_field='code')
    requested_to_template_name = models.CharField(max_length=255)
    requested_to_objective = models.CharField(
        max_length=255,
        blank=True,
        null=True)
    requested_to_priority = models.CharField(max_length=255)
    description = models.CharField(
        max_length=255,
        blank=True,
        null=True)
    created = models.DateTimeField(auto_now_add=True)
    is_active = models.BooleanField(default=True)

    class Meta:
        abstract = True


class BaseApprover(models.Model):
    level = models.IntegerField()
    user = models.ForeignKey(
        User,
        blank=True,
        null=True,
        on_delete=models.PROTECT,
        to_field='code')
    delegation = models.ForeignKey(
        Delegation,
        blank=True,
        null=True,
        on_delete=models.CASCADE,
        to_field='code')
    created = models.DateTimeField(
        blank=True,
        null=True)

    class Meta:
        abstract = True


class BaseStakeholder(models.Model):
    user = models.ForeignKey(
        User,
        blank=True,
        null=True,
        on_delete=models.PROTECT,
        to_field='code')
    delegation = models.CharField(
        max_length=255,
        blank=True,
        null=True)
    created = models.DateTimeField(
        blank=True,
        null=True)

    class Meta:
        abstract = True


class MasterAttachment(models.Model):
    url = models.FileField(
        upload_to='uploads/',
        blank=True,
        null=True)
    attch_ref = models.TextField()


    def delete(self,*args,**kwargs):
        print(self.url.name)
        if os.path.isfile(self.url.path):
            os.remove(self.url.path)

        super(MasterAttachment, self).delete(*args,**kwargs)
    
    class Meta:
        db_table = 'master_attachments'

    def delete(self, *args, **kwargs):
        # self.url.delete()
        # super().delete(*args, **kwargs)

        os.remove(os.path.join(settings.MEDIA_ROOT, self.url.name))
        super(MasterAttachment, self).delete(*args, **kwargs)


class BaseAttachment(models.Model):
    attachment_type = models.CharField(max_length=255)
    attachment_name = models.CharField(max_length=255)
    file_name = models.CharField(
        max_length=255,
        blank=True,
        null=True)
    description = models.CharField(
        max_length=255,
        blank=True,
        null=True)
    uploaded_by = models.ForeignKey(
        User,
        on_delete=models.PROTECT,
        to_field='code')
    created = models.DateTimeField(
        blank=True,
        null=True)

    class Meta:
        abstract = True


class BaseDetails(models.Model):
    field_idx = models.TextField(
        blank=True,
        null=True)
    field_ref = models.TextField(
        blank=True,
        null=True
    )
    field_val = models.TextField(
        blank=True,
        null=True
    )
    field_props = models.TextField(
        blank=True,
        null=True
    )
    created = models.DateTimeField(
        blank=True,
        null=True)

    class Meta:
        abstract = True


'''
*********
TEMPLATES
*********
'''

class ChangeRequestTemplateHeader(BaseHeader):
    template_no = models.CharField(
        unique=True,
        max_length=255)
    requested_to_template_id = models.CharField(
        max_length=255,
        unique=True)
    created_by_user = models.ForeignKey(
        User,
        on_delete=models.PROTECT,
        to_field='code',
        related_name='created_by_user')
    created_by_department = models.ForeignKey(
        Department,
        on_delete=models.PROTECT,
        to_field='code',
        related_name='created_by_department')
    requested_to_target_date = models.IntegerField()
    
    class Meta:
        db_table = 'change_request_template_headers'
        ordering = ['-created']

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

    def save(self, *args, **kwargs):
        super(ChangeRequestTemplateHeader, self).save(*args, **kwargs)
        code = number_generator(enums.GenerateCode.TEMPLATE.value, self.id)
        
        if self.template_no == '':
            self.template_no = code
            self.save()


class ChangeRequestTemplateApprovers(BaseApprover):
    code = models.CharField(
        unique=True,
        max_length=255)  # primary key
    template_no = models.ForeignKey(
        ChangeRequestTemplateHeader,
        on_delete=models.PROTECT,
        to_field='template_no',
        related_name='tmp_approvers')
    company = models.ForeignKey(
        Company,
        blank=True,
        null=True,
        on_delete=models.PROTECT,
        to_field='code')
    department = models.ForeignKey(
        Department,
        blank=True,
        null=True,
        on_delete=models.PROTECT,
        to_field='code')
    is_default = models.BooleanField(
        default=False
    )
    
    class Meta:
        db_table = 'change_request_template_approvers'
        ordering = ['level']

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

    def save(self, *args, **kwargs):
        super(ChangeRequestTemplateApprovers, self).save(*args, **kwargs)
        code = number_generator(enums.GenerateCode.TMP_APPROVER.value, self.id)
        
        if self.code == '':
            self.code = code
            self.created = datetime.now()
            self.save()


class ChangeRequestTemplateStakeHolders(BaseStakeholder):
    code = models.CharField(
        unique=True,
        max_length=255)  # primary key
    template_no = models.ForeignKey(
        ChangeRequestTemplateHeader,
        on_delete=models.PROTECT,
        to_field='template_no',
        related_name='tmp_stakes')
        
    class Meta:
        db_table = 'change_request_template_stakeholders'

    def __str__(self):
        return f'{self.code}'
    
    def save(self, *args, **kwargs):
        super(ChangeRequestTemplateStakeHolders, self).save(*args, **kwargs)
        code = number_generator(enums.GenerateCode.TMP_STAKE.value, self.id)
        
        if self.code == '':
            self.code = code
            self.created = datetime.now()
            self.save()


class ChangeRequestTemplateAttachments(BaseAttachment):
    code = models.CharField(
        max_length=255,
        unique=True)
    file_upload = models.ForeignKey(
        MasterAttachment,
        on_delete=models.PROTECT,
        related_name='template_attachments',
        blank=True,
        null=True
    )
    template_no = models.ForeignKey(
        ChangeRequestTemplateHeader,
        on_delete=models.PROTECT,
        to_field='template_no',
        related_name='tmp_attachments')
    
    class Meta:
        db_table = 'change_request_template_attachments'

    def __str__(self):
        return f'{self.code}'
    
    def save(self, *args, **kwargs):
        super(ChangeRequestTemplateAttachments, self).save(*args, **kwargs)
        code = number_generator(enums.GenerateCode.TMP_ATTACH.value, self.id)

        if self.code == '':
            self.code = code
            self.created = datetime.now()
            self.save()
    

class ChangeRequestTemplateDetails(BaseDetails):
    code = models.CharField(
        max_length=255,
        unique=True)
    template_no = models.ForeignKey(
        ChangeRequestTemplateHeader,
        on_delete=models.PROTECT,
        to_field='template_no',
        related_name='tmp_details')
    
    class Meta:
        db_table = 'change_request_template_details'
    
    def __str__(self):
        return f'{self.code}'

    def save(self, *args, **kwargs):
        super(ChangeRequestTemplateDetails, self).save(*args, **kwargs)
        code = number_generator(enums.GenerateCode.TMP_DETAIL.value, self.id)
        
        if self.code == '':
            self.code = code
            self.created = datetime.now()
            self.save()
    
'''
*****
FORMS
*****
'''

class ChangeRequestFormHeader(BaseHeader):
    form_code = models.CharField(
        max_length=255,
        unique=True)
    requested_by_user = models.ForeignKey(
        User,
        on_delete=models.PROTECT,
        to_field='code',
        related_name='requested_by_user')
    cancel_date = models.DateTimeField(
        null=True,
        blank=True)
    requested_by_department = models.ForeignKey(
        Department,
        on_delete=models.PROTECT,
        to_field='code',
        related_name='requested_by_department')
    template_no = models.ForeignKey(
        ChangeRequestTemplateHeader,
        on_delete=models.PROTECT,
        to_field='template_no')
    status = models.CharField(max_length=50)
    company_desc = models.CharField(
        max_length=255,
        null=True,
        blank=True)
    department_desc = models.CharField(
        max_length=255,
        null=True,
        blank=True)
    requested_desc = models.CharField(
        max_length=255,
        null=True,
        blank=True)
    requested_to_template_id = models.CharField(
        max_length=255)
    requested_to_target_date = models.DateTimeField(
        blank=True,
        null=True)

    class Meta:
        db_table = 'change_request_form_headers'
        ordering = ['-created']
    
    def __str__(self):
        return f'{self.form_code}'
    
    def save(self, *args, **kwargs):
        super(ChangeRequestFormHeader, self).save(*args, **kwargs)
        code = number_generator(enums.GenerateCode.FORM.value, self.id)
        
        if self.form_code == '':
            self.form_code = code
            self.save()


class ChangeRequestFormApprovers(BaseApprover):
    code = models.CharField(
        unique=True,
        max_length=255)  # primary key
    form_code = models.ForeignKey(
        ChangeRequestFormHeader,
        on_delete=models.PROTECT,
        to_field='form_code',
        related_name='frm_approvers')
    remarks = models.CharField(
        max_length=255,
        null=True,
        blank=True)
    action = models.CharField(
        max_length=50,
        blank=True,
        null=True)
    action_date = models.DateTimeField(
        blank=True,
        null=True)
    date_sent = models.DateTimeField(
        blank=True,
        null=True)
    is_action = models.BooleanField(
        default=False)
    tmp_approver = models.ForeignKey(
        ChangeRequestTemplateApprovers,
        on_delete=models.PROTECT,
        blank=True,
        null=True,
        to_field='code')

    class Meta:
        db_table = 'change_request_form_approvers'
        ordering = ['level']
    
    def __str__(self):
        return f'{self.code}'

    def save(self, *args, **kwargs):
        super(ChangeRequestFormApprovers, self).save(*args, **kwargs)
        code = number_generator(enums.GenerateCode.FORM_APPROVER.value, self.id)
        
        if self.code == '':
            self.code = code
            self.created = datetime.now()
            self.save()


class ChangeRequestFormDetails(BaseDetails):
    code = models.CharField(
        unique=True,
        max_length=255)  # primary key
    form_code = models.ForeignKey(
        ChangeRequestFormHeader,
        on_delete=models.PROTECT,
        to_field='form_code',
        related_name='frm_details')

    class Meta:
        db_table = 'change_request_form_details'
    
    def __str__(self):
        return f'{self.code}'
    
    def save(self, *args, **kwargs):
        super(ChangeRequestFormDetails, self).save(*args, **kwargs)
        code = number_generator(enums.GenerateCode.FORM_DETAIL.value, self.id)
        
        if self.code == '':
            self.code = code
            self.created = datetime.now()
            self.save()


class ChangeRequestFormStakeHolders(BaseStakeholder):
    code = models.CharField(
        unique=True,
        max_length=255)  # primary key
    form_code = models.ForeignKey(
        ChangeRequestFormHeader,
        on_delete=models.PROTECT,
        to_field='form_code',
        related_name='frm_stakes')
    date_added = models.DateTimeField(
        blank=True,
        null=True)
    
    class Meta:
        db_table = 'change_request_form_stakeholders'
    
    def __str__(self):
        return f'{self.code}'

    def save(self, *args, **kwargs):
        super(ChangeRequestFormStakeHolders, self).save(*args, **kwargs)
        code = number_generator(enums.GenerateCode.FORM_STAKE.value, self.id)
        
        if self.code == '':
            self.code = code
            self.created = datetime.now()
            self.save()


class ChangeRequestFormAttachments(BaseAttachment):
    code = models.CharField(
        unique=True,
        max_length=255)  # primary key
    form_code = models.ForeignKey(
        ChangeRequestFormHeader,
        on_delete=models.PROTECT,
        to_field='form_code',
        related_name='frm_attachments')
    file_upload = models.ForeignKey(
        MasterAttachment,
        on_delete=models.PROTECT,
        related_name='form_attachments',
        blank=True,
        null=True
    )

    class Meta:
        db_table = 'change_request_form_attachments'
    
    def __str__(self):
        return f'{self.code}'

    def save(self, *args, **kwargs):
        super(ChangeRequestFormAttachments, self).save(*args, **kwargs)
        code = number_generator(enums.GenerateCode.FORM_ATTACH.value, self.id)
        
        if self.code == '':
            self.code = code
            self.created = datetime.now()
            self.save()

'''
*****
CR HISTORY
*****
'''

class ChangeRequestHistory(AuditClass):
    batch_no = models.CharField(
        max_length=255,
        blank=True,
        null=True)
    main_action = models.CharField(
        max_length=255,
        blank=True,
        null=True)
    action = models.CharField(
        max_length=50)
    entity = models.CharField(
        max_length=50)
    form_code = models.CharField(
        max_length=255,
        blank=True,
        null=True)
    fromValue = models.TextField(blank=True, null=True)
    toValue = models.TextField(blank=True, null=True)
    requested_to_template_id = models.CharField(
        max_length=255,
        blank=True,
        null=True)
    requested_to_template_id = models.CharField(
        max_length=255,
        blank=True,
        null=True)
    template_no = models.CharField(
        max_length=255,
        blank=True,
        null=True)
    
    def __str__(self):
        return self.entity

    class Meta:
        db_table = 'change_request_history'


"""
**********************
*** NOTIFICATION TABLES ***
**********************
"""

class Notification(models.Model):
    code = models.CharField(
        unique=True,
        max_length=255)  # primary key
    form_code = models.CharField(
        null=True,
        blank=True,
        max_length=255)
    app = models.CharField(
        null=True,
        blank=True,
        max_length=255)
    notif_type = models.CharField(
        choices=[(tag.value, tag.value) for tag in enums.NotifTypeEnum],
        default=enums.NotifTypeEnum.TASK.value,
        max_length=20
    )
    account_no = models.CharField(
        null=True,
        blank=True,
        max_length=255)
    message = models.CharField(
        max_length=255,
        null=True,
        blank=True)
    is_read = models.BooleanField(
        default=False,
        null=True)
    sender_account_no = models.CharField(
        null=True,
        blank=True,
        max_length=255)
    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)
    
    class Meta:
        db_table = 'notifications'
    
    def __str__(self):
        return self.message

    def save(self, *args, **kwargs):
        super(Notification, self).save(*args, **kwargs)
        code = number_generator(enums.GenerateCode.NOTIFICATION.value, self.id)
        Notification.objects.filter(id=self.id).update(code=code)


class EmailLogs(AuditClass):
    template = models.CharField(max_length=255)
    recipients = models.CharField(max_length=255)
    content = models.TextField()
    is_sent = models.BooleanField(default=True)

    class Meta:
        db_table = 'email_logs'


class PasswordReset(models.Model):
    email = models.EmailField(max_length=255)
    token = models.CharField(max_length=255)
    created_at = models.DateTimeField()
    timeout_at = models.DateTimeField()
    is_active = models.BooleanField(default=True)
    code = models.CharField(max_length=50)

    # def save(self, *args, **kwargs):
    #     super(PasswordReset, self).save(*args, **kwargs)
    #     timeout_at = created_at + datetime.timedelta(days=1)
    #     if self.timeout_at == '':
    #         self.timeout_at = timeout_at
    #         self.save()

    def __str__(self):
        return self.email

    class Meta:
        db_table = 'password_resets'

class AllowedCompany(models.Model):
    id_number = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        to_field='code',
        related_name='allowed_company_id_number'
    )
    company_pivot = models.ForeignKey(
        Company,
        to_field='code',
        related_name='allowed_company_company_pivot',
        on_delete=models.CASCADE,
    )
    group_pivots = models.ForeignKey(
        Department,
        on_delete=models.CASCADE,
        related_name='allowed_company_group_pivots',
        to_field='code'
    )
    # app_code = models.CharField(max_length=250)
    create_change_request = models.BooleanField(default=True)
    create_change_request_template = models.BooleanField(default=True)
    view_all_change_request = models.BooleanField(default=True)
    approve_cr = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)
    deleted_at = models.DateTimeField(null=True, blank=True)
    
    class Meta:
        db_table = 'allowed_company'
        unique_together = ['company_pivot', 'group_pivots', 'id_number']


class ReminderTrigger(models.Model):
    frm_approver = models.ForeignKey(
        ChangeRequestFormApprovers,
        on_delete=models.PROTECT,
        to_field='code')
    auto_cancel_date = models.DateTimeField(
        null=True,
        blank=True)
    date_submitted_last_approver = models.DateTimeField(
        null=True,
        blank=True)
    date_from = models.DateTimeField(
        null=True,
        blank=True)
    date_to = models.DateTimeField(
        null=True,
        blank=True)
    date_to_send = models.DateTimeField(
        null=True,
        blank=True)
    is_sent = models.BooleanField(
        default=False)
    form_code = models.ForeignKey(
        ChangeRequestFormHeader,
        on_delete=models.PROTECT,
        to_field='form_code',
        null=True,
        blank=True)

    class Meta:
        db_table = 'trigger_reminder'


class CancelTrigger(models.Model):
    form_code = models.ForeignKey(
        ChangeRequestFormHeader,
        on_delete=models.PROTECT,
        to_field='form_code')
    frm_approver = models.ForeignKey(
        ChangeRequestFormApprovers,
        on_delete=models.PROTECT,
        to_field='code',
        blank=True,
        null=True)
    auto_cancel_date = models.DateTimeField(
        null=True,
        blank=True)
    is_sent = models.BooleanField(
        default=False)
    date_submitted_last_approver = models.DateTimeField(
        null=True,
        blank=True)
    cancel_type = models.CharField(
        null=True,
        blank=True,
        max_length=255)
    
    class Meta:
        db_table = 'trigger_cancel'


class OverdueTrigger(models.Model):
    form_code = models.ForeignKey(
        ChangeRequestFormHeader,
        on_delete=models.PROTECT,
        to_field='form_code')
    overdue_date = models.DateTimeField(
        null=True,
        blank=True)
    is_sent = models.BooleanField(
        default=False)
    
    class Meta:
        db_table = 'trigger_overdue'


"""
**********************
*** AMS TABLES ***
**********************
"""

class AssetGroup(models.Model):
    code = models.CharField(
        unique=True,
        max_length=255)
    name = models.CharField(
        unique=True,
        max_length=255)
    asset_group = models.CharField(
        unique=True,
        max_length=255)
    created = models.DateTimeField(
        blank=True,
        null=True)
    
    class Meta:
        db_table = 'asset_groups'
        ordering = ['-created']
    
    def __str__(self):
        return f'{self.code}'

    def save(self, *args, **kwargs):
        super(AssetGroup, self).save(*args, **kwargs)
        code = number_generator(enums.GenerateCode.ASSET_GROUP.value, self.id)
        
        if self.code == '':
            self.code = code
            self.created = datetime.now()
            self.save()