from django.db import models
from apps.system.models import Post, User

from apps.utils.models import BaseModel, CommonADModel, CommonAModel, CommonBModel
from django.utils import timezone
from datetime import timedelta
from django.core.validators import RegexValidator

PHONE_VALIDATOR = RegexValidator(r'^1[3456789]\d{9}$', '手机号码格式不正确')
class Employee(CommonBModel):
    """
    TN:员工信息
    """
    JOB_ON = 10
    JOB_OFF = 20
    JOB_RETIRE = 30
    jobstate_choices = (
        (JOB_ON, '在职'),
        (JOB_OFF, '离职'),
        (JOB_RETIRE, '退休')
    )
    PEOPLE_TYPE_CHOICES = (
        ('employee', '内部员工'),
        ('remployee', '相关方人员'),
        ('visitor', '访客'),
        ('driver', '司机')
    )
    
    user = models.OneToOneField(User,
                                verbose_name='系统账号',
                                related_name='employee',
                                on_delete=models.SET_NULL, null=True, blank=True)
    name = models.CharField('姓名', max_length=20)
    phone = models.CharField('手机号', max_length=11, null=True, blank=True)
    email = models.EmailField('邮箱号', null=True, blank=True)
    number = models.CharField('人员编号', max_length=50, null=True, blank=True)
    photo = models.CharField('证件照', max_length=1000, null=True, blank=True)
    signature = models.CharField('签名图片', max_length=200, null=True, blank=True)
    
    qualification = models.CharField(
        '学历', max_length=50, null=True, blank=True)
    job_state = models.IntegerField(
        '在职状态', choices=jobstate_choices, default=10)
    is_atwork = models.BooleanField('当前在岗', default=False)
    show_atwork = models.BooleanField('是否展示在岗状态', default=True)
    last_check_time = models.DateTimeField('打卡时间', null=True, blank=True)
    not_work_remark = models.CharField(
        '当前未打卡说明', null=True, blank=True, max_length=200)
    third_info = models.JSONField(
        '三方信息', default=dict, null=False, blank=True)  # 主要是定位卡信息
    post = models.ForeignKey(Post, verbose_name='所属岗位',
                             on_delete=models.SET_NULL, null=True, blank=True)
    face_data = models.JSONField(
        '人脸数据', null=True, blank=True)  # 存储的是字典(模型名:人脸数据)
    end_date = models.DateField('离职日期', null=True, blank=True)
    workshop = models.CharField('车间', max_length=20, null=True, blank=True)
    position = models.CharField('职务', max_length=20, null=True, blank=True)
    office_date = models.DateField('职务聘任日期', null=True, blank=True)
    type = models.CharField('人员类型', default='employee',
                            max_length=10, choices=PEOPLE_TYPE_CHOICES)
    gender = models.CharField('性别', max_length=10, default='男')
    id_number = models.CharField(
        '身份证号', max_length=100, null=True, blank=True, unique=True)
    bank_card = models.CharField('银行卡号', max_length=30, null=True, blank=True)
    start_date = models.DateField('入职日期', null=True, blank=True)
    contract_end_date = models.DateField('合同到期日', null=True, blank=True)
    regular_date = models.DateField('转正日期', null=True, blank=True)
    birthday = models.DateField('出生年月日', null=True, blank=True)
    age = models.PositiveIntegerField('年龄', null=True, blank=True)
    work_years = models.PositiveIntegerField('工龄', null=True, blank=True)
    partisan = models.CharField('政治面貌', max_length=20, null=True, blank=True)
    join_partisan_date = models.DateField('入党时间', null=True, blank=True)
    nation = models.CharField('民族', max_length=20, null=True, blank=True)
    marriage = models.CharField('婚姻状况', max_length=5, null=True, blank=True)
    hukou_type = models.CharField('户口性质', max_length=20, null=True, blank=True)
    birthplace = models.CharField('籍贯', max_length=40, null=True, blank=True)
    hukou_address = models.CharField('户籍地址', max_length=100, null=True, blank=True)
    address = models.CharField('现住地址', max_length=100, null=True, blank=True)
    zhuanzhi = models.CharField('枣庄市职称', max_length=50, null=True, blank=True)
    zhuanzhi_img_1 = models.CharField('职称证书图片1', max_length=100, null=True, blank=True)
    zhuanzhi_img_2 = models.CharField('职称证书图片2', max_length=100, null=True, blank=True)
    zhuanzhi_date = models.DateField('获得枣庄市职称日期', null=True, blank=True)
    zyjt_zhuanzhi = models.CharField('总院/集团职称', max_length=50, null=True, blank=True)
    zyjt_zhuanzhi_img_1 = models.CharField('总院/集团职称证书图片1', max_length=100, null=True, blank=True)
    zyjt_zhuanzhi_date = models.DateField('获得职称日期', null=True, blank=True)
    skill_rank = models.CharField('职业技能等级', max_length=50, null=True, blank=True)
    skill_rank_date = models.DateField('获得技能等级证书日期', null=True, blank=True)
    full_edu = models.CharField('全日制最高学历', max_length=50, null=True, blank=True)
    full_edu_school = models.CharField('全日制最高学历学校名称', max_length=100, null=True, blank=True)
    full_edu_major = models.CharField('全日制最高学历专业', max_length=100, null=True, blank=True)
    full_edu_time = models.CharField('全日制最高学历毕业时间', max_length=50, null=True, blank=True)
    part_edu = models.CharField('非全日制最高学历', max_length=50, null=True, blank=True)
    part_edu_school = models.CharField('非全日制最高学历学校名称', max_length=100, null=True, blank=True)
    part_edu_major = models.CharField('非全日制最高学历专业', max_length=100, null=True, blank=True)
    part_edu_time = models.CharField('非全日制最高学历毕业时间', max_length=50, null=True, blank=True)
    emergency_contact = models.CharField('紧急联系人姓名', max_length=20, null=True, blank=True)
    emergency_phone = models.CharField('紧急联系人电话', max_length=20, null=True, blank=True)
    honor = models.TextField('所获荣誉', null=True, blank=True)
    first_social_security_date = models.DateField('首次缴纳社保日期', null=True, blank=True)
    is_veteran = models.BooleanField('是否为退役军人', default=False)

    class Meta:
        verbose_name = '员工补充信息'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name

    def save(self, *args, **kwargs) -> None:
        return super().save(*args, **kwargs)


