# -*- coding: utf-8 -*-
"""
Test para verificar la cancelación en cascada de muestras y pruebas
cuando se cancela una orden de laboratorio
"""

from odoo.tests import TransactionCase
from odoo.exceptions import UserError
import logging

_logger = logging.getLogger(__name__)


class TestOrderCancelCascade(TransactionCase):
    """Test de cancelación en cascada de órdenes de laboratorio"""
    
    def setUp(self):
        super().setUp()
        
        # Obtener modelos
        self.Partner = self.env['res.partner']
        self.Product = self.env['product.product']
        self.SaleOrder = self.env['sale.order']
        self.StockLot = self.env['stock.lot']
        self.LimsTest = self.env['lims.test']
        
        # Crear datos de prueba
        self.patient = self.Partner.create({
            'name': 'Test Patient Cancel',
            'is_patient': True,
            'birthdate_date': '1990-01-01',
            'gender': 'male'
        })
        
        self.doctor = self.Partner.create({
            'name': 'Test Doctor Cancel',
            'is_doctor': True
        })
        
        # Crear tipo de muestra
        self.sample_type = self.env['product.template'].create({
            'name': 'Tubo EDTA Test',
            'is_sample_type': True,
            'type': 'service',
            'categ_id': self.env.ref('product.product_category_all').id
        })
        
        # Crear análisis
        self.analysis = self.env['product.template'].create({
            'name': 'Hemograma Test Cancel',
            'is_analysis': True,
            'type': 'service',
            'required_sample_type_id': self.sample_type.id,
            'categ_id': self.env.ref('product.product_category_all').id
        })
        
        # Crear parámetro para el análisis
        self.parameter = self.env['lims.analysis.parameter'].create({
            'name': 'Hemoglobina Test',
            'code': 'HGB_TEST',
            'value_type': 'numeric',
            'unit': 'g/dL'
        })
        
        # Configurar parámetro en el análisis
        self.env['product.template.parameter'].create({
            'product_tmpl_id': self.analysis.id,
            'parameter_id': self.parameter.id,
            'sequence': 10
        })
    
    def test_01_cancel_order_cancels_samples(self):
        """Test que al cancelar una orden se cancelan las muestras asociadas"""
        # Crear orden de laboratorio
        order = self.SaleOrder.create({
            'partner_id': self.patient.id,
            'doctor_id': self.doctor.id,
            'is_lab_request': True,
            'order_line': [(0, 0, {
                'product_id': self.analysis.product_variant_id.id,
                'product_uom_qty': 1.0
            })]
        })
        
        # Confirmar la orden (debe generar muestras)
        order.action_confirm()
        
        # Verificar que se generaron muestras
        self.assertTrue(order.generated_sample_ids, "No se generaron muestras")
        samples = order.generated_sample_ids
        
        # Verificar estado inicial de las muestras
        for sample in samples:
            self.assertIn(sample.state, ['pending_collection', 'collected'], 
                         f"Estado inicial incorrecto: {sample.state}")
        
        # Cancelar la orden
        order.action_cancel()
        
        # Verificar que las muestras fueron canceladas
        for sample in samples:
            self.assertEqual(sample.state, 'cancelled', 
                           f"Muestra no fue cancelada: {sample.state}")
    
    def test_02_cancel_order_cancels_tests(self):
        """Test que al cancelar una orden se cancelan las pruebas asociadas"""
        # Crear orden de laboratorio
        order = self.SaleOrder.create({
            'partner_id': self.patient.id,
            'doctor_id': self.doctor.id,
            'is_lab_request': True,
            'order_line': [(0, 0, {
                'product_id': self.analysis.product_variant_id.id,
                'product_uom_qty': 1.0
            })]
        })
        
        # Confirmar la orden
        order.action_confirm()
        
        # Obtener las pruebas generadas
        tests = self.LimsTest.search([
            ('sale_order_line_id.order_id', '=', order.id)
        ])
        self.assertTrue(tests, "No se generaron pruebas")
        
        # Verificar estado inicial
        for test in tests:
            self.assertEqual(test.state, 'draft', 
                           f"Estado inicial incorrecto: {test.state}")
        
        # Iniciar proceso en una prueba
        if tests:
            tests[0].write({'sample_id': order.generated_sample_ids[0].id})
            tests[0].action_start_process()
            self.assertEqual(tests[0].state, 'in_process')
        
        # Cancelar la orden
        order.action_cancel()
        
        # Verificar que las pruebas fueron canceladas
        for test in tests:
            self.assertEqual(test.state, 'cancelled', 
                           f"Prueba no fue cancelada: {test.state}")
    
    def test_03_dont_cancel_completed_samples(self):
        """Test que no se cancelan muestras en estados finales"""
        # Crear orden
        order = self.SaleOrder.create({
            'partner_id': self.patient.id,
            'doctor_id': self.doctor.id,
            'is_lab_request': True,
            'order_line': [(0, 0, {
                'product_id': self.analysis.product_variant_id.id,
                'product_uom_qty': 1.0
            })]
        })
        
        # Confirmar
        order.action_confirm()
        
        # Marcar una muestra como analizada
        sample = order.generated_sample_ids[0]
        sample.write({'state': 'analyzed'})
        
        # Cancelar la orden
        order.action_cancel()
        
        # Verificar que la muestra analizada no fue cancelada
        self.assertEqual(sample.state, 'analyzed', 
                       "Muestra analizada fue cancelada incorrectamente")
    
    def test_04_dont_cancel_validated_tests(self):
        """Test que no se cancelan pruebas validadas"""
        # Crear orden
        order = self.SaleOrder.create({
            'partner_id': self.patient.id,
            'doctor_id': self.doctor.id,
            'is_lab_request': True,
            'order_line': [(0, 0, {
                'product_id': self.analysis.product_variant_id.id,
                'product_uom_qty': 1.0
            })]
        })
        
        # Confirmar
        order.action_confirm()
        
        # Obtener prueba y marcarla como validada
        test = self.LimsTest.search([
            ('sale_order_line_id.order_id', '=', order.id)
        ], limit=1)
        
        if test:
            test.write({
                'state': 'validated',
                'sample_id': order.generated_sample_ids[0].id
            })
        
        # Cancelar la orden
        order.action_cancel()
        
        # Verificar que la prueba validada no fue cancelada
        self.assertEqual(test.state, 'validated', 
                       "Prueba validada fue cancelada incorrectamente")
    
    def test_05_chatter_messages_created(self):
        """Test que se crean mensajes en el chatter"""
        # Crear orden
        order = self.SaleOrder.create({
            'partner_id': self.patient.id,
            'doctor_id': self.doctor.id,
            'is_lab_request': True,
            'order_line': [(0, 0, {
                'product_id': self.analysis.product_variant_id.id,
                'product_uom_qty': 1.0
            })]
        })
        
        # Confirmar
        order.action_confirm()
        
        # Obtener conteo inicial de mensajes
        initial_order_messages = len(order.message_ids)
        sample = order.generated_sample_ids[0]
        initial_sample_messages = len(sample.message_ids)
        
        # Cancelar
        order.action_cancel()
        
        # Verificar que se agregaron mensajes
        self.assertGreater(len(order.message_ids), initial_order_messages,
                          "No se agregó mensaje en la orden")
        self.assertGreater(len(sample.message_ids), initial_sample_messages,
                          "No se agregó mensaje en la muestra")
        
        # Verificar contenido del mensaje
        last_order_msg = order.message_ids[0].body
        self.assertIn("cancelaron automáticamente", last_order_msg,
                     "Mensaje de orden no contiene texto esperado")
    
    def test_06_non_lab_order_not_affected(self):
        """Test que órdenes normales no son afectadas"""
        # Crear orden normal (no de laboratorio)
        order = self.SaleOrder.create({
            'partner_id': self.patient.id,
            'is_lab_request': False,  # NO es orden de laboratorio
            'order_line': [(0, 0, {
                'product_id': self.analysis.product_variant_id.id,
                'product_uom_qty': 1.0
            })]
        })
        
        # Confirmar
        order.action_confirm()
        
        # No deberían generarse muestras
        self.assertFalse(order.generated_sample_ids, 
                        "Se generaron muestras en orden normal")
        
        # Cancelar - no debería causar error
        order.action_cancel()
        self.assertEqual(order.state, 'cancel')