# This is an auto-generated Django model module.
# You'll have to do the following manually to clean this up:
#   * Rearrange models' order
#   * Make sure each model has one field with primary_key=True
#   * Make sure each ForeignKey and OneToOneField has `on_delete` set to the desired behavior
#   * Remove `managed = False` lines if you wish to allow Django to create, modify, and delete the table
# Feel free to rename the models, but don't rename db_table values or field names.

from django.db import models
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, BaseUserManager
from django.contrib.auth import authenticate, login
from django.utils import timezone
from datetime import timedelta

# from django.db.models import (
#     Value, F, Max, Q, CharField, Case, When, Concat
# )
# from django.db.models.functions import Coalesce, Concat, Cast
# from django.utils.timezone import localtime
from django.conf import settings
from django.utils.text import slugify
from functools import partial
import os
from django.db import migrations
from django.db.models import Value, F, Max, CharField, Case, When
from django.db.models.functions import Coalesce, Concat, Cast
# from users.middleware import get_current_user
# from multiselectfield import MultiSelectField
from django.db.models import signals


class Airlines(models.Model):
    id = models.AutoField(primary_key=True)
    iata = models.TextField(max_length=250, blank=True, null=True)  # Field name made lowercase.
    icao = models.TextField(max_length=250, blank=True, null=True)  # Field name made lowercase.
    airline = models.TextField(max_length=250, blank=True, null=True)  # Field name made lowercase.
    callsign = models.TextField(max_length=250, blank=True, null=True)  # Field name made lowercase.
    country = models.TextField(max_length=250, blank=True, null=True)  # Field name made lowercase.

    class Meta:
        db_table = 'airlines'
    
    def __str__(self):
        return self.airline or ""
    
    
class AssocClientCompany(models.Model):
    ref_company = models.ForeignKey('users.Company', on_delete=models.SET_NULL, blank=True, null=True, related_name="assoc_client_company")
    ref_client = models.ForeignKey('users.Client', on_delete=models.SET_NULL, blank=True, null=True, related_name="client_companies")
    designation = models.CharField(max_length=50, blank=True, null=True)
    primary_company = models.BooleanField(default=False, null=True, blank=True)

    class Meta:
        db_table = 'assoc_client_company'


class AuthGroupsUser(models.Model):
    user = models.ForeignKey('users.User', on_delete=models.CASCADE, blank=True, null=True)
    group = models.CharField(max_length=255)
    created_at = models.DateTimeField()

    class Meta:
        db_table = 'auth_groups_users'


class AuthLogin(models.Model):
    ip_address = models.CharField(max_length=255)
    user_agent = models.CharField(max_length=255, blank=True, null=True)
    id_type = models.CharField(max_length=255)
    identifier = models.CharField(max_length=255)
    user_id = models.PositiveIntegerField(blank=True, null=True)
    date = models.DateTimeField()
    success = models.IntegerField()

    class Meta:
        db_table = 'auth_logins'


class AuthPermissionsUser(models.Model):
    user = models.ForeignKey('users.User', on_delete=models.CASCADE, blank=True, null=True)
    permission = models.CharField(max_length=255)
    created_at = models.DateTimeField()

    class Meta:
        db_table = 'auth_permissions_users'


class AuthRememberToken(models.Model):
    selector = models.CharField(unique=True, max_length=255)
    hashedvalidator = models.CharField(db_column='hashedValidator', max_length=255)  # Field name made lowercase.
    user = models.ForeignKey('users.User', on_delete=models.SET_NULL, blank=True, null=True)
    expires = models.DateTimeField()
    created_at = models.DateTimeField()
    updated_at = models.DateTimeField()

    class Meta:
        db_table = 'auth_remember_tokens'


class AuthTokenLogin(models.Model):
    ip_address = models.CharField(max_length=255)
    user_agent = models.CharField(max_length=255, blank=True, null=True)
    id_type = models.CharField(max_length=255)
    identifier = models.CharField(max_length=255)
    user_id = models.PositiveIntegerField(blank=True, null=True)
    date = models.DateTimeField()
    success = models.IntegerField()

    class Meta:
        db_table = 'auth_token_logins'


class Cities(models.Model):
    name = models.CharField(max_length=30)
    state_id = models.ForeignKey('users.State', on_delete=models.SET_NULL, null=True, blank=True)

    class Meta:
        db_table = 'cities'
    
    def __str__(self):
        return self.name or ""


def client_upload_path(instance, filename, folder):
    # Use the client id if available, else 'unassigned'
    client_id = getattr(instance.ref_client, "client_id", None) or getattr(instance, "client_id", None) or "unassigned"
    # Fallback folder name for empty folder string
    # folder_name = folder if folder else "documents"
    return os.path.join("uploads", "clients", str(client_id), folder, filename)

client_aadhar_card_path = partial(client_upload_path, folder="")
client_pan_card_path = partial(client_upload_path, folder="")
client_passport_path = partial(client_upload_path, folder="")
client_insurance_path = partial(client_upload_path, folder="insurance")
client_visa_path = partial(client_upload_path, folder="visas")
client_document_path = partial(client_upload_path, folder="other_documents")

def company_upload_path(instance, filename, folder):
    # Use the client id if available, else 'unassigned'
    company_id = instance.id or "unassigned"
    # Fallback folder name for empty folder string
    # folder_name = folder if folder else "documents"
    return os.path.join("uploads", "company", str(company_id), folder, filename)

company_gst_doc_path = partial(company_upload_path, folder="")

# def aadhar_card_upload_to(instance, filename):
#     # return client_upload_path(instance, filename, "")
#     return f"clients/{instance.pk}/aadhar_card/{filename.split('/')[-1]}"

# def pan_card_upload_to(instance, filename):
#     return client_upload_path(instance, filename, "")

# def temp_documents_upload_path(instance, filename):

#     return os.path.join('temp_uploads', filename)
    

# class Client(models.Model):
#     SALUTION = [
#         ('Mr.', 'Mr.'),
#         ('Ms.', 'Ms.'),
#         ('Mrs.', 'Mrs.'),
#         ('Miss.', 'Miss.'),
#         ('Master', 'Master'),
#         ('Dr.', 'Dr.'),
#     ]