# class Card(CommonAModel):
#     """
#     卡
#     """
#     CARD_FACE = 10
#     CARD_LOCATION = 20


class NotWorkRemark(CommonADModel):
    """
    TN:离岗说明
    """
    not_work_date = models.DateField('未打卡日期')
    user = models.ForeignKey(User, verbose_name='用户', on_delete=models.CASCADE)
    remark = models.CharField('未打卡说明', null=True, blank=True, max_length=200)


class Attendance(CommonADModel):
    """
    TN:到岗记录
    """
    ATT_STATE_CHOICES = [
        ('pending', '待定'),
        ('normal', '正常'),
        ('late', '迟到'),
        ('early_leave', '早退'),
        ('absent', '未到岗'),
        ('leave', '请假'),
        # 可以根据需要添加更多状态
    ]

    user = models.ForeignKey(
        User, verbose_name='关联人员', on_delete=models.CASCADE)
    work_date = models.DateField('工作日期')
    shift = models.ForeignKey(
        'mtm.shift', verbose_name='班次', on_delete=models.CASCADE)
    team = models.ForeignKey('mtm.team', verbose_name='班组',
                             on_delete=models.SET_NULL, null=True, blank=True)
    post = models.ForeignKey('system.post', verbose_name='岗位',
                             on_delete=models.SET_NULL, null=True, blank=True)
    work_time_start = models.DateTimeField('工作开始时间')
    work_time_end = models.DateTimeField('工作结束时间')
    state = models.CharField('状态', max_length=20,
                             choices=ATT_STATE_CHOICES, default='pending', help_text=str(ATT_STATE_CHOICES))
    note = models.TextField('备注信息', default='', blank=True)

    # class Meta:
    #     unique_together = ('user', 'work_date', 'shift')


class ClockRecord(BaseModel):
    """
    TN:打卡记录
    """
    ClOCK_ON = 10
    CLOCK_OFF = 20
    CLOCK_ING = 30
    type_choice = (
        (ClOCK_ON, '上班打卡'),
        (CLOCK_OFF, '下班打卡'),
        (CLOCK_ING, '忽略'),  # 尽量不用
    )
    E_TYPE_LESS = 10
    E_TYPE_MORE = 20
    E_TYPE_MISS = 30
    E_TYPE_ADD = 40
    E_TYPE_CHOISE = (
        (E_TYPE_LESS, '在岗时间短'),
        (E_TYPE_MORE, '在岗时间长'),
        (E_TYPE_MISS, '缺卡'),
        (E_TYPE_ADD, '加班')
    )
    type = models.PositiveSmallIntegerField(
        '打卡类型', choices=type_choice, default=ClOCK_ON)
    employee = models.ForeignKey(
        Employee, verbose_name='对应人员', on_delete=models.CASCADE)
    clock_time = models.DateTimeField('打卡时间', null=True, blank=True)
    # panel, location, door, manual
    trigger = models.CharField('触发', max_length=20)
    detail = models.JSONField('相关记录', default=dict,
                              null=False, blank=True)  # 里面主要有对应的ID值
    exception_type = models.PositiveSmallIntegerField(
        '异常类型', choices=E_TYPE_CHOISE, null=True, blank=True)
    note = models.CharField('备注', max_length=20, default='')
    attendance = models.ForeignKey(
        Attendance, on_delete=models.SET_NULL, verbose_name='关联到岗记录', null=True, blank=True)


