import time

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

class Dialyzer(Model):
    _name="clinic.dialyzer"
    _string="Dialyzer"
    _audit_log=True
    _name_field="number"
    _multi_company=True
    
    _fields={
        "name": fields.Char("Name",search=True),
        "number": fields.Char("Number",required=True,search=True),
        'ref': fields.Char("Ref."),
        "note": fields.Text("Note",search=True),
        "date": fields.DateTime("Create Date",search=True),
        "use_time": fields.Integer("Use Time"),
        "max_use_time": fields.Integer("Max Use Time"),
        "exp_date": fields.Date("Expiry Date",search=True),
        "dialyzer_type": fields.Selection([("low","low flux"),("high","high flux"),("dbl","dbl hifulx")],"Dialyzer Type"),
        "state": fields.Selection([("new","New"),("active","Active"),("drop","Drop"),("expire","Expire"),('cancelled','Cancelled')],"Status"),
        "comments": fields.One2Many("message","related_id","Comments"),
        "company_id": fields.Many2One("company","Company"),
        'product_id': fields.Many2One("product", "Product",required=True),
        "pickings": fields.One2Many("stock.picking","related_id","Pickings"),
        "patient_id": fields.Many2One("clinic.patient","Patient",search=True),
        "visit_id": fields.Many2One("clinic.visit","Visit",search=True),
        "hd_case_id": fields.Many2One("clinic.hd.case","HD Case",search=True),
        "hd_cases": fields.One2Many("clinic.hd.case","dlz_id","HD Case"), #TODO funtion to get hd case
        'department_id': fields.Many2One("clinic.department","Department",search=True),
        "membrane_type": fields.Selection([("unsub","Unsub cellul"),("sub","Sub cellul"),("synthetic","Synthetic")],"Membrane Type"),
    }

    def _get_number(self,context={}):
        while 1:
            seq_name='Clinic Dialyzer'
            seq_id=get_model("sequence").find_sequence(name=seq_name)
            if not seq_id:
                raise Exception("Can not found sequence %s"%seq_name)
            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_product(self,context={}):
        categ_ids=get_model("product.categ").search([['name','=','Dialyzer']])
        product_id=None
        found=False
        for prod in get_model("product").search_browse([]):
            if found:
                break
            if prod.categ_id.id in categ_ids:
                product_id=prod.id
                found=True
                break
        if not product_id:
            raise Exception("No Product with category 'Dialyzer'")
        return product_id

    def _get_product_name(self,context={}):
        categ_ids=get_model("product.categ").search([['name','=','Dialyzer']])
        product_name=''
        found=False
        for prod in get_model("product").search_browse([]):
            if found:
                break
            if prod.categ_id.id in categ_ids:
                product_name=prod.name
                found=True
                break
        return product_name

    _defaults={
        "state": "new",
        "date": lambda *a: time.strftime("%Y-%m-%d %H:%M:%S"),
        'number': '/',
        "max_use_time": 10,
        "use_time": 0,
        "company_id": lambda *a: get_active_company(),
        'product_id': _get_product,
        'name': _get_product_name,
        'dialyzer_type': 'low',
    }
    _order="date desc,number desc"

    def void(self,ids,context={}):
        obj=self.browse(ids)[0]
        obj.write({"state":"voided"})

    def validate(self,ids,context={}):
        id=ids[0]
        obj=self.browse(id)
        patient=obj.patient_id
        #if not patient:
            #raise Exception("Patient is required")
        partner=patient.partner_id
        if not partner:
            raise Exception("Contact not for this patient")
        ship_address_id=None
        for address in partner.addresses:
            if address.type=="shipping":
                ship_address_id=address.id
                break
        if not ship_address_id:
            patient.simple_address()

        #XXX
        st=get_model("clinic.setting").browse(1)
        stock_journal=st.stock_journal_id

        wh_loc_id=None
        cust_loc_id=None
        department=obj.department_id
        if department:
            stock_journal=department.pick_out_journal_id
            if stock_journal:
                wh_loc_id=stock_journal.location_from_id.id
                cust_loc_id=stock_journal.location_to_id.id
                print("get location from stock journal %s "%(stock_journal.name))

        if not stock_journal:
            raise Exception("Not found stock journal")

        pick_vals={
            "type": "out",
            'journal_id': stock_journal.id,
            'date': obj.date,
            "ref": obj.number,
            "related_id": "clinic.dialyzer,%s"%obj.id,
            "partner_id": obj.patient_id.partner_id.id,
            "ship_address_id": ship_address_id,
            "lines": [],
            "state": "draft",
        }

        if not cust_loc_id:
            res=get_model("stock.location").search([["type","=","customer"]])
            if not res:
                raise Exception("Customer location not found")
            cust_loc_id=res[0]

        prod=obj.product_id
        if not wh_loc_id:
            wh_loc_id=prod.location_id.id # product -> tab inventory -> warehouse filed
            if not wh_loc_id:
                res=get_model("stock.location").search([["type","=","internal"]])
                if not res:
                    raise Exception("Warehouse not found")
                wh_loc_id=res[0]

        line_vals={
            "product_id": prod.id,
            "qty": 1,
            "uom_id": prod.uom_id.id,
            "location_from_id": wh_loc_id,
            "location_to_id": cust_loc_id,
        }
        pick_vals["lines"].append(("create",line_vals))
        if not pick_vals["lines"]:
            return {
                "flash": "Nothing left to deliver",
            }
        picking_obj=get_model("stock.picking")
        pick_id=picking_obj.create(pick_vals,context={"pick_type": "out"})
        pick=picking_obj.browse(pick_id)
        pick.set_done([pick_id])
        number=obj.number.replace("/","")
        if not number:
            number=self._get_number(context)
        obj.write({
            "number": number,
            "state": "active",
            })
        return {
            'next':{
               'name': 'clinic_dialyzer',
               'mode': 'form',
               'active_id': obj.id
            },
            'flash': 'Dialyzer %s is confirmed'%(number),
        }
        print("Done!")

    def delete(self,ids,context={}):
        for obj in self.browse(ids):
            if obj.state != 'new':
                raise Exception("Can not delete Dializer %s because state is not 'new'"%obj.number)
        super().delete(ids)
    
    def cancel(self,ids,context={}):
        obj=self.browse(ids[0])
        for pick in obj.pickings:
            pick.to_draft(context)
            pick.delete()
        obj.write({
            'state': 'cancelled',
        })
        return {
            'next':{
               'name': 'clinic_dialyzer',
               'mode': 'form',
               'active_id': obj.id
            },
            'flash': 'Dializer %s is cancelled'%(obj.number),
        }
    
    def to_draft(self,ids,context={}):
        obj=self.browse(ids[0])
        #if obj.use_time > obj.max_use_time:
            #raise Exception("Dialyzer %s is expired. (use time > max use time)"%obj.number or '')
        obj.cancel()
        obj.write({"state": "new"})

    def drop(self,ids,context={}):
        obj=self.browse(ids[0])
        obj.write({"state": "drop"})
        

    def copy(self,ids,context={}):
        obj=self.browse(ids[0])
        vals={
            'patient_id': obj.patient_id.id,
            'pickings':[],
        }
        new_id=self.create(vals,context=context)
        new_obj=self.browse(new_id)
        return {
            'next':{
               'name': 'clinic_dialyzer',
               'mode': 'form',
               'active_id': new_id,
            },
            'flash': 'Dializer %s is copy to %s'%(obj.number,new_obj.number),
        }
        
    
    def onchange_patient(self,context={}):
        data=context['data']
        patient_id=data['patient_id']
        patient=get_model("clinic.patient").browse(patient_id)
        department=patient.department_id
        if department:
            data['department_id']=department.id
        return data

    def onchange_product(self,context={}):
        data=context['data']
        prod_id=data['product_id']
        prod=get_model("product").browse(prod_id)
        if prod:
            data['name']=prod.name
        return data

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

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

Dialyzer.register()