#     GENDER = [
#         ('Male', 'Male'),
#         ('Female', 'Female'),
#         ('Other', 'Other'),
#     ]

#     MARITAL_STATUS = [
#         ('Married', 'Married'),
#         ('Unmarried', 'Unmarried'),
#         ('Divorced', 'Divorced'),
#     ]

#     REFERENCE_FROM = [
#         ('Walk In', 'Walk In'),
#         ('BNI', 'BNI'),
#         ('Client', 'Client'),
#         ('Atul Sir', 'Atul_sir'),
#         ('Jignesh Sir', 'Jignesh_Sir'),
#         ('Counter', 'Counter/Internal_Staff'),
#     ]

#     RELATION = [
#         ('Father', 'Father'),
#         ('Mother', 'Mother'),
#         ('Spouse', 'Spouse'),
#         ('Daughter', 'Daughter'),
#         ('Brother', 'Brother'),
#         ('Sister', 'Sister'),
#         ('Son', 'Son'),
#     ]

#     CROSS_RELATION = [
#         ('Father', 'Father'),
#         ('Mother', 'Mother'),
#         ('Spouse', 'Spouse'),
#         ('Daughter', 'Daughter'),
#         ('Brother', 'Brother'),
#         ('Sister', 'Sister'),
#         ('Son', 'Son'),
#     ]

#     CLIENT_TYPE = [
#         ('Primary Member', 'Primary-Member'),
#         ('Family Member', 'Family-Member'),
#     ]

#     PREFERED_FARE_TYPE = [
#         ('F - First class', 'F - First class'),
#         ('J - Business class', 'J - Business class'),
#         ('W - Premium economy', 'W - Premium economy'),
#         ('Y - Economy class', 'Y - Economy class'),
#     ]

#     PREFERED_MEAL = [
#         ('Veg', 'Veg'),
#         ('Non-Veg', 'Non-Veg'),
#         ('Jain Food', 'Jain-Food'),
#     ]

#     ROOM_PREFERED = [
#         ('King Size Bed', 'King_Size_Bed'),
#         ('Smoking Room', 'Smoking_Room'),
#         ('Non-Smoking Room', 'Non-Smoking_Room'),
#     ]

#     STAY_PREFERED = [
#         ('Short Stay (1–2 Nights)', 'Short Stay (1–2 Nights)'),
#         ('Long Stay (3+ Nights)', 'Long Stay (3+ Nights)'),
#         ('Business Stay', 'Business Stay'),
#         ('Leisure Stay', 'Leisure Stay'),
#         ('Staycation', 'Staycation'),
#     ]

#     STAR_RATING = [
#         ('3 Star', '3 Star'),
#         ('4 Star', '4 Star'),
#         ('5 Star', '5 Star'),
#     ]

#     SEAT_PREFERED = [
#         ('Window', 'Window'),
#         ('Aisle', 'Aisle'),
#         ('Middle', 'Middle'),
#         ('Double Seat', 'Double_Seat'),
#         ('First Row', 'First_Row'),
#         ('Emergency Exit Row', 'Emergency Exit Row'),
#         ('Other', 'Other'),
#     ]

#     class Status(models.IntegerChoices):
#         INACTIVE = 0, "Inactive"
#         ACTIVE = 1, "Active"
#         DELETED = 2, "Deleted"

#     EXTRA_AMENITIES = [
#         ('Breakfast Included', 'Breakfast Included'),
#         ('Swimming Pool Access', 'Swimming Pool Access'),
#         ('Gym Access', 'Gym Access'),
#         ('Near Airport', 'Near Airport'),
#         ('Near City Center', 'Near City Center'),
#     ]

#     client_id = models.AutoField(primary_key=True)
#     old_ref_client_id = models.IntegerField(blank=True, null=True)
#     ref_client = models.ForeignKey('self', on_delete=models.SET_NULL, blank=True, null=True, db_column="ref_client_id", related_name='related_clients')
#     relation = models.CharField(max_length=20, choices=RELATION, blank=True, null=True)
#     crossrelation = models.CharField(max_length=20, choices=CROSS_RELATION, blank=True, null=True)

#     client_salutation = models.CharField(max_length=20, choices=SALUTION, blank=True, null=True)
#     client_first_name = models.CharField(max_length=500, blank=True, null=True)
#     client_middle_name = models.CharField(max_length=500, blank=True, null=True, default='')
#     client_last_name = models.CharField(max_length=500, blank=True, null=True, default='')
#     client_code = models.CharField(max_length=50, unique=True, blank=True, null=True)

#     client_type = models.CharField(max_length=30, choices=CLIENT_TYPE, blank=True, null=True)
#     is_prepayment = models.BooleanField(default=False)

#     dob = models.DateField(blank=True, null=True)
#     country_code = models.ForeignKey('Countries', on_delete=models.SET_NULL, null=True, blank=True, db_column='country_code', related_name='country_codes')
#     contact_no = models.CharField(max_length=20, blank=True, null=True, default='')
#     email = models.CharField(max_length=500, blank=True, null=True, default='')
#     gender = models.CharField(max_length=10, choices=GENDER, blank=True, null=True, default='')
#     marital_status = models.CharField(max_length=50, choices=MARITAL_STATUS, blank=True, null=True)
#     anniversary_date = models.DateField(blank=True, null=True)

#     reference_from = models.CharField(max_length=50, choices=REFERENCE_FROM, blank=True, null=True)
#     reference_id = models.IntegerField(blank=True, null=True)
#     # clientRef_id = models.ForeignKey('self', on_delete=models.SET_NULL, blank=True, null=True, db_column="clientRef_id", related_name='client_related')
#     reference_remark = models.CharField(max_length=150, blank=True, null=True, default='')
    
#     occupation = models.CharField(max_length=500, blank=True, null=True, default='')
#     preferred_contact_method = models.JSONField(default=list, blank=True, null=True)

#     PREFERRED_CONTACT_METHODS = {
#         'Mail': 'Mail',
#         'Call': 'Call',
#         'WhatsApp': 'WhatsApp',
#         'Group Message': 'Group Message',
#     }

