# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.

from odoo.tests import Form, common


class TestDuplicateProducts(common.TransactionCase):
    @classmethod
    def setUpClass(cls):
        super(TestDuplicateProducts, cls).setUpClass()
        cls.workcenter_1 = cls.env['mrp.workcenter'].create({
            'name': 'Nuclear Workcenter',
            'default_capacity': 2,
            'time_start': 10,
            'time_stop': 5,
            'time_efficiency': 80,
        })
        # Products and lots
        cls.painted_boat = cls.env['product.product'].create({
            'name': 'Painted boat',
            'type': 'product',
            'tracking': 'serial'})
        cls.pb1 = cls.env['stock.lot'].create({
            'company_id': cls.env.company.id,
            'product_id': cls.painted_boat.id,
            'name': 'pb1'})
        cls.blank_boat = cls.env['product.product'].create({
            'name': 'Blank Boat',
            'type': 'product',
            'tracking': 'serial'})
        cls.bb1 = cls.env['stock.lot'].create({
            'company_id': cls.env.company.id,
            'product_id': cls.blank_boat.id,
            'name': 'bb1'})
        cls.painting = cls.env['product.product'].create({
            'name': 'Color Painting',
            'type': 'product',
            'tracking': 'lot'})
        cls.p1 = cls.env['stock.lot'].create({
            'company_id': cls.env.company.id,
            'product_id': cls.painting.id,
            'name': 'p1'})

        # Bill of material
        cls.bom_boat = cls.env['mrp.bom'].create({
            'product_tmpl_id': cls.painted_boat.product_tmpl_id.id,
            'product_qty': 1.0})
        cls.operation_1 = cls.env['mrp.routing.workcenter'].create({
            'name': 'Gift Wrap Maching',
            'workcenter_id': cls.workcenter_1.id,
            'bom_id': cls.bom_boat.id,
            'time_cycle': 15,
            'sequence': 1,
        })
        cls.env['mrp.bom.line'].create({
            'product_id': cls.blank_boat.id,
            'product_qty': 1.0,
            'bom_id': cls.bom_boat.id})
        # first painting layer
        cls.env['mrp.bom.line'].create({
            'product_id': cls.painting.id,
            'product_qty': 1.0,
            'bom_id': cls.bom_boat.id})
        # second painting layer
        cls.env['mrp.bom.line'].create({
            'product_id': cls.painting.id,
            'product_qty': 1.0,
            'bom_id': cls.bom_boat.id})

        # Update quantities
        cls.location_1 = cls.env.ref('stock.stock_location_stock')
        Quant = cls.env['stock.quant']
        Quant._update_available_quantity(cls.blank_boat, cls.location_1, 1.0, lot_id=cls.bb1)
        Quant._update_available_quantity(cls.painting, cls.location_1, 10.0, lot_id=cls.p1)

    def test_duplicate_without_point(self):
        """ Bom with the same tracked product in 2 bom lines"""
        mrp_order_form = Form(self.env['mrp.production'])
        mrp_order_form.product_id = self.painted_boat
        mrp_order_form.product_qty = 1
        production = mrp_order_form.save()

        production.action_confirm()
        production.button_plan()
        self.assertEqual(len(production.workorder_ids), 1, "wrong number of workorders")
        self.assertEqual(production.workorder_ids.state, 'ready', "workorder state should be 'ready'")
        self.assertEqual(len(production.workorder_ids.check_ids), 3, "Same components are not merged, should be 3 quality checks")
        painting_checks = production.workorder_ids.check_ids.filtered(lambda check: check.component_id == self.painting)
        self.assertEqual(len(painting_checks), 2, "should be 2 quality checks for painting")

    def test_duplicate_with_points(self):
        """ Bom with the same non tracked product in 2 bom lines and a quality point
        on this component"""
        self.painting.tracking = 'none'
        self.blank_boat.tracking = 'none'
        self.env['quality.point'].create({
            'product_ids': [(4, self.painted_boat.id)],
            'picking_type_ids': [(4, self.env['stock.picking.type'].search([('code', '=', 'mrp_operation')], limit=1).id)],
            'operation_id': self.operation_1.id,
            'test_type_id': self.env.ref('mrp_workorder.test_type_register_consumed_materials').id,
            'component_id': self.painting.id,
        })
        self.env['quality.point'].create({
            'product_ids': [(4, self.painted_boat.id)],
            'picking_type_ids': [(4, self.env['stock.picking.type'].search([('code', '=', 'mrp_operation')], limit=1).id)],
            'operation_id': self.operation_1.id,
            'test_type_id': self.env.ref('mrp_workorder.test_type_register_consumed_materials').id,
            'component_id': self.blank_boat.id,
        })
        self.bom_boat.bom_line_ids.write({'operation_id': self.operation_1.id})

        mrp_order_form = Form(self.env['mrp.production'])
        mrp_order_form.product_id = self.painted_boat
        mrp_order_form.product_qty = 1
        production = mrp_order_form.save()

        production.action_confirm()
        production.button_plan()
        self.assertEqual(len(production.workorder_ids), 1, "wrong number of workorders")
        self.assertEqual(production.workorder_ids.state, 'ready', "workorder state should be 'ready'")
        self.assertEqual(len(production.workorder_ids.check_ids), 3, "Same components are not merged, should be 3 quality checks")
        painting_checks = production.workorder_ids.check_ids.filtered(lambda check: check.component_id == self.painting)
        self.assertEqual(len(painting_checks), 2, "should be 2 quality checks for painting")

    def test_assignation_1(self):
        """ Bom with the same tracked product in 2 bom lines
        Plan the workorder before reservign quantities """
        mrp_order_form = Form(self.env['mrp.production'])
        mrp_order_form.product_id = self.painted_boat
        mrp_order_form.product_qty = 1
        production = mrp_order_form.save()

        production.action_confirm()
        production.button_plan()
        self.assertEqual(len(production.workorder_ids), 1, "wrong number of workorders")
        self.assertEqual(production.workorder_ids.state, 'ready', "workorder state should be 'ready'")
        self.assertEqual(len(production.workorder_ids.check_ids), 3, "Same components are not merged, should be 3 quality checks")
        painting_checks = production.workorder_ids.check_ids.filtered(lambda check: check.component_id == self.painting)
        self.assertEqual(len(painting_checks), 2, "should be 2 quality checks for painting")
        production.action_assign()
        self.assertEqual(len(production.workorder_ids.check_ids), 3, "Same components merged, should be 3 quality checks")
        painting_checks = production.workorder_ids.check_ids.filtered(lambda check: check.component_id == self.painting)
        self.assertEqual(len(painting_checks), 2, "should be 2 quality checks for painting")

    def test_byproduct_1(self):
        """ Use the same product as component and as byproduct"""
        # Required for `byproduct_ids` to be visible in the view
        self.env.user.groups_id += self.env.ref('mrp.group_mrp_byproducts')
        bom_form = Form(self.bom_boat)
        with bom_form.byproduct_ids.new() as bp:
            bp.product_id = self.painting
            bp.product_qty = 1.0
        bom_form.save()
        self.p2 = self.env['stock.lot'].create({
            'company_id': self.env.company.id,
            'product_id': self.painting.id,
            'name': 'p2'})

        mrp_order_form = Form(self.env['mrp.production'])
        mrp_order_form.product_id = self.painted_boat
        mrp_order_form.product_qty = 1
        production = mrp_order_form.save()

        production.action_confirm()
        production.button_plan()

        production.workorder_ids[0].button_start()
        wo_form = Form(production.workorder_ids[0], view='mrp_workorder.mrp_workorder_view_form_tablet')
        # Components
        wo_form.finished_lot_id = self.pb1
        wo = wo_form.save()
        qc_form = Form(wo.current_quality_check_id, view='mrp_workorder.quality_check_view_form_tablet')
        qc_form.lot_id = self.bb1
        qc = qc_form.save()
        qc._next()
        # First layer
        qc_form = Form(wo.current_quality_check_id, view='mrp_workorder.quality_check_view_form_tablet')
        qc_form.lot_id = self.p1
        qc = qc_form.save()
        qc._next()
        # Second layer
        qc_form = Form(wo.current_quality_check_id, view='mrp_workorder.quality_check_view_form_tablet')
        qc_form.lot_id = self.p1
        qc = qc_form.save()
        qc._next()
        qc_form = Form(wo.current_quality_check_id, view='mrp_workorder.quality_check_view_form_tablet')
        # Byproduct
        qc_form.lot_id = self.p2
        qc = qc_form.save()
        qc._next()
        wo.do_finish()
        production.button_mark_done()

        move_paint_raw = production.move_raw_ids.filtered(lambda move: move.product_id == self.painting)
        self.assertEqual(len(move_paint_raw), 2, 'there should be 2 moves after merge same components')
        self.assertEqual(move_paint_raw.mapped('state'), ['done', 'done'], 'Moves should be done')
        self.assertEqual(move_paint_raw.mapped('quantity_done'), [1, 1], 'Consumed quantity should be 2')
        self.assertEqual(len(move_paint_raw.move_line_ids), 2, 'their should be 2 move lines')
        self.assertEqual(move_paint_raw.mapped('move_line_ids').mapped('lot_id'), self.p1, 'Wrong lot numbers used')
        move_paint_finished = production.move_finished_ids.filtered(lambda move: move.product_id == self.painting)
        self.assertEqual(move_paint_finished.state, 'done', 'Move should be done')
        self.assertEqual(move_paint_finished.quantity_done, 1, 'Consumed quantity should be 1')
        self.assertEqual(len(move_paint_finished.move_line_ids), 1, 'their should be 1 move line')
        self.assertEqual(move_paint_finished.move_line_ids.lot_id, self.p2, 'Wrong lot numbers used')
