# -*- coding: utf-8 -*-
"""
Tests para la generación automática de resultados basada en parámetros
"""
from odoo.tests import TransactionCase
from datetime import date


class TestAutoResultGeneration(TransactionCase):
    """Tests para la generación automática de resultados al crear pruebas"""
    
    def setUp(self):
        super().setUp()
        
        # Modelos
        self.Test = self.env['lims.test']
        self.Sample = self.env['stock.lot']
        self.Order = self.env['sale.order']
        self.Parameter = self.env['lims.analysis.parameter']
        self.TemplateParam = self.env['product.template.parameter']
        self.Product = self.env['product.template']
        self.Partner = self.env['res.partner']
        
        # Crear paciente
        self.patient = self.Partner.create({
            'name': 'Patient for Auto Generation',
            'is_patient': True,
            'gender': 'male',
            'birth_date': date(1985, 3, 15)
        })
        
        # Crear doctor
        self.doctor = self.Partner.create({
            'name': 'Dr. Test',
            'is_doctor': True
        })
        
        # Crear parámetros
        self.param1 = self.Parameter.create({
            'code': 'AUTO1',
            'name': 'Parameter Auto 1',
            'value_type': 'numeric',
            'unit': 'mg/dL'
        })
        
        self.param2 = self.Parameter.create({
            'code': 'AUTO2',
            'name': 'Parameter Auto 2',
            'value_type': 'selection',
            'selection_values': 'Normal,Anormal'
        })
        
        self.param3 = self.Parameter.create({
            'code': 'AUTO3',
            'name': 'Parameter Auto 3',
            'value_type': 'text'
        })
        
        # Crear análisis con parámetros configurados
        self.analysis_multi = self.Product.create({
            'name': 'Multi-Parameter Analysis',
            'type': 'service',
            'is_analysis': True,
            'categ_id': self.env.ref('lims_management.product_category_clinical_analysis').id,
            'sample_type_id': self.env.ref('lims_management.sample_type_blood').id,
        })
        
        # Configurar parámetros en el análisis
        self.TemplateParam.create({
            'product_tmpl_id': self.analysis_multi.id,
            'parameter_id': self.param1.id,
            'sequence': 10
        })
        
        self.TemplateParam.create({
            'product_tmpl_id': self.analysis_multi.id,
            'parameter_id': self.param2.id,
            'sequence': 20
        })
        
        self.TemplateParam.create({
            'product_tmpl_id': self.analysis_multi.id,
            'parameter_id': self.param3.id,
            'sequence': 30
        })
        
        # Crear análisis sin parámetros
        self.analysis_empty = self.Product.create({
            'name': 'Empty Analysis',
            'type': 'service',
            'is_analysis': True,
            'categ_id': self.env.ref('lims_management.product_category_clinical_analysis').id,
        })
        
    def test_auto_generate_results_on_test_creation(self):
        """Test generación automática de resultados al crear una prueba"""
        # Crear orden y muestra
        order = self.Order.create({
            'partner_id': self.patient.id,
            'doctor_id': self.doctor.id,
            'is_lab_request': True,
            'order_line': [(0, 0, {
                'product_id': self.analysis_multi.product_variant_id.id,
                'product_uom_qty': 1.0
            })]
        })
        order.action_confirm()
        
        # Generar muestra
        order.action_generate_samples()
        sample = order.lab_sample_ids[0]
        
        # La prueba debe haberse creado automáticamente con los resultados
        self.assertEqual(len(sample.test_ids), 1)
        test = sample.test_ids[0]
        
        # Verificar que se generaron todos los resultados
        self.assertEqual(len(test.result_ids), 3)
        
        # Verificar que cada resultado tiene el parámetro correcto
        param_ids = test.result_ids.mapped('parameter_id')
        self.assertIn(self.param1, param_ids)
        self.assertIn(self.param2, param_ids)
        self.assertIn(self.param3, param_ids)
        
        # Verificar orden de secuencia
        results_sorted = test.result_ids.sorted('sequence')
        self.assertEqual(results_sorted[0].parameter_id, self.param1)
        self.assertEqual(results_sorted[1].parameter_id, self.param2)
        self.assertEqual(results_sorted[2].parameter_id, self.param3)
        
    def test_no_results_for_analysis_without_parameters(self):
        """Test que no se generan resultados para análisis sin parámetros"""
        # Crear orden con análisis sin parámetros
        order = self.Order.create({
            'partner_id': self.patient.id,
            'is_lab_request': True,
            'order_line': [(0, 0, {
                'product_id': self.analysis_empty.product_variant_id.id,
                'product_uom_qty': 1.0
            })]
        })
        order.action_confirm()
        order.action_generate_samples()
        
        sample = order.lab_sample_ids[0]
        test = sample.test_ids[0]
        
        # No debe haber resultados
        self.assertEqual(len(test.result_ids), 0)
        
    def test_manual_test_creation_generates_results(self):
        """Test generación de resultados al crear prueba manualmente"""
        # Crear muestra manual
        sample = self.Sample.create({
            'name': 'SAMPLE-MANUAL-001',
            'is_lab_sample': True,
            'patient_id': self.patient.id,
            'sample_state': 'collected'
        })
        
        # Crear prueba manualmente
        test = self.Test.create({
            'sample_id': sample.id,
            'patient_id': self.patient.id,
            'product_id': self.analysis_multi.product_variant_id.id,
            'state': 'draft'
        })
        
        # Verificar generación automática
        self.assertEqual(len(test.result_ids), 3)
        
    def test_results_inherit_correct_sequence(self):
        """Test que los resultados heredan la secuencia correcta"""
        # Crear análisis con secuencias específicas
        analysis = self.Product.create({
            'name': 'Sequence Test Analysis',
            'type': 'service',
            'is_analysis': True,
            'categ_id': self.env.ref('lims_management.product_category_clinical_analysis').id,
        })
        
        # Configurar con secuencias no consecutivas
        self.TemplateParam.create({
            'product_tmpl_id': analysis.id,
            'parameter_id': self.param1.id,
            'sequence': 100
        })
        
        self.TemplateParam.create({
            'product_tmpl_id': analysis.id,
            'parameter_id': self.param2.id,
            'sequence': 50
        })
        
        self.TemplateParam.create({
            'product_tmpl_id': analysis.id,
            'parameter_id': self.param3.id,
            'sequence': 75
        })
        
        # Crear prueba
        test = self.Test.create({
            'patient_id': self.patient.id,
            'product_id': analysis.product_variant_id.id,
            'state': 'draft'
        })
        
        # Verificar orden: param2 (50), param3 (75), param1 (100)
        results_sorted = test.result_ids.sorted('sequence')
        self.assertEqual(results_sorted[0].parameter_id, self.param2)
        self.assertEqual(results_sorted[0].sequence, 50)
        self.assertEqual(results_sorted[1].parameter_id, self.param3)
        self.assertEqual(results_sorted[1].sequence, 75)
        self.assertEqual(results_sorted[2].parameter_id, self.param1)
        self.assertEqual(results_sorted[2].sequence, 100)
        
    def test_bulk_test_creation_performance(self):
        """Test rendimiento de creación masiva de pruebas"""
        # Crear múltiples órdenes
        orders = []
        for i in range(5):
            order = self.Order.create({
                'partner_id': self.patient.id,
                'is_lab_request': True,
                'order_line': [(0, 0, {
                    'product_id': self.analysis_multi.product_variant_id.id,
                    'product_uom_qty': 1.0
                })]
            })
            order.action_confirm()
            orders.append(order)
        
        # Generar muestras en lote
        for order in orders:
            order.action_generate_samples()
        
        # Verificar que todas las pruebas tienen resultados
        total_tests = 0
        total_results = 0
        
        for order in orders:
            for sample in order.lab_sample_ids:
                for test in sample.test_ids:
                    total_tests += 1
                    total_results += len(test.result_ids)
        
        self.assertEqual(total_tests, 5)
        self.assertEqual(total_results, 15)  # 5 tests * 3 parameters each
        
    def test_result_generation_with_mixed_analyses(self):
        """Test generación con análisis mixtos (con y sin parámetros)"""
        # Crear orden con múltiples análisis
        order = self.Order.create({
            'partner_id': self.patient.id,
            'is_lab_request': True,
            'order_line': [
                (0, 0, {
                    'product_id': self.analysis_multi.product_variant_id.id,
                    'product_uom_qty': 1.0
                }),
                (0, 0, {
                    'product_id': self.analysis_empty.product_variant_id.id,
                    'product_uom_qty': 1.0
                })
            ]
        })
        order.action_confirm()
        order.action_generate_samples()
        
        # Verificar resultados por prueba
        tests_with_results = 0
        tests_without_results = 0
        
        for sample in order.lab_sample_ids:
            for test in sample.test_ids:
                if test.result_ids:
                    tests_with_results += 1
                else:
                    tests_without_results += 1
        
        self.assertEqual(tests_with_results, 1)  # Solo analysis_multi
        self.assertEqual(tests_without_results, 1)  # Solo analysis_empty