#     def get_preferred_contact_method_display(self):
#         values = []
#         for v in (self.preferred_contact_method or []):
#             if isinstance(v, dict):  
#                 # Handle stored dicts safely
#                 key = v.get("id") or v.get("value") or v.get("label")
#             else:
#                 key = str(v)
#             if key:
#                 values.append(self.PREFERRED_CONTACT_METHODS.get(key, key))
#         return ", ".join(values)
    
#     aadhaar_card_file = models.FileField(upload_to=client_aadhar_card_path, blank=True, null=True)
#     aadhaar_no = models.CharField(max_length=20, blank=True, null=True)
#     pan_card_file = models.FileField(upload_to=client_pan_card_path, blank=True, null=True)
#     pan_no = models.CharField(max_length=15, blank=True, null=True)

#     residential_address = models.CharField(max_length=500, blank=True, null=True)
#     residential_city = models.ForeignKey('users.Cities', on_delete=models.SET_NULL, null=True, blank=True, db_column='residential_city', related_name='residential_city')
#     residential_state = models.ForeignKey('users.State', on_delete=models.SET_NULL, null=True, blank=True, db_column='residential_state', related_name='residential_state')
#     residential_country = models.ForeignKey('users.Countries', on_delete=models.SET_NULL, null=True, blank=True, db_column='residential_country', related_name='residential_country')
#     residential_pincode = models.CharField(max_length=10, blank=True, null=True)

#     ref_preferred_airline = models.ForeignKey('users.Airlines', on_delete=models.SET_NULL, null=True, blank=True, db_column='ref_preferred_airline', related_name='ref_preferred_airline_clients')
#     seat_preference = models.CharField(max_length=30, choices=SEAT_PREFERED, blank=True, null=True)
#     seat_preference_other = models.CharField(max_length=50, blank=True, null=True)
#     meal_preference = models.CharField(max_length=10, choices=PREFERED_MEAL, blank=True, null=True)
#     fare_preference = models.CharField(max_length=20, choices=PREFERED_FARE_TYPE, blank=True, null=True)
#     star_rating = models.CharField(max_length=10, choices=STAR_RATING, blank=True, null=True)
#     stay_preference = models.CharField(max_length=50, choices=STAY_PREFERED, blank=True, null=True)
#     room_preference = models.CharField(max_length=50, choices=ROOM_PREFERED, blank=True, null=True)
#     extra_amenities = models.CharField(max_length=50, choices=EXTRA_AMENITIES, blank=True, null=True)

#     client_status = models.SmallIntegerField(choices=Status.choices, blank=True, null=True, default=Status.ACTIVE)
#     is_active = models.SmallIntegerField(default=1)

#     created_at = models.DateTimeField(auto_now_add=True, blank=True, null=True)
#     created_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, blank=True, null=True, db_column='created_by', related_name='clients_created')
#     updated_at = models.DateTimeField(auto_now=True, blank=True, null=True)
#     updated_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, blank=True, null=True, db_column='updated_by', related_name='clients_updated')

#     def save(self, *args, **kwargs):
#         if self.client_status == 1:
#             self.is_active = True
#         elif self.client_status == 0:
#             self.is_active = False
#         else:
#             # fallback: sync based on is_active
#             self.client_status = 1 if self.is_active else 0
#         super().save(*args, **kwargs)

#     @property
#     def full_name(self):
#         return f"{self.client_first_name or ''} {self.client_middle_name or ''} {self.client_last_name or ''}".strip()
    
#     # def save(self, *args, **kwargs):

#     #     temp_files = {}
#     #     if not self.pk:  # New client
#     #         if self.aadhaar_card_file:
#     #             temp_files["aadhaar_card_file"] = self.aadhaar_card_file
#     #             self.aadhaar_card_file = None
#     #         if self.pan_card_file:
#     #             temp_files["pan_card_file"] = self.pan_card_file
#     #             self.pan_card_file = None

#     #         super().save(*args, **kwargs)  # Save client to get ID

#     #         # Assign files with doc type info
#     #         for field, file in temp_files.items():
#     #             self._current_file_field = field  # used by upload_to function
#     #             setattr(self, field, file)

#     #     # Normalize created_at / updated_at to naive datetime without microseconds
#     #     if self.created_at:
#     #         self.created_at = self.created_at.replace(microsecond=0, tzinfo=None)
#     #     if self.updated_at:
#     #         self.updated_at = self.updated_at.replace(microsecond=0, tzinfo=None)

#     #     super().save(*args, **kwargs)

#     def save(self, *args, **kwargs):
    
#         temp_files = {}

#         # Only for new client
#         if not self.pk:
#             if self.aadhaar_card_file:
#                 temp_files["aadhaar_card_file"] = self.aadhaar_card_file
#                 self.aadhaar_card_file = None
#             if self.pan_card_file:
#                 temp_files["pan_card_file"] = self.pan_card_file
#                 self.pan_card_file = None

#             # First save to get ID
#             super().save(*args, **kwargs)

#             # Now assign files
#             for field, file in temp_files.items():
#                 self._current_file_field = field  # used by upload_to
#                 setattr(self, field, file)

#             # Save again, but only update file fields
#             super().save(update_fields=list(temp_files.keys()))
#         else:
#             # Existing client, normal save
#             # Normalize datetime fields
#             if self.created_at:
#                 self.created_at = self.created_at.replace(microsecond=0, tzinfo=None)
#             if self.updated_at:
#                 self.updated_at = self.updated_at.replace(microsecond=0, tzinfo=None)
#             super().save(*args, **kwargs)


#     # def save(self, *args, **kwargs):
#     #     current_user = get_current_user()
#     #     if not self.pk:  # creating new object
#     #         if not self.created_by:
#     #             self.created_by = current_user
#     #     else:  # updating existing object
#     #         self.updated_by = current_user
#     #     super().save(*args, **kwargs)

#     # def save(self, *args, **kwargs):
#     #     if not self.pk:
#     #         # On creation
#     #         if not self.created_by:
#     #             self.created_by = get_current_user()
#     #     else:
#     #         self.updated_by = get_current_user()
#     #     super().save(*args, **kwargs)

