from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
from django.utils.translation import gettext_lazy as _
from django.utils import timezone
from django.urls import reverse
import uuid
from at_django_boilerplate.utils.encryption_utils import EncryptionUtils
# ✅ imports fixed according to your project structure
from at_django_boilerplate.utils.hash_utils import hexdigest
from at_django_boilerplate.utils.custom_fields import (
    EncryptedTextField,
    EncryptedSearchableTextField,
)
from at_django_boilerplate.utils.mixins import UUIDMixin

def user_directory_path(instance, filename):
    user_id = str(instance.id).zfill(10)
    return f'uploads/users/{user_id}/{filename}'

class CustomUserManager(BaseUserManager):
    def create_user(self, email=None, contact_number=None, password=None, **extra_fields):
        """
        Create and save a User with the given email and/or contact_number and password.
        At least one of email or contact_number must be provided.
        """
        if not email and not contact_number:
            raise ValueError("Either email or contact number must be provided.")

        if email:
            email = self.normalize_email(email)

        user = self.model(email=email, contact_number=contact_number, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email=None, contact_number=None, password=None, **extra_fields):
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)

        if extra_fields.get('is_staff') is not True:
            raise ValueError('Superuser must have is_staff=True.')
        if extra_fields.get('is_superuser') is not True:
            raise ValueError('Superuser must have is_superuser=True.')

        # Superuser usually needs at least one identifier
        if not email and not contact_number:
            raise ValueError('Superuser must have email or contact number.')

        return self.create_user(email, contact_number, password, **extra_fields)

    # Keep your existing search helpers unchanged
    def get_by_email(self, email):
        try:
            return self.get(email_hash=hexdigest(email))
        except CustomUser.DoesNotExist:
            return None

    def filter_by_email(self, email):
        return self.filter(email_hash=hexdigest(email))

    def get_by_contact_number(self, contact_number):
        try:
            return self.get(contact_number_hash=hexdigest(contact_number))
        except CustomUser.DoesNotExist:
            return None

    def filter_by_contact_number(self, contact_number):
        return self.filter(contact_number_hash=hexdigest(contact_number))

class CustomUser(AbstractBaseUser, PermissionsMixin,UUIDMixin):

    first_name = EncryptedTextField()
    last_name = EncryptedTextField()
    email = EncryptedSearchableTextField(hash_field='email_hash',null=True,      # ← Must be True
    blank=True)

    dob = models.DateField(_('Date Of Birth'), blank=True, null=True)

    contact_number = EncryptedSearchableTextField( hash_field='contact_number_hash',null=True, blank=True)
    profile_photo = models.ImageField(
        upload_to=user_directory_path,
        default='assets/default_profile.png',
        null=True,
        blank=True
    )

    is_staff = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    date_joined = models.DateTimeField(default=timezone.now)

    terms_accepted = models.BooleanField("Terms & Conditions", default=False)
    terms_accepted_time = models.DateTimeField(default=timezone.now)

    source = models.CharField(max_length=10, default='manual')

    last_active = models.DateTimeField(null=True,blank=True)


    is_technician = models.BooleanField(default=False)
    is_manager = models.BooleanField(default=False)




    objects = CustomUserManager()

    USERNAME_FIELD = 'id'
    REQUIRED_FIELDS = ['first_name', 'last_name']

    def __str__(self):
        return self.get_decrypted_name()

    @property
    def name(self):
        return self.get_decrypted_name()


    @property
    def is_admin(self):
        return self.is_superuser

    def get_absolute_url(self):
        return reverse("user_profile")

    def get_decrypted_first_name(self):
        return self.first_name or ''

    def get_decrypted_last_name(self):
        return self.last_name or ''

    def get_decrypted_name(self):
        return f"{self.get_decrypted_first_name()} {self.get_decrypted_last_name()}".strip()

    def get_decrypted_email(self):
        return self.email or ''

    def get_decrypted_contact_number(self):
        return self.contact_number or ''

    def set_contact_number(self, value):
        self.contact_number = value
        self.save()

    def set_first_name(self, value):
        self.first_name = value
        self.save()

    def set_last_name(self, value):
        self.last_name = value
        self.save()

    def set_name(self, value):
        names = value.strip().split(' ', 1)
        self.set_first_name(names[0])
        self.set_last_name(names[1] if len(names) > 1 else '')

    def has_contact_number(self):
        return bool(self.contact_number)


    def is_customer(self):
        try:
            return self.connection_account.all().count() >=1
        except Exception as e:
            print(e)
            return False

    def get_connection(self):
            return self.connection_account.all().first()

    def get_technician(self):
            return self.is_technician
    

    def get_manager(self):
        return self.is_manager
    # def ge