from odoo import models, fields
import logging
import base64


class ResProductTemplate(models.Model):
    _inherit = 'product.template'

    # 模型的长,宽,高,体积,精度,材料
    model_name = fields.Char('模型名称')
    categ_type = fields.Selection(
        [("成品", "成品"), ("胚料", "胚料"), ("原材料", "原材料")], string='产品的类别', related='categ_id.type', store=True)
    model_long = fields.Float('模型长[mm]', digits=(16, 3))
    model_width = fields.Float('模型宽[mm]', digits=(16, 3))
    model_height = fields.Float('模型高[mm]', digits=(16, 3))
    model_volume = fields.Float('模型体积[m³]')
    model_machining_precision = fields.Selection([
        ('0.10', '±0.10mm'),
        ('0.05', '±0.05mm'),
        ('0.03', '±0.03mm'),
        ('0.02', '±0.02mm'),
        ('0.01', '±0.01mm')], string='加工精度')
    product_model_type_id = fields.Many2one('sf.model.type', string='产品模型类型')
    embryo_model_type_id = fields.Many2one('sf.model.type', string='胚料模型类型')
    model_processing_panel = fields.Char('模型加工面板')
    model_surface_process_id = fields.Many2one('sf.production.process', string='表面工艺')
    model_process_parameters_id = fields.Many2one('sf.processing.technology', string='工艺参数')
    # model_price = fields.Float('模型单价', digits=(16, 3))
    model_remark = fields.Char('模型备注说明')
    length = fields.Float('长[mm]', digits=(16, 3))
    width = fields.Float('宽[mm]', digits=(16, 3))
    height = fields.Float('高[mm]', digits=(16, 3))
    materials_id = fields.Many2one('sf.production.materials', string='材料')
    materials_type_id = fields.Many2one('sf.materials.model', string='材料型号')
    single_manufacturing = fields.Boolean(string="单个制造")
    upload_model_file = fields.Many2many('ir.attachment', 'upload_model_file_attachment_ref', string='上传模型文件')
    model_code = fields.Char('模型编码')
    is_bfm = fields.Boolean('业务平台是否自动创建', default=False)

    def _get_volume_uom_id_from_ir_config_parameter(self):
        product_length_in_feet_param = self.env['ir.config_parameter'].sudo().get_param('product.volume_in_cubic_feet')
        if product_length_in_feet_param == '1':
            return self.env.ref('uom.product_uom_cubic_foot')
        else:
            return self.env.ref('sf_dlm.product_uom_cubic_millimeter')

    # model_file = fields.Binary('模型文件')

    # 胚料的库存路线设置
    # def _get_routes(self, route_type):
    #     route_manufacture = self.env.ref('mrp.route_warehouse0_manufacture', raise_if_not_found=False).sudo()
    #     route_mto = self.env.ref('stock.route_warehouse0_mto', raise_if_not_found=False).sudo()
    #     route_purchase = self.env.ref('purchase_stock.route_warehouse0_buy', raise_if_not_found=False).sudo()
    #     if route_manufacture and route_mto:
    #         # 外协
    #         if route_type == 'subcontract':
    #             route_subcontract = self.env.ref('mrp_subcontracting.route_resupply_subcontractor_mto',
    #                                              raise_if_not_found=False).sudo()
    #             return [route_mto.id, route_purchase.id, route_subcontract.id]
    #         elif route_type == 'purchase':
    #             # 采购
    #             return [route_mto.id, route_purchase.id]
    #         else:
    #             return [route_mto.id, route_manufacture.id]
    #     return []

    # route_ids = fields.Many2many(default=lambda self: self._get_route())

    # 业务平台分配工厂后在智能工厂先创建销售订单再创建该产品
    def product_create(self, product_id, item, order_id, order_number, i):
        copy_product_id = product_id.with_user(self.env.ref("base.user_admin")).copy()
        copy_product_id.product_tmpl_id.active = True
        model_type = self.env['sf.model.type'].search([], limit=1)
        attachment = self.attachment_create(item['model_name'], item['model_data'])
        vals = {
            'name': '%s-%s-%s' % ('P', order_id.name, i),
            'model_long': item['model_long'] + model_type.embryo_tolerance,
            'model_width': item['model_width'] + model_type.embryo_tolerance,
            'model_height': item['model_height'] + model_type.embryo_tolerance,
            'model_volume': (item['model_long'] + model_type.embryo_tolerance) * (
                    item['model_width'] + model_type.embryo_tolerance) * (
                                    item['model_height'] + model_type.embryo_tolerance),
            'product_model_type_id': model_type.id,
            'model_processing_panel': 'R',
            'model_machining_precision': item['model_machining_precision'],
            'model_code': item['barcode'],
            'length': item['model_long'],
            'width': item['model_width'],
            'height': item['model_height'],
            'volume': item['model_long'] * item['model_width'] * item['model_height'],
            'model_file': '' if not item['model_file'] else base64.b64decode(item['model_file']),
            'model_name': attachment.name,
            'upload_model_file': [(6, 0, [attachment.id])],
            # 'single_manufacturing': True,
            # 'tracking': 'serial',
            'list_price': item['price'],
            # 'categ_id': self.env.ref('sf_dlm.product_category_finished_sf').id,
            'materials_id': self.env['sf.production.materials'].search(
                [('materials_no', '=', item['texture_code'])]).id,
            'materials_type_id': self.env['sf.materials.model'].search(
                [('materials_no', '=', item['texture_type_code'])]).id,
            'model_surface_process_id': self.env['sf.production.process'].search(
                [('process_encode', '=', item['surface_process_code'])]).id,
            # 'model_process_parameters_id': self.env['sf.processing.technology'].search(
            #     [('process_encode', '=', item['process_parameters_code'])]).id,
            'model_remark': item['remark'],
            'default_code': '%s-%s' % (order_number, i),
            # 'barcode': item['barcode'],
            'active': True,
            # 'route_ids': self._get_routes('')
        }
        copy_product_id.sudo().write(vals)
        # product_id.product_tmpl_id.active = False
        return copy_product_id

    def attachment_create(self, name, data):
        attachment = self.env['ir.attachment'].create({
            'datas': base64.b64decode(data),
            'type': 'binary',
            'public': True,
            'description': '模型文件',
            'name': name
        })
        return attachment

    # 创建胚料
    def no_bom_product_create(self, product_id, item, order_id, route_type, i):
        no_bom_copy_product_id = product_id.with_user(self.env.ref("base.user_admin")).copy()
        no_bom_copy_product_id.product_tmpl_id.active = True
        materials_id = self.env['sf.production.materials'].search(
            [('materials_no', '=', item['texture_code'])])
        materials_type_id = self.env['sf.materials.model'].search(
            [('materials_no', '=', item['texture_type_code'])])
        model_type = self.env['sf.model.type'].search([], limit=1)
        supplier = self.env['mrp.bom'].get_supplier(materials_type_id)
        logging.info('no_bom_copy_product_supplier-vals:%s' % supplier)
        vals = {
            'name': '%s-%s-%s [%s %s-%s * %s * %s]' % ('R',
                                                       order_id.name, i, materials_id.name, materials_type_id.name,
                                                       item['model_long'] + model_type.embryo_tolerance,
                                                       item['model_width'] + model_type.embryo_tolerance,
                                                       item['model_height'] + model_type.embryo_tolerance),
            'length': item['model_long'] + model_type.embryo_tolerance,
            'width': item['model_width'] + model_type.embryo_tolerance,
            'height': item['model_height'] + model_type.embryo_tolerance,
            'volume': (item['model_long'] + model_type.embryo_tolerance) * (
                    item['model_width'] + model_type.embryo_tolerance) * (
                              item['model_height'] + model_type.embryo_tolerance),
            'embryo_model_type_id': model_type.id,
            'list_price': item['price'],
            'materials_id': materials_id.id,
            'materials_type_id': materials_type_id.id,
            'is_bfm': True,
            # 'route_ids': self._get_routes(route_type),
            # 'categ_id': self.env.ref('sf_dlm.product_category_embryo_sf').id,
            # 'model_surface_process_id': self.env['sf.production.process'].search(
            #     [('process_encode', '=', item['surface_process_code'])]).id,
            # 'model_process_parameters_id': self.env['sf.processing.technology'].search(
            #     [('process_encode', '=', item['process_parameters_code'])]).id,
            'active': True
        }
        # 外协和采购生成的胚料需要根据材料型号绑定供应商
        if route_type == 'subcontract' or route_type == 'purchase':
            no_bom_copy_product_id.purchase_ok = True
            no_bom_copy_product_id.seller_ids = [
                (0, 0, {'partner_id': supplier.partner_id.id, 'delay': 1.0})]
            if route_type == 'subcontract':
                partner = self.env['res.partner'].search([('id', '=', supplier.partner_id.id)])
                partner.is_subcontractor = True
        no_bom_copy_product_id.write(vals)
        logging.info('no_bom_copy_product_id-vals:%s' % vals)
        # product_id.product_tmpl_id.active = False
        return no_bom_copy_product_id

    # @api.onchange('upload_model_file')
    # def onchange_model_file(self):
    #     for item in self:
    #         if len(item.upload_model_file) > 1:
    #             raise ValidationError('只允许上传一个文件')
    #         if item.upload_model_file:
    #             file_attachment_id = item.upload_model_file[0]
    #             item.model_name = file_attachment_id.name
    #             # 附件路径
    #             report_path = file_attachment_id._full_path(file_attachment_id.store_fname)
    #             shapes = read_step_file(report_path)
    #             output_file = get_resource_path('sf_dlm', 'static/file', 'out.stl')
    #             write_stl_file(shapes, output_file, 'binary', 0.03, 0.5)
    #             # 转化为glb
    #             output_glb_file = get_resource_path('sf_dlm', 'static/file', 'out.glb')
    #             util_path = get_resource_path('sf_dlm', 'static/util')
    #             cmd = 'python %s/stl2gltf.py %s %s -b' % (util_path, output_file, output_glb_file)
    #             os.system(cmd)
    #             # 转base64
    #             with open(output_glb_file, 'rb') as fileObj:
    #                 image_data = fileObj.read()
    #                 base64_data = base64.b64encode(image_data)
    #                 item.model_file = base64_data