#     # def save(self, *args, **kwargs):
#     #     user = get_current_user()

#     #     # Only assign if user is authenticated
#     #     if user and user.is_authenticated:
#     #         if not self.pk and not self.created_by:
#     #             self.created_by = user
#     #         self.updated_by = user

#     #     super().save(*args, **kwargs)

#     def save_with_user(self, *args, user=None, **kwargs):
#         """
#         Custom save method to attach the user who performed the action.
#         """
#         # Attach the user to a temporary attribute for signals
#         if user:
#             self._performed_by = user
#         super().save(*args, **kwargs)

    

#     # def save(self, *args, **kwargs):
#     #     # Temporarily store files
#     #     temp_files = {}
#     #     if not self.pk:  # New client
#     #         if self.aadhaar_card_file:
#     #             temp_files["aadhaar_card_file"] = self.aadhaar_card_file
#     #             self.aadhaar_card_file = None
#     #         if self.pan_card_file:
#     #             temp_files["pan_card_file"] = self.pan_card_file
#     #             self.pan_card_file = None

#     #         super().save(*args, **kwargs)  # Save client to get ID

#     #         # Assign files with doc type info
#     #         for field, file in temp_files.items():
#     #             self._current_file_field = field  # used by upload_to function
#     #             setattr(self, field, file)

#     #     super().save(*args, **kwargs)  # Save again with files



#     class Meta:
#         db_table = 'clients'

