import time

from netforce.model import Model, fields, get_model
from netforce.access import get_active_company, get_active_user, set_active_user

class Staff(Model):
    _name="clinic.staff"
    _string="Staff"
    _audit_log=True
    _multi_company=True

    def _get_age(self,ids,context={}):
        res={}
        year_now=int(time.strftime("%Y"))
        for obj in self.browse(ids):
            age=0
            if obj.birthday:
                year_bd=int(obj.birthday[0:4])
                age=year_now-year_bd
            res[obj.id]=age
        return res
    
    def _get_cycle(self,ids,context={}):
        res={}
        for obj in self.browse(ids):
            cycle_id=None
            for line in obj.cycles:
                cycle=line.cycle_id
                cycle_id=cycle.id
            res[obj.id]=cycle_id
        return res
    
    def _get_rotation(self,ids,context={}):
        res={}
        for obj in self.browse(ids):
            wage=0
            max_cycle=0
            ot_per_cycle=0
            level_id=None
            categ_id=None
            for rotate in sorted(obj.rotations,key=lambda x: x.hire_date or ""):
                if rotate.state=='approved':
                    level_id=rotate.level_id.id
                    wage=rotate.wage
                    max_cycle=rotate.max_cycle
                    ot_per_cycle=rotate.ot_per_cycle or 0
                    categ_id=rotate.categ_id.id
            res[obj.id]={
                'wage': wage,
                'max_cycle': max_cycle,
                'ot_per_cycle': ot_per_cycle,
                'level_id': level_id,
                'categ_id': categ_id,
            }
        return res
    
    def _get_hdcase(self,ids,context={}):
        # problem slow to load
        res={}
        for obj in self.browse(ids):
            hids=[]
            if obj.type=='doctor':
                hids=get_model("clinic.hd.case.staff").search([['staff_id','=',obj.id]])
            elif obj.type=='nurse':
                item_ids=[item['cycle_item_id'][0] for item in get_model("clinic.cycle.item.line").search_read([['nurse_id','=',obj.id]],['cycle_item_id'])]
                for item in get_model("clinic.cycle.item").browse(item_ids):
                    for hdcase in item.hd_cases:
                        hids.append(hdcase.id)
            res[obj.id]=hids
        return res
    
    def _get_name(self,ids,context={}):
        res={}
        for obj in self.browse(ids):
            name=''
            title_name=''
            title=obj.title_id
            if title:
                title_name=title.name or ""
                title_name=title_name.replace(" ","")
                if title_name.lower()!='notitle':
                    name+=obj.title_id.name or ""
            if obj.first_name:
                name+=obj.first_name or ""
                name+=" "
            if obj.last_name:
                name+=obj.last_name or ""
            if not obj.active:
                name+='__'
            elif context.get('active'):
                name+='__'
            name_check=name.replace(" ","")
            name_check=name_check.replace(title_name,"")
            res[obj.id]={
                'name': name,
                'name_check': name_check, # remove all space for make sure
            }
        return res
    
    def _get_location(self,ids,context={}):
        res={}
        user_id=get_active_user()
        set_active_user(1)
        for obj in self.browse(ids):
            st_codes=set([d.code for d in obj.departments])
            res[obj.id]=",".join([dcode for dcode in sorted(st_codes)])
        set_active_user(user_id)
        return res

    def _get_department_names(self,ids,context={}):
        res={}
        user_id=get_active_user()
        set_active_user(1)
        for obj in self.browse(ids):
            dpt_st=set([dpt.name for dpt in obj.departments])
            res[obj.id]=','.join([dpt_name for dpt_name in sorted(dpt_st)])
        set_active_user(user_id)
        return res
    
    _fields={
        'employee_id': fields.Many2One("hr.employee","Employee"),
        "number": fields.Char("Number",required=True,search=True),
        "title_id": fields.Many2One("clinic.name.title","Title"),
        "first_name": fields.Char("First Name"),
        "last_name": fields.Char("Last Name"),
        "name": fields.Char("Name",function="_get_name",function_multi=True,store=True,required=True,search=True),
        "name_check": fields.Char("Name",function="_get_name",function_multi=True,store=True),
        "name_eng": fields.Char("Eng Name",search=True),
        "nick_name": fields.Char("Nick Name",search=True),
        "identification" : fields.Char("ID Card"),
        "expiry_card" : fields.Date("Expired Card"),
        "birthday": fields.Date("Birthday",search=True),
        "age": fields.Integer("Age", function="_get_age"),
        "state": fields.Selection([["part_time","Part Time"],["full_time","Full Time"]],"Working Status",search=True),
        "type": fields.Selection([['staff','Staff'],["doctor","Doctor"],["nurse","Nurse"]],"Type"),
        "gender": fields.Selection([["male","Male"],["female","Female"]],"Gender"),
        "nation_id": fields.Many2One("clinic.nation","Nationality"),
        "mobile": fields.Char("Mobile",required=False,search=True),
        "phone": fields.Char("Phone",search=True),
        'email': fields.Char("Email"),
        "prof_license" : fields.Char("License No."),
        "prof_license_date" : fields.Date("License Date"),
        "prof_license_expiry" : fields.Date("Expired License"),
        "birthday": fields.Date("BirthDay",search=True),
        "department_id": fields.Many2One("clinic.department", "Department",search=True),
        "addresses": fields.One2Many("address","staff_id","Addresses"),
        "comments": fields.One2Many("message","related_id","Comments"),
        "nurse_visits": fields.One2Many("clinic.visit","nurse_id","Visits"),
        "doctor_visits": fields.One2Many("clinic.visit","doctor_id","Visits"),
        "company_id": fields.Many2One("company","Company",search=True),
        "user_id": fields.Many2One("base.user","User",search=True),
        'image': fields.File("Image"),
        'note': fields.Text("Note"),
        'categ_id': fields.Many2One("clinic.staff.categ", "Category",function="_get_rotation",function_multi=True,store=True),
        'level_id': fields.Many2One("clinic.staff.level", "Level", function="_get_rotation",function_multi=True,store=True),
        'active': fields.Boolean("Active"),
        'date': fields.Date("Register Date"),
        'wage': fields.Float("Wage", function="_get_rotation",function_multi=True,store=True),
        'max_cycle': fields.Integer("Max Cycle", function="_get_rotation",function_multi=True,store=True),
        'ot_per_cycle': fields.Integer("OT Per Cycle", function="_get_rotation",function_multi=True,store=True),
        'check_max_cycle': fields.Boolean("Check Max Cycle"),
        'hire_date': fields.Date("Hire Date"),
        'resign_date': fields.Date("Resign Date"),
        "documents": fields.One2Many("document","related_id","Documents"),
        "rotations": fields.One2Many("clinic.staff.rotation","staff_id","Staff Rotation"),
        "cycles": fields.One2Many("clinic.staff.cycle","staff_id","Cycles"),
        'cycle_id': fields.Many2One('clinic.cycle','Last Cycle',function="_get_cycle"),
        "hd_case_staffs": fields.One2Many("clinic.hd.case.staff","staff_id","HD Cases"),
        "hd_cases": fields.Many2Many("clinic.hd.case","HD Cases",function="_get_hdcase"), # not need to use (it's slow to load)
        "cycle_item_lines": fields.One2Many("clinic.cycle.item.line","nurse_id","Cycle Items"),
        'branch_id': fields.Many2One("clinic.branch","Branch", search=True),
        "partner_id": fields.Many2One("partner","Contact"),
        'departments': fields.Many2Many("clinic.department","Departments"),
        'department_names': fields.Text("Departments",function="_get_department_names"),
        "location": fields.Char("Location",function="_get_location",store=True),
    }

    def _get_number(self,context={}):
        while 1:
            seq_type='clinic_staff'
            seq_id=get_model("sequence").find_sequence(type=seq_type)
            if not seq_id:
                return "/"
            num=get_model("sequence").get_next_number(seq_id,context=context)
            if not num:
                return None
            user_id=get_active_user()
            set_active_user(1)
            res=self.search([["number","=",num]])
            set_active_user(user_id)
            if not res:
                return num
            get_model("sequence").increment_number(seq_id,context=context)

    def _get_branch(self,context={}):
        b_ids=get_model('clinic.branch').search([])
        if b_ids:
            return b_ids[0]

    def _get_departments(self,context={}):
        res=get_model('select.company').get_select()
        if res:
            if res.get("department_ids"):
                return res['department_ids']
            else:
                return [res['department_id']]
        return get_model("clinic.department").search([])

    def _get_default_location(self,context={}):
        res=get_model('select.company').get_select()
        code=''
        if res:
            dpt_ids=[]
            if res.get("department_ids"):
                dpt_ids=res['department_ids']
            else:
                dpt_ids=[res['department_id']]
            dpts=get_model("clinic.department").browse(dpt_ids)
            code=','.join([dpt.code for dpt in dpts])
        return code

    def _get_department(self,context={}):
        res=get_model('select.company').get_select()
        if res:
            if res.get("department_ids"):
                return res['department_ids'][0]
            else:
                return res['department_id']

    _defaults={
        'active': True,
        "state": "part_time",
        "type": lambda self,ctx: ctx.get("type") or "staff",
        "date": lambda *a: time.strftime("%Y-%m-%d"),
        "number": _get_number,
        "company_id": lambda *a: get_active_company(),
        'branch_id': _get_branch,
        'departments': _get_departments,
        'department_id': _get_department,
        'location': _get_default_location,
    }

    _sql_constraints=("clinic_staff_key_uniq","unique(name_check)","name should be unique"),
    _order="date desc,number desc"
    
    def create_contact(self,code,name):
        partner_id=get_model("partner").create({
            'code': code,
            'name': name,
            'last_name': name,
            'type': 'person',
            'is_staff': True,
        })
        address_id=get_model('address').create({
            'type': 'shipping',
            'partner_id': partner_id,
            'address': 'your address',
            'address2': 'your address2',
            'city': 'your city',
            'postal_code': 'your zip',
            'country_id': 1,

        })
        return partner_id, address_id

    def check_contact(self,name=""):
        partner_id=None
        dom=[
            ['name','=',name],
            ['is_staff','=',True],
        ]
        for partner in get_model("partner").search_browse(dom):
            if partner.name==name:
                partner_id=partner.id
                break
        return partner_id

    def check_emp(self,name="", employee_id=None):
        names=name.split(" ")
        first_name=names[0]
        last_name=names[-1]
        if first_name==last_name:
            first_name=""
        vals={
            'first_name': first_name,
            'last_name': last_name,
        }
        emp_obj=get_model("hr.employee")
        emp_ids=emp_obj.search([['last_name','=',last_name]])
        emp_id=None
        if not emp_ids and not employee_id:
            emp_id=emp_obj.create(vals)
        elif employee_id:
            emp_obj.browse(employee_id).write(vals)
            emp_id=employee_id
        else:
            emp_id=emp_ids[0]
        return emp_id

    def create(self,vals,**kw):
        title_id=vals['title_id']
        title=get_model("clinic.name.title").browse(title_id)
        title_name=title.name or ""
        vals['name']=''
        if title_name.lower()=='notitle':
            vals['name']='%s%s %s'%(title_name,vals['first_name'],vals['last_name'])
        else:
            vals['name']='%s %s'%(vals['first_name'],vals['last_name'])
        partner_name='%s %s'%(vals['first_name'],vals['last_name']) #XXX
        employee_id=vals.get('employee_id')
        name=vals['name']
        emp_id=self.check_emp(name,employee_id)
        if emp_id:
            vals['employee_id']=emp_id
        partner_id=get_model("clinic.staff").check_contact(partner_name)
        address_id=None
        if not partner_id:
            vals['partner_id'],address_id=self.create_contact(vals['number'],partner_name)
        new_id=super().create(vals,**kw)
        self.function_store([new_id])
        for obj in self.browse([new_id]):
            if address_id:
                addr=get_model('address').browse(address_id)
                addr.write({
                    'partner_id': vals['partner_id'],
                    'staff_id': new_id,
                })
            if not obj.departments:
                dpt_ids=get_model("clinic.department").search([])
                for st in get_model("clinic.staff").search_browse([]):
                    if not st.departments:
                        st.write({
                            'departments': [['set',dpt_ids]],
                        })
                        print('set all department for ', st.name)
                
        return new_id

    def write(self,ids,vals,**kw):
        obj=self.browse(ids)[0]
        name=vals.get("name","")
        if not name:
            name=obj.name
        emp_id=self.check_emp(name,obj.employee_id.id)
        if emp_id:
            vals['employee_id']=emp_id
        partner_name='%s %s'%(obj.first_name or "",obj.last_name or "")
        partner_id=get_model("clinic.staff").check_contact(partner_name)
        address_id=None
        if not partner_id:
            vals['partner_id'],address_id=self.create_contact(partner_name,partner_name) #XXX
        super().write(ids,vals,**kw)
        self.function_store(ids)
        if address_id:
            addr=get_model('address').browse(address_id)
            addr.write({
                'partner_id': vals['partner_id'],
                'staff_id': ids[0],
            })
        if not obj.departments:
            dpt_ids=get_model("clinic.department").search([])
            for st in get_model("clinic.staff").search_browse([]):
                if not st.departments:
                    st.write({
                        'departments': [['set',dpt_ids]],
                    })
                    print('set all department for ', st.name)

    def name_get(self,ids,context={}):
        vals=[]
        for obj in self.browse(ids):
            name=obj.name or ""
            nickname=obj.nick_name or ""
            if nickname:
                name+=" (%s)"%(nickname)
            vals.append((obj.id,name))
        return vals

    def name_search(self,name,domain=None,condition=[],context={},**kw):
        dom=[["name","ilike","%"+name+"%"]]
        if domain:
             dom=[dom,domain] 
        ids1=self.search(dom)
        dom=[["nick_name","ilike","%"+name+"%"]]
        if domain:
             dom=[dom,domain] 
        ids2=self.search(dom)
        ids=list(set(ids1+ids2))
        return self.name_get(ids,context=context)

Staff.register()