from trytond.model import fields, ModelSQL, ModelView, Workflow, dualmethod
from trytond.modules.company import CompanyReport
from trytond.modules.company.model import employee_field, set_employee
from trytond.pool import Pool, PoolMeta
from trytond.pyson import Eval, If
from trytond.exceptions import UserError
from itertools import groupby
from trytond.transaction import Transaction
 

class Move(metaclass=PoolMeta):
    "Stock Move"
    __name__ = "stock.move"
    
    equipment = fields.Many2One('optical_equipment.equipment', "Equipment",
                                domain=[('state', '=', 'registred'),
                                        ('product','=', Eval('product'))
                                        ],
                                states={'invisible': If(~Eval('product_equipment'), True),
                                        'readonly': (Eval('state').in_(['cancelled', 'done'])),},
                                depends=['product_equipment'])
    equipment_serial = fields.Function(fields.Char('Serial',
                                                   states={'readonly': True,
                                                           'invisible': If(~Eval('product_equipment'), True)},
                                                   depends=['product_equipment']),
                                       'get_equipment_serial')
    product_equipment = fields.Function(fields.Boolean("It Equipment"),'get_product_equipment')

                
    @fields.depends('product')
    def get_product_equipment(self, product):
        if self.product.equipment:
            return True
        else:
            return False

    @fields.depends('equipment')
    def get_equipment_serial(self, equipment):
        if self.equipment:
            return self.equipment.serial
        else:
            return None
        
    @fields.depends('product', 'equipment', 'uom')
    def on_change_product(self):
        if self.product:
            if (not self.uom
                    or self.uom.category != self.product.default_uom.category):
                self.uom = self.product.default_uom

    @fields.depends(methods=['get_equipment_serial'])
    def on_change_equipment(self):
        if self.equipment:
            self.product = self.equipment.product.id
            self.equipment_serial = self.get_equipment_serial(self.equipment)
        else:
            self.equipment_serial = None


class ShipmentOut(metaclass=PoolMeta):
    "Customer Shipment"
    __name__ = 'stock.shipment.out'

    service_maintenance_initial = fields.Boolean('Maintenance Initial', states={'readonly': True})
    sale_type = fields.Char('Type sale origin')
    
    @classmethod
    def __setup__(cls):
        super(ShipmentOut, cls).__setup__()
        cls._buttons.update({
            'maintenance_initial': {
                'invisible': ((Eval('service_maintenance_initial',True))
                              | (Eval('sale_type').in_(['maintenance', 'replaces'])))}
        })
        
    @classmethod
    def view_attributes(cls):
        return super(ShipmentOut, cls).view_attributes() + [
            ('//page[@name="inventory_moves"]', 'states', {
                'invisible': False,
                    }),]

    @classmethod
    @ModelView.button
    @Workflow.transition('done')
    @set_employee('done_by')
    def done(cls, shipments):
        pool = Pool()
        Move = pool.get('stock.move')
        Date = pool.get('ir.date')

        Equipments = pool.get('optical_equipment.equipment')
        for shipment in shipments:
            for move in shipment.inventory_moves:
                count = 0
                if move.equipment:
                    equipment  = move.equipment
                    Id = equipment.id
                    equipment = Equipments.search(['id', '=',Id])[0]
                    equipment.propietary = shipment.customer.id
                    equipment.propietary_address= shipment.delivery_address.id
                    equipment.state="uncontrated"
                    equipment.shipment_destination = shipment
                    equipment.sale_destination = shipment.outgoing_moves[count].origin
                    equipment.propietarys += (shipment.customer,)
                    equipment.maintenance_frequency = "6" if shipment.customer.customer_type == "ips" else "12"
                    count+=1
                    equipment.save()
                else:
                    count+=1

        Move.delete([
                m for s in shipments for m in s.outgoing_moves
                if m.state == 'staging'])

        Move.do([m for s in shipments for m in s.outgoing_moves])
        for company, c_shipments in groupby(
                shipments, key=lambda s: s.company):
            with Transaction().set_context(company=company.id):
                today = Date.today()
            cls.write([s for s in c_shipments if not s.effective_date], {
                    'effective_date': today,
                    })

    @classmethod
    @ModelView.button
    def maintenance_initial(cls, shipments):
        pool = Pool()
        MaintenanceService = pool.get('optical_equipment_maintenance.service')
        Maintenance = pool.get('optical_equipment.maintenance')
        SaleLine = pool.get('sale.line')

        Equipments = pool.get('optical_equipment.equipment')

        for shipment in shipments:
            sale_origin = shipment.outgoing_moves[0].origin.sale.id
            # saleLine = SaleLine(
            #     type='line',
            #     quantity=1,
            #     unit_price=0,
            #     sale=sale_origin)
            # saleLine.save()
            #raise UserError(str((shipment.get_origins(name))))
            maintenanceService = MaintenanceService(
                sale_date=shipment.outgoing_moves[0].origin.sale.sale_date,
                sale_origin=shipment.outgoing_moves[0].origin.sale,
                maintenance_type='initial',
                propietary=shipment.customer.id,
                propietary_address=shipment.delivery_address.id,
                state='draft')
            maintenanceService.save()
            
            serial = False
            for move in shipment.inventory_moves:
                if move.product_equipment and move.equipment:
                    serial = True
                elif not move.product_equipment:
                    serial = True
                else:
                    serial = False

            if serial == True:
                for move in shipment.inventory_moves:
                    if move.product_equipment and move.equipment:
                        maintenance = Maintenance(
                            service_maintenance=maintenanceService.id,
                            maintenance_type='initial',
                            propietary=shipment.customer.id,
                            equipment_calibrate= True if move.equipment.product.calibration else False,
                            propietary_address=shipment.delivery_address.id,
                            equipment=move.equipment.id,
                            initial_operation = move.equipment.product.initial_operation,
                            check_equipment = move.equipment.product.template.check_equipment,
                            check_electric_system = move.equipment.product.template.check_electric_system,
                            clean_int_ext = move.equipment.product.template.clean_int_ext,
                            clean_eyes = move.equipment.product.template.clean_eyes,
                            check_calibration = move.equipment.product.template.check_calibration,
                            temperature_min = maintenanceService.temperature_min,
                            temperature_max = maintenanceService.temperature_max,
                            temperature_uom = maintenanceService.temperature_uom.id,
                            moisture_min = maintenanceService.moisture_min,
                            moisture_max = maintenanceService.moisture_max,
                            moisture_uom = maintenanceService.moisture_uom.id)
                        maintenance.save()
                shipment.service_maintenance_initial = True
                shipment.save()
            else:
                raise UserError(str('Por favor Primero debe Asignar un serial a todos los Equipos.'))