class Client(models.Model):
    SALUTION = [
        ('Mr.', 'Mr.'),
        ('Ms.', 'Ms.'),
        ('Mrs.', 'Mrs.'),
        ('Miss.', 'Miss.'),
        ('Master', 'Master'),
        ('Dr.', 'Dr.'),
    ]

    GENDER = [
        ('Male', 'Male'),
        ('Female', 'Female'),
        ('Other', 'Other'),
    ]

    MARITAL_STATUS = [
        ('Married', 'Married'),
        ('Unmarried', 'Unmarried'),
        ('Divorced', 'Divorced'),
    ]

    REFERENCE_FROM = [
        ('Walk In', 'Walk In'),
        ('BNI', 'BNI'),
        ('Client', 'Client'),
        ('Atul Sir', 'Atul_sir'),
        ('Jignesh Sir', 'Jignesh_Sir'),
        ('Counter', 'Counter/Internal_Staff'),
    ]

    RELATION = [
        ('Father', 'Father'),
        ('Mother', 'Mother'),
        ('Spouse', 'Spouse'),
        ('Daughter', 'Daughter'),
        ('Brother', 'Brother'),
        ('Sister', 'Sister'),
        ('Son', 'Son'),
    ]

    CROSS_RELATION = [
        ('Father', 'Father'),
        ('Mother', 'Mother'),
        ('Spouse', 'Spouse'),
        ('Daughter', 'Daughter'),
        ('Brother', 'Brother'),
        ('Sister', 'Sister'),
        ('Son', 'Son'),
    ]

    CLIENT_TYPE = [
        ('Primary Member', 'Primary-Member'),
        ('Family Member', 'Family-Member'),
    ]

    PREFERED_FARE_TYPE = [
        ('F - First class', 'F - First class'),
        ('J - Business class', 'J - Business class'),
        ('W - Premium economy', 'W - Premium economy'),
        ('Y - Economy class', 'Y - Economy class'),
    ]

    PREFERED_MEAL = [
        ('Veg', 'Veg'),
        ('Non-Veg', 'Non-Veg'),
        ('Jain Food', 'Jain-Food'),
    ]

    ROOM_PREFERED = [
        ('King Size Bed', 'King_Size_Bed'),
        ('Smoking Room', 'Smoking_Room'),
        ('Non-Smoking Room', 'Non-Smoking_Room'),
    ]

    STAY_PREFERED = [
        ('Short Stay (1–2 Nights)', 'Short Stay (1–2 Nights)'),
        ('Long Stay (3+ Nights)', 'Long Stay (3+ Nights)'),
        ('Business Stay', 'Business Stay'),
        ('Leisure Stay', 'Leisure Stay'),
        ('Staycation', 'Staycation'),
    ]

    STAR_RATING = [
        ('3 Star', '3 Star'),
        ('4 Star', '4 Star'),
        ('5 Star', '5 Star'),
    ]

    SEAT_PREFERED = [
        ('Window', 'Window'),
        ('Aisle', 'Aisle'),
        ('Middle', 'Middle'),
        ('Double Seat', 'Double_Seat'),
        ('First Row', 'First_Row'),
        ('Emergency Exit Row', 'Emergency Exit Row'),
        ('Other', 'Other'),
    ]

    class Status(models.IntegerChoices):
        INACTIVE = 0, "Inactive"
        ACTIVE = 1, "Active"
        DELETED = 2, "Deleted"

    EXTRA_AMENITIES = [
        ('Breakfast Included', 'Breakfast Included'),
        ('Swimming Pool Access', 'Swimming Pool Access'),
        ('Gym Access', 'Gym Access'),
        ('Near Airport', 'Near Airport'),
        ('Near City Center', 'Near City Center'),
    ]

    client_id = models.AutoField(primary_key=True)
    old_ref_client_id = models.IntegerField(blank=True, null=True)
    ref_client = models.ForeignKey('self', on_delete=models.SET_NULL, blank=True, null=True, db_column="ref_client_id", related_name='related_clients')
    relation = models.CharField(max_length=20, choices=RELATION, blank=True, null=True)
    crossrelation = models.CharField(max_length=20, choices=CROSS_RELATION, blank=True, null=True)

    client_salutation = models.CharField(max_length=20, choices=SALUTION, blank=True, null=True)
    client_first_name = models.CharField(max_length=500, blank=True, null=True)
    client_middle_name = models.CharField(max_length=500, blank=True, null=True, default='')
    client_last_name = models.CharField(max_length=500, blank=True, null=True, default='')
    client_code = models.CharField(max_length=50, unique=True, blank=True, null=True)

    client_type = models.CharField(max_length=30, choices=CLIENT_TYPE, blank=True, null=True)
    is_prepayment = models.BooleanField(default=False)

    dob = models.DateField(blank=True, null=True)
    country_code = models.ForeignKey('Countries', on_delete=models.SET_NULL, null=True, blank=True, db_column='country_code', related_name='country_codes')
    contact_no = models.CharField(max_length=20, blank=True, null=True, default='')
    email = models.CharField(max_length=500, blank=True, null=True, default='')
    gender = models.CharField(max_length=10, choices=GENDER, blank=True, null=True, default='')
    marital_status = models.CharField(max_length=50, choices=MARITAL_STATUS, blank=True, null=True)
    anniversary_date = models.DateField(blank=True, null=True)

    reference_from = models.CharField(max_length=50, choices=REFERENCE_FROM, blank=True, null=True)
    reference_id = models.IntegerField(blank=True, null=True)
    reference_remark = models.CharField(max_length=150, blank=True, null=True, default='')
    
    occupation = models.CharField(max_length=500, blank=True, null=True, default='')
    preferred_contact_method = models.JSONField(default=list, blank=True, null=True)

    PREFERRED_CONTACT_METHODS = {
        'Mail': 'Mail',
        'Call': 'Call',
        'WhatsApp': 'WhatsApp',
        'Group Message': 'Group Message',
    }

    def get_preferred_contact_method_display(self):
        values = []
        for v in (self.preferred_contact_method or []):
            if isinstance(v, dict):  
                key = v.get("id") or v.get("value") or v.get("label")
            else:
                key = str(v)
            if key:
                values.append(self.PREFERRED_CONTACT_METHODS.get(key, key))
        return ", ".join(values)
    
    aadhaar_card_file = models.FileField(upload_to=client_aadhar_card_path, blank=True, null=True)
    aadhaar_no = models.CharField(max_length=20, blank=True, null=True)
    pan_card_file = models.FileField(upload_to=client_pan_card_path, blank=True, null=True)
    pan_no = models.CharField(max_length=15, blank=True, null=True)

    residential_address = models.CharField(max_length=500, blank=True, null=True)
    residential_city = models.ForeignKey('users.Cities', on_delete=models.SET_NULL, null=True, blank=True, db_column='residential_city', related_name='residential_city')
    residential_state = models.ForeignKey('users.State', on_delete=models.SET_NULL, null=True, blank=True, db_column='residential_state', related_name='residential_state')
    residential_country = models.ForeignKey('users.Countries', on_delete=models.SET_NULL, null=True, blank=True, db_column='residential_country', related_name='residential_country')
    residential_pincode = models.CharField(max_length=10, blank=True, null=True)

    ref_preferred_airline = models.ForeignKey('users.Airlines', on_delete=models.SET_NULL, null=True, blank=True, db_column='ref_preferred_airline', related_name='ref_preferred_airline_clients')
    seat_preference = models.CharField(max_length=30, choices=SEAT_PREFERED, blank=True, null=True)
    seat_preference_other = models.CharField(max_length=50, blank=True, null=True)
    meal_preference = models.CharField(max_length=10, choices=PREFERED_MEAL, blank=True, null=True)
    fare_preference = models.CharField(max_length=20, choices=PREFERED_FARE_TYPE, blank=True, null=True)
    star_rating = models.CharField(max_length=10, choices=STAR_RATING, blank=True, null=True)
    stay_preference = models.CharField(max_length=50, choices=STAY_PREFERED, blank=True, null=True)
    room_preference = models.CharField(max_length=50, choices=ROOM_PREFERED, blank=True, null=True)
    extra_amenities = models.CharField(max_length=50, choices=EXTRA_AMENITIES, blank=True, null=True)

    client_status = models.SmallIntegerField(choices=Status.choices, blank=True, null=True, default=Status.ACTIVE)
    is_active = models.SmallIntegerField(default=1)

    created_at = models.DateTimeField(auto_now_add=True, blank=True, null=True)
    created_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, blank=True, null=True, db_column='created_by', related_name='clients_created')
    updated_at = models.DateTimeField(auto_now=True, blank=True, null=True)
    updated_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, blank=True, null=True, db_column='updated_by', related_name='clients_updated')

    def save(self, *args, **kwargs):
        print(f"Saving client: pk={self.pk}, client_first_name={self.client_first_name}")
        # Sync client_status and is_active
        if self.client_status == 1:
            self.is_active = True
        elif self.client_status == 0:
            self.is_active = False
        else:
            self.client_status = 1 if self.is_active else 0

        # Handle file fields for new clients
        # temp_files = {}
        # if not self.pk:  # New client
        #     if self.aadhaar_card_file:
        #         temp_files["aadhaar_card_file"] = self.aadhaar_card_file
        #         self.aadhaar_card_file = None
        #     if self.pan_card_file:
        #         temp_files["pan_card_file"] = self.pan_card_file
        #         self.pan_card_file = None

        # Single save for non-file fields
        super().save(*args, **kwargs)

        # Handle file fields after getting ID
        # if temp_files:
        #     for field, file in temp_files.items():
        #         self._current_file_field = field  # Used by upload_to
        #         setattr(self, field, file)
        #     # Save only file fields, but disconnect post_save signal to avoid update log
        #     super().save(update_fields=list(temp_files.keys()))

            # try:
            #     print(f"Updating file fields for client {self.pk}: {temp_files.keys()}")
            #     # signals.post_save.disconnect(sender=Client, dispatch_uid="log_client_activity")
            # finally:
            #     signals.post_save.connect(sender=Client, dispatch_uid="log_client_activity")

    def save_with_user(self, *args, user=None, **kwargs):
        """
        Custom save method to attach the user who performed the action.
        """
        if user:
            self._performed_by = user
        super().save(*args, **kwargs)

    @property
    def full_name(self):
        return f"{self.client_first_name or ''} {self.client_middle_name or ''} {self.client_last_name or ''}".strip()

    class Meta:
        db_table = 'clients'

    # def member_type(self):
    #     return "Primary Member" if not self.client_id else "Family Member"

