from django.db import models
from django.utils import timezone
from django.conf import settings
from datetime import timedelta
# from users.models import User



class OrganisationType(models.Model):
    org_type =  models.CharField(max_length=100)
    date_added = models.DateTimeField(default = timezone.now)
    org_type_added_by = models.BigIntegerField(null=True, blank=True)
    
    class Meta:
        db_table = 'public\".\"organisation_type'

class OrganisationRegField(models.Model):
    field_label =  models.CharField(max_length=100)
    date_added = models.DateTimeField(default = timezone.now)
    org_reg_field_added_by = models.BigIntegerField()
    class Meta:
        db_table = 'public\".\"organisation_reg_field'

class OrganisationTypeField(models.Model):
    org_type =  models.ForeignKey(OrganisationType, on_delete=models.CASCADE, related_name='org_type_field')
    org_reg_field  =  models.ForeignKey(OrganisationRegField, on_delete=models.CASCADE, related_name='org_reg_field')
    date_added = models.DateTimeField(default = timezone.now)
    org_type_field_added_by = models.BigIntegerField()
   
    class Meta:
        db_table = 'public\".\"organisation_type_field'

class Organisation(models.Model):
    REGIONS = (
        ('Central', 'Central'),
        ('Eastern', 'Eastern'),
        ('Western', 'Western'),
        ('Northern', 'Northern')
    )
   
    name =  models.CharField(max_length=255)
    short_name =  models.CharField(max_length=255, null=True, blank=True)
    registration_no =  models.CharField(max_length=50, null=True, blank=True)
    city =  models.CharField(max_length=255, null=True, blank=True)
    address =  models.CharField(max_length=255, null=True, blank=True)
    country =  models.CharField(max_length=255, null=True, blank=True, default='Uganda')
    region =  models.CharField(max_length=255, null=True, blank=True, choices=REGIONS)
    date_added = models.DateTimeField(default = timezone.now)
    organisation_added_by = models.BigIntegerField(null=True, blank=True)
    status =  models.CharField(max_length=25, default='pending')
    organisation_type   =  models.ForeignKey(OrganisationType, on_delete=models.CASCADE, related_name='organisation_type')
    email         = models.EmailField(max_length = 50, null=True, blank=True)
    phone_number  = models.CharField(max_length=15, null=True, blank=True)
    logo_url      = models.TextField(blank=True, null=True)
    base_currency = models.IntegerField(null=False, blank=False,default=1)
    admin_organisation   =  models.ForeignKey('Organisation', on_delete=models.CASCADE, related_name='admin_organ', default=1)
    mse_name = models.CharField(max_length=255, null=True, blank=True)
    income_source = models.CharField(max_length=255, null=True, blank=True)
    registration_level = models.CharField(max_length=255, null=True, blank=True)
    year_established = models.IntegerField(null=True, blank=True)
    group_leader_name = models.CharField(max_length=255, null=True, blank=True)
    certificate_of_incorporation = models.FileField(upload_to='certificates/', null=True, blank=True)
    bds_provider = models.CharField(max_length=255, null=True, blank=True)

    # BDO and Training tracking fields
    assigned_bdo = models.ForeignKey('users.Staff', on_delete=models.SET_NULL, null=True, blank=True, related_name='assigned_bdo_organisations', help_text='Business Development Officer assigned to this organization')
    is_trained = models.BooleanField(default=False, help_text='Whether the organization has been trained to use the system')
    training_date = models.DateField(null=True, blank=True, help_text='Date when the organization was trained')
    physical_address = models.CharField(max_length=255, null=True, blank=True)
    district = models.CharField(max_length=255, null=True, blank=True)
    county = models.CharField(max_length=255, null=True, blank=True)
    sub_county = models.CharField(max_length=255, null=True, blank=True)
    parish = models.CharField(max_length=255, null=True, blank=True)
    village = models.CharField(max_length=255, null=True, blank=True)
    # Whether CRB (credit reference bureau) functionality is enabled for this organisation
    is_crb_active = models.BooleanField(default=False, help_text='Enable or disable CRB requests for this organisation')
    # Whether mobile app functionality is enabled for this organisation
    is_mobile_app_active = models.BooleanField(default=True, help_text='Enable or disable mobile app access for this organisation')


    def __str__(self):
        return self.name
    class Meta:
        db_table = 'public\".\"organisation'


class OrganisationFieldMeta(models.Model):
    org_field_label =  models.CharField(max_length=100)
    value    =  models.TextField()
    required = models.CharField(max_length = 10, null=False, blank=False)
    order    = models.CharField(max_length = 10, null=False, blank=False)
    section  = models.CharField(max_length = 2550, null=False, blank=False)
    date_added  = models.DateTimeField(default = timezone.now)
    org_field   =  models.ForeignKey(OrganisationTypeField, on_delete=models.CASCADE, related_name='org_field')
    field_org   =  models.ForeignKey(Organisation, on_delete=models.CASCADE, related_name='field_org')
    org_field_added_by =  models.BigIntegerField()
   
    class Meta:
        db_table = 'public\".\"organisation_field_meta'

