from django.contrib.auth.models import AbstractUser
from django.db import models
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _


from django.contrib.auth.models import BaseUserManager


class CustomUserManager(BaseUserManager):
    def create_user(self, username, password=None, **extra_fields):
        if not username:
            raise ValueError('The Username field must be set')
        user = self.model(username=username, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, username, password=None, **extra_fields):
        # Set default values for staff and superuser flags
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)
        
        # Do not require email for superuser
        extra_fields.setdefault('email', '')  # Can also be set to None if you prefer
        extra_fields.setdefault('access_level' , 'Administrator')
        # Call the method that creates a normal user
        return self.create_user(username, password, **extra_fields)




class AccessLevel:
    ADMINISTRATOR = 'Administrator'
    SUPERVISOR = 'Supervisor'
    ACCOUNTANT = 'Accountant'
    TECHNICIAN = 'Technician'
    STORE = 'Store'
    SECRETARY = 'Secretary'
    DOCTOR = 'Doctor'
    LEADER = 'Leader'

    CHOICES = (
        (ADMINISTRATOR, _('Administrator')),
        (SUPERVISOR, _('Supervisor')),
        (ACCOUNTANT, _('Accountant')),
        (TECHNICIAN, _('Technician')),
        (DOCTOR, _('Doctor')),
        (LEADER, _('Leader')),
        (STORE, _('Store')),
        (SECRETARY, _('Secretary')),
    )
from django.core.validators import RegexValidator
phone_regex = RegexValidator(
    regex=r'^\d{1,15}$',
    message=""
)
class User(AbstractUser):
    first_name = models.CharField(
        _('first name'),
        max_length=150,
        blank=False
    )
    last_name = models.CharField(
        _('last name'),
        max_length=150,
        blank=False
    )

    username = models.CharField(
        _('username'),
        max_length=150,
        unique=True,
        help_text=_(
            'Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.'),
        validators=[AbstractUser.username_validator],
        error_messages={
            'unique': _("A user with that username already exists."),
        },
        # Allow blank input in the admin form; it will be auto-generated later.
        blank=True
    )
    phone_number = models.CharField(
        max_length=15,  # Adjust length as necessary
        null=True,
        blank=True,
        validators=[RegexValidator(regex=r'^\v1,15}$', message="Phone number must contain only numeric characters and between 1 to 15 digits.")]
    )
    country_code = models.CharField(max_length=100,  blank=True)
    email = models.EmailField(_('email address'), null=True, blank=True)
    access_level = models.CharField(
        _('access level'),
        max_length=50,
        choices=AccessLevel.CHOICES,
        default=AccessLevel.SUPERVISOR
    )

    USERNAME_FIELD = 'username'
    REQUIRED_FIELDS = ['first_name', 'last_name']

    objects = CustomUserManager()

    # Add custom related_name to avoid reverse accessor clash
    groups = models.ManyToManyField(
        'auth.Group',
        related_name='custom_user_groups',  # Change the related_name to avoid conflict
        blank=True
    )
    user_permissions = models.ManyToManyField(
        'auth.Permission',
        related_name='custom_user_permissions',  # Change the related_name to avoid conflict
        blank=True
    )

    class Meta:
        verbose_name = _('user')
        verbose_name_plural = _('users')

    def __str__(self):
        return f'{self.get_full_name()} ({self.username}) - {self.get_access_level_display()}'

    def clean(self):
        super().clean()
        if not self.username and self.first_name and self.last_name:
            self.username = f"{self.first_name.lower()}-{self.last_name.lower()}"
        elif not self.username:
            raise ValidationError(_('Username is required if first and last name are missing.'))

    def save(self, *args, **kwargs):
        # Automatically set username based on first and last name if blank
        if not self.username and self.first_name and self.last_name:
            self.username = f"{self.first_name.lower()}-{self.last_name.lower()}"

        # Automatically adjust staff and superuser status based on access level
        if self.access_level == AccessLevel.ADMINISTRATOR:
            self.is_staff = True
            self.is_superuser = True
        else:
            self.is_staff = False

        super(User, self).save(*args, **kwargs)

    def get_full_name(self):
        return f'{self.first_name} {self.last_name}'.strip()

    def get_access_level_display(self):
        # Mimic TextChoices functionality for display
        return dict(AccessLevel.CHOICES).get(self.access_level, self.access_level)

from django.contrib.auth import get_user_model
User = get_user_model()

from django.utils import timezone
from datetime import timedelta