class ClientDataView(models.Model):
    client_id = models.IntegerField(primary_key=True)
    ref_client_id = models.IntegerField(null=True)
    relation = models.CharField(max_length=255, blank=True, null=True)
    client_salutation = models.CharField(max_length=20, blank=True, null=True)
    client_first_name = models.CharField(max_length=255)
    client_middle_name = models.CharField(max_length=255, blank=True, null=True)
    client_last_name = models.CharField(max_length=255, blank=True, null=True)
    client_code = models.CharField(max_length=100)
    dob = models.DateField(blank=True, null=True)
    country_code = models.IntegerField(blank=True, null=True)
    contact_no = models.CharField(max_length=50, blank=True, null=True)
    email = models.CharField(max_length=255, blank=True, null=True)
    gender = models.CharField(max_length=20, blank=True, null=True)
    marital_status = models.CharField(max_length=50, blank=True, null=True)
    anniversary_date = models.DateField(blank=True, null=True)
    occupation = models.CharField(max_length=255, blank=True, null=True)
    aadhaar_card_file = models.CharField(max_length=255, blank=True, null=True)
    aadhaar_no = models.CharField(max_length=50, blank=True, null=True)
    pan_card_file = models.CharField(max_length=255, blank=True, null=True)
    pan_no = models.CharField(max_length=50, blank=True, null=True)
    residential_address = models.CharField(max_length=500, blank=True, null=True)
    residential_city = models.IntegerField(blank=True, null=True)
    residential_state = models.IntegerField(blank=True, null=True)
    residential_country = models.IntegerField(blank=True, null=True)
    residential_pincode = models.CharField(max_length=20, blank=True, null=True)
    client_status = models.CharField(max_length=20, blank=True, null=True)
    created_at = models.DateTimeField(blank=True, null=True)
    created_by = models.IntegerField(blank=True, null=True)
    updated_at = models.DateTimeField(blank=True, null=True)
    updated_by = models.IntegerField(blank=True, null=True)
    full_contact_no = models.CharField(max_length=50, blank=True, null=True)
    dateOfBirth = models.CharField(max_length=20, blank=True, null=True)
    anniversaryDate = models.CharField(max_length=20, blank=True, null=True)
    passport_no = models.CharField(max_length=50, blank=True, null=True)
    passportExpiryDate = models.CharField(max_length=20, blank=True, null=True)
    city_name = models.CharField(max_length=255, blank=True, null=True)
    company_name = models.CharField(max_length=255, blank=True, null=True)
    client_name = models.CharField(max_length=500)
    ResidentialAddress = models.CharField(max_length=500, blank=True, null=True)
    client_type = models.CharField(max_length=50)
    clientStatus = models.CharField(max_length=20)
    createdOn = models.CharField(max_length=50)

    class Meta:
        managed = False  # important: Django will not try to create this table
        db_table = 'view_client_data'


class ClientRelation(models.Model):
    from_client = models.ForeignKey(Client, on_delete=models.CASCADE, related_name="relations_from")
    to_client = models.ForeignKey(Client, on_delete=models.CASCADE, related_name="relations_to")
    relation = models.CharField(max_length=20, choices=Client.RELATION, blank=True, null=True)
    cross_relation = models.CharField(max_length=20, choices=Client.CROSS_RELATION, blank=True, null=True)

    class Meta:
        db_table = "clients_relations"


class ClientDocument(models.Model):
    ref_client = models.ForeignKey('users.client', on_delete=models.SET_NULL, null=True, blank=True, related_name="client_documents")
    other_document = models.FileField(upload_to=client_document_path, blank=True, null=True)
    other_document_name = models.CharField(max_length=100, blank=True, null=True)

    class Meta:
        db_table = 'clients_documents'


class ClientFrequentFlyer(models.Model):
    ref_client = models.ForeignKey(Client, on_delete=models.SET_NULL, db_column="ref_client_id", related_name='frequent_flyers', blank=True, null=True)
    ref_airline = models.ForeignKey(Airlines, on_delete=models.SET_NULL, db_column="ref_airline_id", related_name='frequent_flyers_airlines', blank=True, null=True)
    ff_no = models.CharField(max_length=50, blank=True, null=True)

    class Meta:
        db_table = 'clients_frequent_flyer'


class ClientLog(models.Model):
    ref_client_id = models.ForeignKey('Client', on_delete=models.SET_NULL, blank=True, null=True, db_column='ref_client_id', related_name="client_logs")
    ref_company_id = models.ForeignKey('Company', on_delete=models.SET_NULL, blank=True, null=True, db_column='ref_company_id', related_name="company_logs")
    ref_user_id = models.ForeignKey('users.User', on_delete=models.SET_NULL, blank=True, null=True, db_column='ref_user_id', related_name="users_logs")
    # ref_client_id = models.IntegerField(null=True, blank=True)
    ref_table_name = models.CharField(max_length=100, blank=True, null=True)
    ref_id = models.IntegerField(blank=True, null=True)
    action_type = models.CharField(max_length=50, blank=True, null=True)
    changed_data = models.JSONField()
    # performed_by = models.ForeignKey('users.User', on_delete=models.CASCADE, null=True)
    performed_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True, blank=True)
    performed_at = models.DateTimeField(blank=True, null=True)

    @property
    def formatted_performed_at(self):
        return self.performed_at.strftime("%d/%m/%Y %H:%M")

    class Meta:
        db_table = 'clients_logs'


class ClientPassport(models.Model):
    ref_client = models.ForeignKey(Client, on_delete=models.SET_NULL, blank=True, null=True, related_name="client_passport")
    passport_file = models.FileField(upload_to=client_passport_path, blank=True, null=True)
    passport_no = models.CharField(max_length=20, blank=True, null=True)
    passport_expiry_date = models.DateField(blank=True, null=True)

    class Meta:
        db_table = 'clients_passports'


class ClientTravelInsurance(models.Model):
    ref_client = models.ForeignKey(Client, on_delete=models.SET_NULL, blank=True, null=True, related_name="travel_insurance")
    insurance_document = models.FileField(upload_to=client_insurance_path, blank=True, null=True)
    insurance_from_date = models.DateField(blank=True, null=True)
    insurance_to_date = models.DateField(blank=True, null=True)

    class Meta:
        db_table = 'clients_travel_insurance'