class Certificate(CommonAModel):
    """
    TN:证书
    """
    CERT_OK = 10
    CERT_EXPIRING = 20
    CERT_EXPIRED = 30
    
    CERTIFICATE_TYPE_CHOICES = (
        (10, '特种作业证书'),
        (20, '特种设备操作证书'),
        (30, '安全管理人员证书')
    )
    employee = models.ForeignKey(
        Employee, verbose_name='对应人员', on_delete=models.CASCADE)
    name = models.CharField('证书名称', max_length=20)
    number = models.CharField('证书编号', max_length=20)
    type = models.PositiveSmallIntegerField('证书类型', default=10)
    issue_date = models.DateField('发证日期')
    expiration_date = models.DateField('有效期')
    state = models.PositiveSmallIntegerField('证书状态', default=CERT_OK, choices=((CERT_OK, '有效'), (CERT_EXPIRING, '即将过期'), (CERT_EXPIRED, '已过期')))
    review_date = models.DateField('下一次复审日期')
    file = models.TextField('文件地址', null=True, blank=True)

    def get_state(self, need_update=False):
        now = timezone.now().date()
        new_state = self.CERT_EXPIRED
        if  self.expiration_date - timedelta(days=30)  <= now < self.expiration_date:
            new_state = self.CERT_EXPIRING
        elif now < self.expiration_date - timedelta(days=30):
            new_state = self.CERT_OK
        if need_update and new_state != self.state:
            self.state = new_state
            self.save(update_fields=['state'])
        return new_state
    

class Resignation(CommonADModel):
    """
    TN:离职记录
    """
    employee = models.ForeignKey(Employee, verbose_name='员工', on_delete=models.CASCADE)
    end_date = models.DateField('离职日期')
    reason = models.TextField('离职原因')
    handle_date = models.DateField('办理离职交接日期', null=True, blank=True)
    ticket = models.ForeignKey('wf.ticket', verbose_name='关联工单', on_delete=models.SET_NULL, null=True, blank=True, related_name='resignation_ticket')


class EmpNeed(CommonADModel):
    """
    TN:员工需求
    """
    dept_need = models.ForeignKey('system.Dept', verbose_name='需求部门', on_delete=models.CASCADE)
    post_need = models.TextField("需求岗位")
    count_need = models.PositiveIntegerField('需求人数')
    salary = models.PositiveIntegerField("工资报酬")
    arrival_date = models.DateField('到岗日期')
    reason = models.TextField('申请理由', help_text="新增人员/该岗原人员离职或辞职或辞退需补充/其他原因")
    duty = models.TextField("岗位人员职责描述")
    gender = models.CharField('性别要求', max_length=10, help_text="男/女/不限")
    education = models.CharField('学历要求', max_length=50, help_text='高中/大专/不限')
    professional_requirement = models.TextField(verbose_name="相关专业及技能要求", null=True, blank=True)
    ticket = models.OneToOneField('wf.ticket', verbose_name='关联工单', 
        on_delete=models.CASCADE, related_name='empneed_ticket', null=True, blank=True)


class EmpJoin(CommonADModel):
    """
    TN:员工入职
    """
    dept_need = models.ForeignKey('system.Dept', verbose_name='入职部门', on_delete=models.CASCADE)
    ticket = models.OneToOneField('wf.ticket', verbose_name='关联工单', 
        on_delete=models.CASCADE, related_name='empjoin_ticket', null=True, blank=True)
    person = models.JSONField('人员信息', default=list)
    join_date = models.DateField('入职日期')


class EmpPersonInfo(CommonADModel):
    """
    TN:入职人员信息
    """
    name = models.CharField('姓名', max_length=20)
    gender = models.CharField('性别', max_length=10, default='男')
    IDcard = models.CharField('身份证号', max_length=20)
    phone = models.CharField('手机号', max_length=20,validators=[PHONE_VALIDATOR], null=True, blank=True)
    post = models.CharField('岗位', max_length=20, null=True, blank=True)
    note = models.TextField('备注', null=True, blank=True)