class PasswordResetCode(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    code = models.CharField(max_length=6)
    created_at = models.DateTimeField(auto_now_add=True)
    is_used = models.BooleanField(default=False)

    def is_valid(self):
        # کد به مدت 15 دقیقه معتبر است
        return not self.is_used and (timezone.now() - self.created_at) < timedelta(minutes=15)

    def __str__(self):
        return f"Reset code for {self.user.username}"

    class Meta:
        ordering = ['-created_at']
class VerificationCode(models.Model):

    code = models.IntegerField(null=False,blank=False)
    modified_at = models.DateTimeField(auto_now=True)
    modified_by = models.ForeignKey(
        User,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name="Modified By"
    )

    def __str__(self):
        return f"{self.id()}"

    class Meta:
        ordering = ['id']

class MessageTemplate(models.Model):
    MESSAGE_TYPE_CHOICES = [
        ('patient_created', 'Patient Created'),
        ('doctor_created', 'Doctor Created'),
        ('Technician_created', 'Technician Created'),
        ('reservation_created', 'Reservation Created'),
        ('reservation_rejected_doctor', 'rejected service to Doctor'),
        ('reservation_rejected_technician', 'rejected service to Technician'),
        ('reservation_assigned_doctor', 'Assigned service to Doctor'),
        ('reservation_assigned_technician', 'Assigned service to Technician'),
        ('reservation_completed_service', 'Completed patient service'),
        ('reservation_payed_service', 'Payed patient service'),
        ('reservation_canceled_service', 'Canceled patient service'),

        ('patient_add_user', 'Add Patient'),
        ('doctor_add_user', 'Add Doctor'),
        ('technician_add_user', 'Add Technician'),

        ('patient_wallet', 'Change Patient Wallet'),
        ('patient_add_wallet', 'Add Patient Wallet'),
        ('doctor_add_wallet', 'Add Doctor Wallet'),
        ('technician_add_wallet', 'Add Technician Wallet'),
        ('doctor_wallet', 'Change Doctor Wallet'),
        ('technician_wallet', 'Change Technician Wallet'),


        ('patient_no_complete_service_before_2_day', 'Send message before 2 day for patient service'),
        ('patient_complete_service_after_1_month', 'Send message after 1 month for completed patient service'),
        ('patient_birth_date', 'Patient birth date'),
        ('daily_report', 'Send daily report'),
        ('monthly_report', 'Send monthly report'),
        ('patient_without_service_holidays', 'Patient without service in holidays'),


        ('patient_complete_service_after_6_month', 'Send message after 6 month for completed patient service'),
        ('patient_without_service', 'Patient without service'),
        ('patient_with_service', 'Patient with service'),
        ('patient_with_service_holidays', 'Patient with service in holidays'),
    ]

    message_type = models.CharField(
        max_length=50,
        choices=MESSAGE_TYPE_CHOICES,
        unique=True,
        verbose_name="Message Type"
    )
    service_name = models.CharField(max_length=30, blank=True, null=True)
    service_id = models.IntegerField(blank=True, null=True)

    content = models.TextField(verbose_name="Message Content")
    created_at = models.DateTimeField(auto_now_add=True)
    modified_at = models.DateTimeField(auto_now=True)
    modified_by = models.ForeignKey(
        User,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name="Modified By"
    )

    def __str__(self):
        return f"{self.get_message_type_display()}"

    class Meta:
        verbose_name = "Message Template"
        verbose_name_plural = "Message Templates"
        ordering = ['id']


class MessageWhatsappTemplate(models.Model):
    MESSAGE_TYPE_CHOICES = [
        ('reservation_created', 'Reservation Created'),
        ('reservation_rejected_doctor', 'rejected service to Doctor'),
        ('reservation_rejected_technician', 'rejected service to Technician'),
        ('reservation_assigned_doctor', 'Assigned service to Doctor'),
        ('reservation_assigned_technician', 'Assigned service to Technician'),
        ('reservation_completed_service', 'Completed patient service'),
        ('reservation_payed_service', 'Payed patient service'),
        ('reservation_canceled_service', 'Canceled patient service'),

        ('patient_wallet', 'Change Patient Wallet'),
        ('doctor_wallet', 'Change Doctor Wallet'),
        ('technician_wallet', 'Change Technician Wallet'),


        ('patient_no_complete_service_before_2_day', 'Send message before 2 day for patient service'),
        ('patient_complete_service_after_1_month', 'Send message after 1 month for completed patient service'),
        ('patient_birth_date', 'Patient birth date'),
        ('daily_report', 'Send daily report'),
        ('monthly_report', 'Send monthly report'),
        ('patient_without_service_holidays', 'Patient without service in holidays'),


        ('patient_complete_service_after_6_month', 'Send message after 6 month for completed patient service'),
        ('patient_without_service', 'Patient without service'),
        ('patient_with_service', 'Patient with service'),
        ('patient_with_service_holidays', 'Patient with service in holidays'),
    ]

    message_type = models.CharField(
        max_length=50,
        choices=MESSAGE_TYPE_CHOICES,
        verbose_name="Message Type"
    )
    service_name = models.CharField(max_length=30, blank=True, null=True)
    service_id = models.IntegerField(blank=True, null=True)

    content = models.TextField(verbose_name="Message Content")
    created_at = models.DateTimeField(auto_now_add=True)
    modified_at = models.DateTimeField(auto_now=True)
    modified_by = models.ForeignKey(
        User,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name="Modified By"
    )

    def __str__(self):
        return f"{self.get_message_type_display()}"

    class Meta:
        verbose_name = "Message Template"
        verbose_name_plural = "Message Templates"
        ordering = ['id']