class ClientVisa(models.Model):
    VISA_TYPE = (
        ('Business Visa', 'Business Visa'),
        ('Employment Visa', 'Employment Visa'),
        ('Tourist Visa', 'Tourist Visa'),
        ('Medical Visa', 'Medical Visa'),
        ('Student Visa', 'Student Visa'),
    )
    ref_client = models.ForeignKey(Client, on_delete=models.SET_NULL, blank=True, null=True, related_name="client_visa")
    ref_visa_country = models.ForeignKey('Countries', on_delete=models.CASCADE, related_name="ref_visa_country", blank=True, null=True)
    visa_type = models.CharField(max_length=20, choices=VISA_TYPE, blank=True, null=True)
    passport_size_photograph = models.FileField(upload_to=client_visa_path, blank=True, null=True)
    visa_from_date = models.DateField(blank=True, null=True)
    visa_to_date = models.DateField(blank=True, null=True)

    class Meta:
        db_table = 'clients_visas'


class Company(models.Model):
    COMPANY_STATUS = (
        ('active', 'Active'),
        ('inactive', 'Inactive'),
    )
    company_name = models.CharField(max_length=100)
    company_address = models.CharField(max_length=200, blank=True, null=True)

    company_city = models.ForeignKey('Cities', on_delete=models.SET_NULL, null=True, db_column='company_city')
    company_state = models.ForeignKey('State', on_delete=models.SET_NULL, null=True, db_column='company_state')
    company_country = models.ForeignKey('Countries', on_delete=models.SET_NULL, null=True, db_column='company_country')

    company_pincode = models.CharField(max_length=10, null=True, blank=True, default="")
    gst_name = models.CharField(max_length=100, blank=True, null=True, default="")
    gst_no = models.CharField(max_length=15, blank=True, null=True, default="")
    gst_document_file = models.FileField(upload_to=company_gst_doc_path, blank=True, null=True)

    account_concerned_person = models.CharField(max_length=100, blank=True, null=True, default="")
    account_concerned_person_country_code = models.ForeignKey(
        'Countries', on_delete=models.SET_NULL, null=True, blank=True,
        related_name='account_country_code', db_column='account_concerned_person_country_code'
    )
    account_concerned_person_contact_no = models.CharField(max_length=15, blank=True, null=True, default="")

    travel_concerned_person = models.CharField(max_length=100, blank=True, null=True)
    travel_concerned_person_country_code = models.ForeignKey(
        'Countries', on_delete=models.SET_NULL, null=True, blank=True,
        related_name='travel_country_code', db_column='travel_concerned_person_country_code'
    )
    travel_concerned_person_contact_no = models.CharField(max_length=15, blank=True, null=True)

    company_status = models.CharField(max_length=20, choices=COMPANY_STATUS, blank=True, null=True, default="active")
    is_active = models.BooleanField(default=True)

    created_at = models.DateTimeField(auto_now_add=True, blank=True, null=True)
    created_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, blank=True, null=True, db_column='created_by', related_name='company_created')
    updated_at = models.DateTimeField(auto_now=True, blank=True, null=True)
    updated_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, blank=True, null=True, db_column='updated_by', related_name='company_updated')

    # def save(self, *args, **kwargs):
    #     if self.company_status == 'active':
    #         self.is_active = True
    #     elif self.company_status == 'inactive':
    #         self.is_active = False
    #     else:
    #         # fallback: sync based on is_active
    #         self.company_status = 'active' if self.is_active else 'inactive'
    #     super().save(*args, **kwargs)

    def save(self, *args, **kwargs):
        temp_files = {}

        # Handle GST document for new company
        if not self.pk:
            # if self.gst_document_file:
            #     temp_files["gst_document_file"] = self.gst_document_file
            #     self.gst_document_file = None

            # Save first to get ID
            super().save(*args, **kwargs)

            # Assign files to proper folder
            for field, file in temp_files.items():
                # Determine folder if needed (can be empty string for default)
                folder = ""  # optional
                full_path = company_upload_path(self, file.name, folder)

                # Save file physically
                storage = getattr(self, field).storage
                saved_path = storage.save(full_path, file)

                # Store only filename in DB
                setattr(self, field, saved_path)

            # Save again only for file fields
            super().save(update_fields=list(temp_files.keys()))
        else:
            # Existing company, normal save
            super().save(*args, **kwargs)

        # Sync company_status to is_active
        if self.company_status == 'active':
            self.is_active = True
        elif self.company_status == 'inactive':
            self.is_active = False
        else:
            self.company_status = 'active' if self.is_active else 'inactive'
        super().save(update_fields=['is_active', 'company_status'])

    class Meta:
        db_table = 'company'

    def __str__(self):
        return self.company_name or ""
    

class CompanyDataView(models.Model):
    id = models.IntegerField(primary_key=True)
    company_name = models.CharField(max_length=255)
    gst_name = models.CharField(max_length=255, blank=True, null=True)
    gst_no = models.CharField(max_length=50, blank=True, null=True)
    CompanyAddress = models.CharField(max_length=500, blank=True, null=True)
    account_concerned_person = models.CharField(max_length=255, blank=True, null=True)
    account_concerned_person_contact_no = models.CharField(max_length=50, blank=True, null=True)
    full_account_concerned_person_contact_no = models.CharField(max_length=50, blank=True, null=True)
    company_status = models.IntegerField(blank=True, null=True)
    companyStatus = models.CharField(max_length=20)

    class Meta:
        managed = False
        db_table = 'view_company_data'

class Countries(models.Model):
    shortname = models.CharField(max_length=3)
    name = models.CharField(max_length=150)
    country_code = models.IntegerField()
    min_length = models.IntegerField(blank=True, null=True)
    max_length = models.IntegerField(blank=True, null=True)

    class Meta:
        db_table = 'countries'

    def __str__(self):
        return self.name or ""
    