class Leave(CommonADModel):
    """
    TN:员工请假
    """
    E_TYPE_CHOISE = (
        (10, '事假'),
        (20, '病假'),
        (30, '婚假'),
        (40, '丧假'),
        (50, '公假'),
        (60, '工伤'),
        (70, '产假'),
        (80, '护理假'),
        (90, '其他'),
    )
    employee = models.ForeignKey(Employee, verbose_name='员工', on_delete=models.CASCADE)
    start_date = models.DateTimeField('开始日期')
    end_date = models.DateTimeField('结束日期')
    leave_type = models.PositiveSmallIntegerField('请假类型', choices=E_TYPE_CHOISE, default=10)
    reason = models.TextField('请假事由')
    hour = models.PositiveSmallIntegerField('请假时长', null=True, blank=True)
    file = models.TextField('证明', null=True, blank=True)
    ticket = models.OneToOneField('wf.ticket', verbose_name='关联工单', 
        on_delete=models.CASCADE, related_name='leave_ticket', null=True, blank=True)
    

class EmployeeTransfer(CommonADModel):
    """
    TN:员工岗位调动
    """
    employee = models.ForeignKey(Employee, verbose_name='员工', on_delete=models.CASCADE)
    is_change = models.BooleanField('是否跨部门调动', default=False)
    is_promotion = models.BooleanField('是否晋升', default=False)
    new_dept = models.ForeignKey('system.Dept', verbose_name='新部门', related_name="transfer_new_dept", on_delete=models.CASCADE, null=True, blank=True)
    new_post = models.ForeignKey('system.Post', verbose_name='新岗位', related_name="transfer_new_post", on_delete=models.CASCADE, null=True, blank=True)
    original_dept = models.ForeignKey('system.Dept', verbose_name='原部门', related_name="transfer_original_dept", on_delete=models.CASCADE, null=True, blank=True)
    original_post = models.ForeignKey('system.Post', verbose_name='原岗位', related_name="transfer_original_post", on_delete=models.CASCADE, null=True, blank=True)
    transfer_date = models.DateField('调岗日期')
    original_slary = models.DecimalField('原岗位薪资', max_digits=10, decimal_places=2, null=True, blank=True)
    new_slary = models.DecimalField('调岗后薪资', max_digits=10, decimal_places=2, null=True, blank=True)
    content = models.TextField('个人工作内容', null=True, blank=True)
    reason = models.TextField('调动原因', null=True, blank=True)
    ticket = models.OneToOneField('wf.ticket', verbose_name='关联工单', 
        on_delete=models.CASCADE, related_name='transfer_ticket', null=True, blank=True)
    

class Probation(CommonBModel):
    """
    TN:员工转正
    """
    empperson = models.OneToOneField(EmpPersonInfo, verbose_name='人员信息', on_delete=models.SET_NULL, null=True, blank=True)
    ticket = models.OneToOneField('wf.ticket', verbose_name='关联工单', 
        on_delete=models.CASCADE, related_name='probation_ticket', null=True, blank=True)
    reg_dept = models.ForeignKey('system.Dept', verbose_name='转正部门', on_delete=models.SET_NULL, null=True, blank=True)
    reg_post = models.ForeignKey('system.Post', verbose_name='转正岗位', on_delete=models.SET_NULL, null=True, blank=True)
    trial_date = models.DateField('试用日期')
    regular_date = models.DateField('转正日期')
    content = models.TextField('个人工作内容', null=True, blank=True)
    record_file = models.CharField('应聘人员登记表',  null=True, blank=True, max_length=100)
    apply_file = models.CharField('员工转正申请表',  null=True, blank=True, max_length=100)
    ppt_file = models.CharField('PPT 汇报考核', null=True, blank=True, max_length=100)


class EmpContract(CommonAModel):
    """
    TN:劳动合同
    """
    employee = models.ForeignKey(Employee, verbose_name='人员信息', on_delete=models.SET_NULL, null=True, blank=True)
    ticket = models.ForeignKey('wf.ticket', verbose_name='关联工单',
        on_delete=models.CASCADE, related_name='contract_ticket', null=True, blank=True)
    counts = models.PositiveSmallIntegerField('合同变更次数', default=0)
    plan_renewal = models.DateField('应续签', null=True, blank=True)
    normal_renewal = models.DateField('正常续签', null=True, blank=True)
    change_date = models.IntegerField('续签/变更(年)', null=True, blank=True)
    change_reason = models.TextField('缩短续签/变更年限原因', null=True, blank=True)

    
    