class OrganisationSetting(models.Model):
    setting_key    =  models.CharField(max_length=100)
    setting_value  =  models.TextField()
    date_added     = models.DateTimeField(default = timezone.now)
    last_updated   = models.DateTimeField(default = timezone.now)
    org_setting    =  models.ForeignKey(Organisation, on_delete=models.CASCADE, related_name='org_setting')
    setting_added_by = models.BigIntegerField()
    class Meta:
        db_table = 'public\".\"organisation_setting'

class OrganisationBranch(models.Model):
    name =  models.CharField(max_length=255)
    short_name =  models.CharField(max_length=50, null=True, blank=True)
    date_added = models.DateTimeField(default = timezone.now)
    added_by = models.BigIntegerField(null=True, blank=True)
    status  =  models.CharField(max_length=25, null=True, blank=True)
    address =  models.CharField(max_length=255, null=True, blank=True)
    can_transact =  models.BooleanField(default=True)
    account_number_prefix =  models.CharField(max_length=255, null=True, blank=True)
    branch_organisation =  models.ForeignKey(Organisation, on_delete=models.CASCADE, related_name='organisation_branches')
    member_number_prefix = models.CharField(max_length=55, null=True, blank=True)
    inter_branch_chart = models.BigIntegerField(blank=True, null=True)

    class Meta:
        db_table = 'public\".\"organisation_branch'
        ordering = ['date_added'] 
    
    def __str__(self):
        return self.name

# for all components / features on the system 
class SystemComponent(models.Model):
    component      =  models.CharField(max_length=255)
    component_desc =  models.TextField()
    type           =  models.CharField(max_length=50, null=True, blank=True)
    key            =  models.CharField(max_length=50, null=True, blank=True)
    date_added     = models.DateTimeField(default = timezone.now)
    parent_component =  models.IntegerField(default='0', null=False, blank=False)
    component_added_by = models.BigIntegerField(),
    is_active = models.BooleanField(default=False)

    class Meta:
        db_table = 'public\".\"system_component'


# for all components / features assigned to the organisation
class OrganisationComponent(models.Model):
    system_component = models.ForeignKey(SystemComponent, on_delete=models.CASCADE, related_name='system_component')
    component_org    =  models.ForeignKey(Organisation, on_delete=models.CASCADE, related_name='component_org')
    date_added       = models.DateTimeField(default = timezone.now)
    org_component_added_by = models.BigIntegerField(),
    is_active = models.BooleanField(default=False)
    class Meta:
        db_table = 'public\".\"org_component'

# for all components / features assigned to the organisation
class OrgTypeComponent(models.Model):
    system_component = models.ForeignKey(SystemComponent, on_delete=models.CASCADE, related_name='system_comp')
    comp_org_type    =  models.ForeignKey(OrganisationType, on_delete=models.CASCADE, related_name='comp_org_type')
    date_added       = models.DateTimeField(default = timezone.now)
    org_type_comp_added_by = models.BigIntegerField(),
    is_active = models.BooleanField(default=False)
    class Meta:
        db_table = 'public\".\"org_type_component'


# view model for all components / features assigned to the organisation
class OrganisationFeature(models.Model):
    id = models.IntegerField(primary_key=True)
    component_id =  models.CharField(max_length=255)
    component   =  models.CharField(max_length=255)
    desc        =  models.CharField(max_length=255)
    type        =  models.CharField(max_length=255)
    key         =  models.CharField(max_length=255)
    date_added  = models.CharField(max_length=255)
    parent      = models.CharField(max_length=255)
    is_active   = models.CharField(max_length=255)
    is_feature_active   = models.CharField(max_length=255)
    org_id      = models.CharField(max_length=255)
    org_name    = models.CharField(max_length=255)
    org_short_name = models.CharField(max_length=255)
    class Meta:
        managed = False
        db_table = 'public\".\"organisation_feature_view'

# for all roles belonging to an organisation.
class UserRole(models.Model):
    PARTNER_TYPES = (
        ('internal', 'Internal Role'),
        ('partner', 'Partner Role'),
    )
    
    role_name     =  models.CharField(max_length=255)
    role_desc     =  models.TextField(blank=True)
    deleted       =  models.CharField(max_length=5, default='0')
    date_added    = models.DateTimeField(default = timezone.now)
    is_active     = models.BooleanField(default=True)
    role_added_by = models.BigIntegerField()
    role_org      =  models.ForeignKey(Organisation, on_delete=models.CASCADE, related_name='role_org')
    
    # Partner-specific fields
    role_type = models.CharField(
        max_length=20, 
        choices=PARTNER_TYPES, 
        default='internal',
        help_text="Type of role - internal or partner"
    )
    partner_name = models.CharField(
        max_length=100, 
        null=True, 
        blank=True,
        help_text="Name of the partner organization (e.g., 'UNCDF')"
    )
    
    class Meta:
        db_table = 'public\".\"user_role'