class ResMrpBom(models.Model):
    _inherit = 'mrp.bom'

    subcontractor_id = fields.Many2one('res.partner', string='外包商')

    def bom_create_line_has(self, embryo):
        vals = {
            'bom_id': self.id,
            'product_id': embryo.id,
            'product_tmpl_id': embryo.product_tmpl_id.id,
            'product_qty': 1,
            'product_uom_id': 1
        }
        return self.env['mrp.bom.line'].create(vals)

    # 业务平台分配工厂后在智能工厂先创建销售订单再创建该产品后再次进行创建bom
    def bom_create(self, product, bom_type, product_type):
        bom_id = self.env['mrp.bom'].create({
            'product_tmpl_id': product.product_tmpl_id.id,
            'type': bom_type,
            # 'subcontractor_id': '' or subcontract.partner_id.id,
            'product_qty': 1,
            'product_uom_id': 1
        })
        if bom_type == 'subcontract' and product_type is not False:
            subcontract = self.get_supplier(product.materials_type_id)
            bom_id.subcontractor_id = subcontract.partner_id.id
        return bom_id

    # 胚料BOM组件：选取当前胚料原材料，
    # 然后根据当前的胚料的体积得出需要的原材料重量（立方米m³） *材料密度 * 1000 = 所需原材料重量KG（公斤）
    # 胚料所需原材料公式：当前的胚料的体积（立方米m³） *材料密度 * 1000 = 所需原材料重量KG（公斤）
    def bom_create_line(self, embryo):
        # 选取当前胚料原材料
        raw_bom_line = self.get_raw_bom(embryo)
        if raw_bom_line:
            bom_line = self.env['mrp.bom.line'].create({
                'bom_id': self.id,
                'product_id': raw_bom_line.id,
                'product_tmpl_id': raw_bom_line.product_tmpl_id.id,
                'product_qty': round(embryo.volume / 1000000000 * raw_bom_line.materials_type_id.density, 2),
                'product_uom_id': raw_bom_line.uom_id.id,
            })
            return bom_line
        else:
            return False

    # 查询材料型号默认排第一的供应商
    def get_supplier(self, materials_type):
        seller_id = self.env['sf.supplier.sort'].search(
            [('materials_model_id', '=', materials_type.id)],
            limit=1,
            order='sequence asc')
        return seller_id

    # 匹配bom
    def get_bom(self, product):
        embryo_has = self.env['product.product'].search(
            [('categ_id.type', '=', '胚料'), ('materials_type_id', '=', product.materials_type_id.id),
             ('length', '>', product.length), ('width', '>', product.width),
             ('height', '>', product.height), ('is_bfm', '=', False)
             ],
            limit=1,
            order='volume desc'
        )
        logging.info('get_bom-vals:%s' % embryo_has)
        if embryo_has:
            rate_of_waste = ((embryo_has.volume - product.model_volume) % embryo_has.volume) * 100
            if rate_of_waste <= 20:
                return embryo_has
        else:
            return

    # 查bom的原材料
    def get_raw_bom(self, product):
        raw_bom = self.env['product.product'].search(
            [('categ_id.type', '=', '原材料'), ('materials_type_id', '=', product.materials_type_id.id)])
        return raw_bom


class ResProductCategory(models.Model):
    _inherit = "product.category"

    type = fields.Selection(
        [("成品", "成品"), ("胚料", "胚料"), ("原材料", "原材料")],
        default="", string="类型")

    # @api.constrains('type')
    # def _check_type(self):
    #     category = self.env['product.category'].search(
    #         [('type', '=', self.type)])
    #     if category:
    #         raise ValidationError("该类别已存在,请选择其他类别")
