from django.db import models
from django.core.exceptions import ValidationError
from datetime import datetime, time, date
from django.utils import timezone
from django.conf import settings
from django.contrib.auth import get_user_model
from django.utils.translation import gettext_lazy as _
from django.contrib.auth.models import User


class Currency(models.Model):
    class Meta:
        verbose_name = 'Currency'
        verbose_name_plural = 'Currency'
    name = models.CharField(max_length=50)
    code = models.CharField(max_length=50)
    symbol = models.CharField(max_length=50)

    def __str__(self):
        return self.code


class Department(models.Model):
    class Meta:
        verbose_name = 'Department'
        verbose_name_plural = 'Departments'
    name = models.CharField(max_length=100)
    description = models.TextField(blank=True, null=True)

    def __str__(self):
        return self.name


class Position(models.Model):
    name = models.CharField(max_length=100)
    department = models.ForeignKey(
        Department, on_delete=models.CASCADE)
    description = models.TextField(
        blank=True, null=True)

    def validate_unique(self, exclude=None):
        qs = Position.objects.filter(
            name=self.name, department=self.department)
        if self.pk:
            qs = qs.exclude(pk=self.pk)
        if qs.exists():
            raise ValidationError(
                'Position with this name already exists in this department.')

    class Meta:
        unique_together = ('name', 'department')

    def __str__(self):
        return self.name

    def get_department_name(self):
        return self.department.name

    # optional, set a custom column header
    get_department_name.short_description = 'Department'


class SalaryScale(models.Model):
    name = models.CharField(max_length=50)
    basic_pay = models.DecimalField(
        max_digits=10, decimal_places=2)
    travel_allowance = models.DecimalField(
        max_digits=10, decimal_places=2)
    food_allowance = models.DecimalField(
        max_digits=10, decimal_places=2)
    individual_allowance = models.DecimalField(
        max_digits=10, decimal_places=2)
    currency = models.ForeignKey(
        Currency, on_delete=models.CASCADE)
    description = models.TextField(blank=True, null=True)

    class Meta:
        verbose_name = 'Salary scale'
        verbose_name_plural = 'Salary scales'

    def total_salary(self):
        return (self.basic_pay + self.travel_allowance + self.food_allowance + self.individual_allowance)

    def __str__(self):
        return self.name


class LeaveType(models.Model):
    class Meta:
        verbose_name = 'Leave Type'
        verbose_name_plural = 'Leave Types'
    name = models.CharField(max_length=50)
    description = models.TextField(blank=True, null=True)

    def __str__(self):
        return self.name


class WorkingShift(models.Model):

    name = models.CharField(max_length=50)
    start_time = models.TimeField()
    end_time = models.TimeField()
    description = models.TextField(blank=True, null=True)

    @property
    def working_hours(self):
        tdelta = datetime.combine(
            date.today(), self.end_time) - datetime.combine(date.today(), self.start_time)
        return tdelta.total_seconds() / 3600

    class Meta:
        verbose_name = 'Working Shift'
        verbose_name_plural = 'Working Shifts'

    def __str__(self):
        return self.name


def validate_date_of_birth(value):
    if value > timezone.now().date():
        raise ValidationError('Date cannot be in the future!')


class Employee(models.Model):
    GENDER_CHOICES = [
        ('M', 'Male'),
        ('F', 'Female'),
        ('O', 'Other')
    ]

    MATERIAL_STATUS_CHOICES = [
        ('S', 'Single'),
        ('M', 'Married'),
        ('W', 'Widowed'),
        ('D', 'Divorced')
    ]
    NATIONALITY = [
        ('AFG', 'Afghan'),
        ('PAK', 'Pakstani'),
        ('IR', 'Iranian'),
        ('US', 'American'),
        ('CA', 'Canadian'),
        ('O', 'Other')
    ]

    name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    father_name = models.CharField(
        max_length=50, blank=True, null=True)
    gender = models.CharField(
        max_length=1, choices=GENDER_CHOICES)
    national_id = models.CharField(max_length=20)
    nationality = models.CharField(
        max_length=3, choices=NATIONALITY)
    current_address = models.CharField(
        max_length=200)
    referred_by = models.CharField(max_length=100)
    referred_by_phone = models.CharField(
        max_length=20)
    relation_with = models.CharField(
        max_length=50)
    material_status = models.CharField(
        max_length=1, choices=MATERIAL_STATUS_CHOICES)
    date_of_birth = models.DateField(
        validators=[validate_date_of_birth])
    email = models.EmailField(blank=True, null=True)
    primary_phone = models.CharField(
        max_length=20)
    emergency_phone = models.CharField(
        max_length=20)
    biometric_id = models.CharField(
        max_length=100, blank=True, null=True)
    image = models.ImageField(upload_to='hr/images',
                              blank=True, null=True)

    class Meta:
        verbose_name = 'Employee'
        verbose_name_plural = 'Employees'

    def __str__(self):
        return f"{self.id} - {self.name} {self.last_name}"


class Education(models.Model):
    DEGREE_CHOICES = (
        ('DP', 'Diplom'),
        ('B', 'Bachelor'),
        ('M', 'Master'),
        ('D', 'Doctorate')
    )
    employee = models.ForeignKey(
        Employee, on_delete=models.CASCADE)
    degree_type = models.CharField(
        max_length=10, choices=DEGREE_CHOICES)
    institution = models.CharField(max_length=100)
    field_of_study = models.CharField(max_length=100)
    start_year = models.PositiveIntegerField()
    end_year = models.PositiveIntegerField(
        blank=True, null=True)
    grade_point_average = models.FloatField(
        blank=True, null=True)

    class Meta:
        verbose_name = 'Education'
        verbose_name_plural = 'Educations'

    def __str__(self):
        return f"{self.degree_type} in {self.field_of_study} from {self.institution} ({self.employee})"


class Attachment(models.Model):
    name = models.CharField(max_length=191, default='-')
    employee = models.ForeignKey(
        Employee, on_delete=models.CASCADE)
    file = models.FileField(upload_to='hr/attachment')
    uploaded_by = models.ForeignKey(
        User, on_delete=models.SET_NULL, null=True, blank=True)
    uploaded_at = models.DateTimeField(
        default=timezone.now)

    class Meta:
        verbose_name = 'Document'
        verbose_name_plural = 'Documents'

    def __str__(self):
        return self.file.name


class Employment(models.Model):
    employee = models.ForeignKey(
        Employee, on_delete=models.CASCADE)
    department = models.ForeignKey(
        Department, on_delete=models.CASCADE)
    position = models.ForeignKey(
        Position, on_delete=models.CASCADE)
    salary_scale = models.ForeignKey(
        SalaryScale, on_delete=models.CASCADE)
    working_shift = models.ForeignKey(
        WorkingShift, on_delete=models.CASCADE)
    tin_number = models.CharField(max_length=191)
    join_date = models.DateField()
    contract_duration = models.IntegerField(help_text=_('In Months!'))
    experience = models.IntegerField(help_text=_('In Years!'))
    working_days = models.PositiveIntegerField(default=5)
    skills = models.TextField(null=True, blank=True)

    class Meta:
        verbose_name = 'Employment'
        verbose_name_plural = 'Employments'
        ordering = ['-join_date']
        unique_together = [
            ('employee', 'department', 'position', 'salary_scale', 'join_date')]

    def __str__(self):
        return f'{self.employee} - {self.position}'