class ShipmentInternal(metaclass=PoolMeta):
    'Shipment Interncal'
    __name__ = 'stock.shipment.internal'

    @classmethod
    @ModelView.button
    @Workflow.transition('done')
    @set_employee('done_by')
    def done(cls, shipments):
        pool = Pool()
        Move = pool.get('stock.move')
        Date = pool.get('ir.date')

        for shipment in shipments:
            for move in shipment.moves:
                if move.equipment:
                    move.equipment.location = shipment.to_location
                    move.equipment.save()
                    
        Move.do([m for s in shipments for m in s.incoming_moves])
        cls.write([s for s in shipments if not s.effective_date], {
                'effective_date': Date.today(),})


class ShipmentOutReturn(metaclass=PoolMeta):
    "Customer Shipment Return"
    __name__ = 'stock.shipment.out.return'

    service_maintenance_initial = fields.Boolean('Maintenance Initial', states={'readonly': True})
    sale_type = fields.Char('Type sale origin')

    
class PickingListDeliveryReport(CompanyReport):
    __name__ = 'stock.shipment.out.picking_list1'

    @classmethod
    def execute(cls, ids, data):
        with Transaction().set_context(address_with_party=True):
            return super(PickingListDeliveryReport, cls).execute(ids, data)

    @classmethod
    def get_context(cls, records, header, data):
        pool = Pool()
        Date = pool.get('ir.date')
        context = super().get_context(records, header, data)
        context['today'] = Date.today()

        return context

    
class CapacitationReport(CompanyReport):
    __name__ = 'stock.shipment.out.capacitation_note'

    @classmethod
    def execute(cls, ids, data):
        with Transaction().set_context(address_with_party=True):
            return super(CapacitationReport, cls).execute(ids, data)

    @classmethod
    def get_context(cls, records, header, data):
        pool = Pool()
        Date = pool.get('ir.date')
        context = super().get_context(records, header, data)
        context['today'] = Date.today()

        return context