from datetime import datetime, timedelta

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

class Schedule(Model):
    _name="clinic.schedule"
    _string="Schedule"
    _name_field="name"
    _key=['name']

    def _get_name(self,ids,context={}):
        res={}
        for obj in self.browse(ids):
            count=len(obj.lines)
            dpt=obj.department_id
            name='%s %s'%(obj.date, dpt.name or '')
            res[obj.id]='%s'%(name if count else 'Waiting planing')
        return res
    
    _fields={
        'name': fields.Char("Name", function="_get_name",store=True),
        "time_start": fields.DateTime("Time Start",required=True),
        "time_stop": fields.DateTime("Time Stop",required=True),
        'date': fields.Date("Date",required=True,search=True),
        'lines': fields.One2Many("clinic.schedule.line","schedule_id","Lines"),
        'company_id': fields.Many2One("company","Company"),
        'branch_id': fields.Many2One("clinic.branch","Branch",required=True, search=True),
        'department_id': fields.Many2One("clinic.department","Department",required=True, search=True),
        'state': fields.Selection([['draft','Draft'],['confirmed', 'Confirmed']],'State',search=True),
        'user_id': fields.Many2One("base.user","Confirm By"),
    }
    
    def _get_date(self,context={}):
        datenow=datetime.now().strftime("%Y-%m-%d")
        return datenow

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

    _defaults={
        'user_id': lambda *a: get_active_user(),
        "company_id": lambda *a: get_active_company(),
        'branch_id': _get_branch,
        'date': _get_date,
        'time_start': lambda *a: datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
        'time_stop': lambda *a: (datetime.now()+timedelta(seconds=3600)).strftime("%Y-%m-%d %H:%M:%S"),
        'state': 'draft',
    }

    _order="date desc"

    _sql_constraints=[
        ('schedule_uniq','unique (date,company_id,branch_id,department_id)','Date should be unique'),
    ]

    def confirm(self,ids,context={}):
        obj=self.browse(ids)[0]
        obj.copy2cycle_item()
        obj.write({
            'state': 'confirmed',
        })
        return {
            'next': {
                'name': 'clinic_schedule',
                'mode': 'form',
                'active_id': obj.id,
            },
            'flash': 'Schedule %s has been confirmed'%obj.date,
        }

    def to_draft(self,ids,context={}):
        obj=self.browse(ids)[0]
        obj.write({
            'state': 'draft',
        })
        return {
            'next': {
                'name': 'clinic_schedule',
                'mode': 'form',
                'active_id': obj.id,
            },
            'flash': 'Schedule %s has been set to draft'%obj.date,
        }
        
    
    def copy(self,ids,context={}):
        obj=self.browse(ids)[0]
        datenow=datetime.now().strftime("%Y-%m-%d")
        old_ids=get_model('clinic.schedule').search([['date','=',datenow]])
        if old_ids:
            raise Exception("This schedule is already create!")
        vals={
            'lines': [],
        }
        for line in obj.lines:
            vals['lines'].append(('create', {
                    'nurse_id': line.nurse_id.id,
                    'cycle_id': line.cycle_id.id
                    }
            ))
        new_id=get_model("clinic.schedule").create(vals)
        new_obj=get_model("clinic.schedule").browse(new_id)
        return {
            'next': {
                'name': 'clinic_schedule',
                'mode': 'form',
                'active_id': new_id,
            },
            'flash': 'Copy schedule from %s to %s successfully'%(obj.date,new_obj.date)
        }

    def copy2cycle_item(self,ids,context={}):
        obj=self.browse(ids)[0]
        branch=obj.branch_id
        department=obj.department_id
        date=obj.date
        items={}
        cycles=set()
        for line in obj.lines:
            nurse=line.nurse_id
            cycle=line.cycle_id
            dom=[
                ['date','=',date],
                ['cycle_id','=',cycle.id],
                ['branch_id','=',branch.id],
                ['department_id','=',department.id],
                ]
            item_objs=get_model("clinic.cycle.item").search_browse(dom)
            if item_objs:
                item=item_objs[0]
                if item.state!='draft':
                    continue
                if not items.get(item.id):
                    items[item.id]=[]
                items[item.id].append(('create',{
                    'nurse_id': nurse.id,
                    'level_id': nurse.level_id.id,
                }))
                line.write({
                    'cycle_item_id': item.id,
                })
                cycles.update({cycle.name})
            else:
                item_id=get_model("clinic.cycle.item").create({
                    'cycle_id': cycle.id,
                    'date': date,
                    'branch_id': branch.id,
                    'department_id': department.id,
                })
                items[item_id]=[]
                items[item_id].append(('create',{
                    'nurse_id': nurse.id,
                    'level_id': nurse.level_id.id,
                }))
                line.write({
                    'cycle_item_id': item_id,
                })
                cycles.update({cycle.name})

        for item_id, lines in items.items():
            item=get_model("clinic.cycle.item").browse(item_id)
            for line in item.lines:
                line.delete()
            item.write({
                'lines': lines,
            })

        cycles=list(reversed(list(cycles)))
        msg='Copy nurses to cycle item %s successfully'%(','.join(cycles))
        # TODO create cycle item automatically
        if not items:
            msg='No cycle item to copy'
        return {
            'next': {
                'name': 'clinic_schedule',
                'mode': 'form',
                'active_id': obj.id,
            },
            'flash': msg,
        }

    def onchange_date(self,context={}):
        data=context['data']
        date=data['date']
        time_start=data['time_start'][11:]
        data['time_start']='%s %s'%(date,time_start)
        time_stop=data['time_stop'][11:]
        data['time_stop']='%s %s'%(date,time_stop)
        return data
    
    def load_all_nurse(self,ids,context={}):
        nurses=get_model("clinic.staff").search_browse([['type','=','nurse']])
        vals={
            'lines': [],
        }
        for nurse in nurses:
            vals['lines'].append({
                'cycle_id': nurse.id,
                'nurse_id': nurse.id,
            })
        obj=self.browse(ids)[0]
        obj.write(vals)

    def clear(self,ids,context={}):
        obj=self.browse(ids)[0]
        for line in obj.lines:
            line.delete()
        return {
            'next': {
                'name': 'clinic_schedule',
                'mode': 'form',
                'active_id': obj.id,
            },
            'flash': 'List of nurse has been cleared.',
        }

    def onchange_nurse(self,context={}):
        data=context['data']
        path=context["path"]
        line=get_data_path(data,path,parent=True)
        nurse_id=line['nurse_id']
        nurse=get_model("clinic.staff").browse(nurse_id)
        line['level_id']=nurse.level_id.id
        line['state']=nurse.state
        return data
    
    def create(self,vals,**kw):
        id=super().create(vals,**kw)
        self.function_store([id])
        return id

    def write(self,ids,vals,**kw):
        super().write(ids,vals,**kw)
        self.function_store(ids)
    
    def onchange_branch(self,context={}):
        data=context['data']
        data['department_id']=None
        return data

Schedule.register()