# for all features belonging to a group/role.
class RoleComponent(models.Model):
    user_role      =  models.ForeignKey(UserRole, on_delete=models.CASCADE, related_name='user_role')
    org_component  =  models.ForeignKey(OrganisationComponent, on_delete=models.CASCADE, related_name='org_component')
    date_added     = models.DateTimeField(default = timezone.now)
    is_active      = models.BooleanField(default=True)
    role_component_added_by = models.BigIntegerField()
    class Meta:
        db_table = 'public\".\"role_component'

class LicenseSettings(models.Model):
    PAYMENT_OPTIONS = (
        ('e-payment', 'E Payment'),
        ('bank', 'Bank'),
        ('cash', 'Cash'),
    )
    license_org             = models.ForeignKey(Organisation,on_delete=models.CASCADE, related_name='license')
    subcription_date        = models.DateTimeField(default = timezone.now)
    payment_method          = models.CharField(max_length=255, choices=PAYMENT_OPTIONS, default='cash')
    selected_account        = models.CharField(max_length=255,blank=True,null=True)
    expense_chart           = models.CharField(max_length=255,blank=True,null=True)
    license_added_by        = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='license_added_by')
    license_last_updated_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='license_last_updated_by',null=True, blank=True)
    date_added              = models.DateTimeField(default = timezone.now)
    last_updated            = models.DateTimeField(default = timezone.now)
    amount            = models.FloatField(null=False,default=0)
    
    class Meta:
        db_table = 'public\".\"license_settings'

class WorkingHours(models.Model):
    organ_branch = models.ForeignKey(OrganisationBranch,on_delete=models.CASCADE, related_name='org_working_hours')
    week_days    = models.CharField(max_length=255,blank=True,null=True)
    start_time   = models.TimeField()
    end_time     = models.TimeField()
    is_checked   = models.BooleanField(null=False, blank=False, default=False)
    added_by     = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='hours_added_by')
    last_updated_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='hours_last_updated_by',null=True, blank=True)
    date_added   = models.DateTimeField(default = timezone.now)
    last_updated = models.DateTimeField(default = timezone.now)

    class Meta:
        db_table = 'public\".\"working_hours'

class StaffWorkingHours(models.Model):
    organ_branch = models.ForeignKey(OrganisationBranch,on_delete=models.CASCADE, related_name='role_branch')
    start_time   = models.TimeField()
    end_time     = models.TimeField()
    extra_time   = models.TimeField(blank=True,null=True)
    is_checked   = models.BooleanField(null=False, blank=False, default=False)
    user_role    = models.ForeignKey(UserRole,on_delete=models.CASCADE,related_name='user_role_hours')
    added_by     = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='staff_hours_added_by')
    last_updated_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='staff_hours_last_updated_by',null=True, blank=True)
    date_added   = models.DateTimeField(default = timezone.now)
    last_updated = models.DateTimeField(default = timezone.now)


class VoucherConfig(models.Model):
    name = models.CharField(blank=True, max_length=255, null=True)
    start_no = models.BigIntegerField()
    increment_no = models.BigIntegerField()
    current_value = models.BigIntegerField()
    status = models.CharField(blank=True, max_length=255, null=True, default='Active')
    created_at = models.DateTimeField(auto_now_add=True, editable=False)
    updated_at = models.DateTimeField(auto_now=True, editable=False)
    added_by = models.BigIntegerField()
    organisation_id =  models.BigIntegerField()
    # branch_id =  models.BigIntegerField(blank=True, null=True default=0)
    # undo_id =  models.BigIntegerField(blank=True, null=True default=0)
    branch_id = models.BigIntegerField(blank=True, null=True, default=0)
    # undo_id = models.BigIntegerField(blank=True, null=True, default=0)

    class Meta:
        db_table = 'public\".\"voucher_config'

class PartnerAccess(models.Model):
    """
    Model to control partner access to specific endpoints
    """
    user = models.OneToOneField(
        settings.AUTH_USER_MODEL, 
        on_delete=models.CASCADE,
        related_name='partner_access'
    )
    partner_name = models.CharField(max_length=100)
    allowed_endpoints = models.JSONField(
        default=list,
        help_text="List of allowed API endpoints for this partner"
    )
    is_active = models.BooleanField(default=True)
    created_at = models.DateTimeField(auto_now_add=True)
    created_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name='created_partner_accesses'
    )
    
    class Meta:
        db_table = 'public\".\"partner_access'
        
    def __str__(self):
        return f"Partner Access for {self.user.username} - {self.partner_name}"


class OrganisationLocation(models.Model):
    name = models.CharField(max_length=255)
    location_code = models.CharField(max_length=100, null=True, blank=True)
    is_active = models.BooleanField(default=True)
    organisation = models.ForeignKey(Organisation, on_delete=models.CASCADE, related_name='locations')
    date_added = models.DateTimeField(default=timezone.now)
    added_by = models.BigIntegerField(null=True, blank=True)

    class Meta:
        db_table = 'public"."organisation_location'

    def __str__(self):
        return self.name