class LoginOTP(models.Model):
    PURPOSE_CHOICES = (
        ('login', 'Login'),
        ('forgot_password', 'Forgot Password'),
    )

    user = models.OneToOneField('User', on_delete=models.CASCADE, related_name="login_otp")
    otp = models.CharField(max_length=6)
    created_at = models.DateTimeField(auto_now_add=True)
    is_verified = models.BooleanField(default=False)
    purpose = models.CharField(max_length=20, choices=PURPOSE_CHOICES, default='login')

    def is_expired(self):
        return timezone.now() > self.created_at + timedelta(minutes=5)

    def __str__(self):
        return f"OTP for {self.user.email} - {self.otp} ({self.purpose})"


class Menu(models.Model):
    ref_menu = models.ForeignKey('self', on_delete=models.SET_NULL, blank=True, null=True, related_name='submenus')
    menu_name = models.CharField(max_length=100)
    menu_action = models.CharField(max_length=100, blank=True, null=True)
    menu_url = models.CharField(max_length=255, blank=True, default="#")
    menu_order_no = models.PositiveSmallIntegerField(blank=True, null=True)
    parent = models.ForeignKey('self', on_delete=models.SET_NULL, blank=True, null=True)
    menu_default = models.BooleanField(default=False)
    menu_status = models.BooleanField(default=True)

    def __str__(self):
        return self.menu_name or ""

    class Meta:
        db_table = 'menus'
        ordering = ['menu_order_no']




class Settings(models.Model):
    class_field = models.CharField(db_column='class', max_length=255)  # Field renamed because it was a Python reserved word.
    key = models.CharField(max_length=255)
    value = models.TextField(blank=True, null=True)
    type = models.CharField(max_length=31)
    context = models.CharField(max_length=255, blank=True, null=True)
    created_at = models.DateTimeField()
    updated_at = models.DateTimeField()

    class Meta:
        db_table = 'settings'


class State(models.Model):
    name = models.CharField(max_length=30)
    country = models.ForeignKey(Countries, on_delete=models.SET_NULL, null=True, blank=True)

    class Meta:
        db_table = 'states'
    
    def __str__(self):
        return self.name or ""


class SystemEmailNotification(models.Model):
    notification_type = models.CharField(unique=True, max_length=23)
    emails = models.TextField()
    created_at = models.DateTimeField(blank=True, null=True)
    updated_at = models.DateTimeField(blank=True, null=True)

    class Meta:
        db_table = 'system_email_notification'


class CustomUserManager(BaseUserManager):
    def create_user(self, email, password=None, **extra_fields):
        if not email:
            raise ValueError('The Email field is required')
        email = self.normalize_email(email)
        user = self.model(email=email, **extra_fields)
        user.set_password(password)  # Handles hashing
        user.save(using=self._db)
        return user

    def create_superuser(self, email, password=None, **extra_fields):
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)
        return self.create_user(email, password, **extra_fields)

class User(AbstractBaseUser, PermissionsMixin):
    STATUS_CHOICE = (
        ('active', 'Active'),
        ('inactive', 'Inactive'),
    )
    email = models.EmailField(unique=True)
    username = models.CharField(max_length=30, blank=True, null=True)
    contact_no = models.CharField(max_length=15, blank=True, null=True)
    designation = models.CharField(max_length=255, blank=True, null=True)
    status = models.CharField(max_length=25,choices=STATUS_CHOICE, blank=True, null=True, default='active')

    password = models.CharField(max_length=255,blank=True, null=True)
    last_login = models.DateTimeField(blank=True, null=True)

    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)
    is_superuser = models.BooleanField(default=False)
    first_login = models.BooleanField(default=True)
    # is_default = models.BooleanField(default=False)

    created_by = models.ForeignKey("self", on_delete=models.SET_NULL, blank=True, null=True, related_name="user_created", db_column="created_by")
    created_at = models.DateTimeField(auto_now_add=True, blank=True, null=True)
    updated_by = models.ForeignKey("self", on_delete=models.SET_NULL, blank=True, null=True, related_name="user_updated", db_column="updated_by")
    updated_at = models.DateTimeField(auto_now=True, blank=True, null=True)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['username']

    objects = CustomUserManager()

    class Meta:
        db_table = 'users'

    def __str__(self):
        return self.username or ""
    
    def save(self, *args, **kwargs):
        # Ensure status and is_active are always in sync
        if self.status == 'active':
            self.is_active = True
        elif self.status == 'inactive':
            self.is_active = False
        else:
            # If no status given → set default active
            self.status = 'active'
            self.is_active = True

        super().save(*args, **kwargs)


class UserPermissions(models.Model):
    ref_user = models.ForeignKey(User, on_delete=models.CASCADE, db_column='ref_user_id', related_name='menu_perms', blank=True, null=True)
    ref_menu = models.ForeignKey(Menu, on_delete=models.SET_NULL, db_column='ref_menu_id', related_name='user_perms', blank=True, null=True)

    can_view   = models.BooleanField(default=False)
    can_add    = models.BooleanField(default=False)
    can_edit   = models.BooleanField(default=False)
    can_delete = models.BooleanField(default=False)
    can_export = models.BooleanField(default=False)

    class Meta:
        db_table = 'users_permissions'
        unique_together = ('ref_user', 'ref_menu')

    def __str__(self):
        return f"{self.ref_user.username} - {self.ref_menu.menu_name}"

    

class EmailSetup(models.Model):
    REPORT_TYPES = [
        ("Visa Expiry", "Visa Expiry"),
        ("Passport Expiry", "Passport Expiry"),
        ("Travel Insurance Expiry", "Travel Insurance Expiry"),
        ("Birthday Report", "Birthday Report"),
        ("Anniversary Report", "Anniversary Report"),
        ("Client Report", "Client Report"),
    ]

    report_type = models.CharField(max_length=50, choices=REPORT_TYPES, blank=True, null=True)
    email = models.EmailField(blank=True, null=True)

    def __str__(self):
        return self.get_report_type_display()


# class ReportEmail(models.Model):
#     setup = models.ForeignKey(EmailSetup, related_name="emails", on_delete=models.CASCADE, blank=True, null=True)
#     email = models.EmailField(blank=True, null=True)

#     def __str__(self):
#         return self.email

