# -*- coding: utf-8 -*-
"""
Tests para la integración entre resultados y el catálogo de parámetros
"""
from odoo.tests import TransactionCase
from datetime import date


class TestResultParameterIntegration(TransactionCase):
    """Tests para la integración de resultados con parámetros y rangos"""
    
    def setUp(self):
        super().setUp()
        
        # Modelos
        self.Result = self.env['lims.result']
        self.Test = self.env['lims.test']
        self.Parameter = self.env['lims.analysis.parameter']
        self.Range = self.env['lims.parameter.range']
        self.Partner = self.env['res.partner']
        self.Product = self.env['product.template']
        
        # Crear paciente de prueba
        self.patient_male = self.Partner.create({
            'name': 'Test Patient Male',
            'is_patient': True,
            'gender': 'male',
            'birth_date': date(1990, 1, 1)  # 34 años aprox
        })
        
        self.patient_female_pregnant = self.Partner.create({
            'name': 'Test Patient Pregnant',
            'is_patient': True,
            'gender': 'female',
            'birth_date': date(1995, 6, 15),  # 29 años aprox
            'is_pregnant': True
        })
        
        # Crear parámetro de prueba
        self.param_glucose = self.Parameter.create({
            'code': 'GLU_TEST',
            'name': 'Glucosa Test',
            'value_type': 'numeric',
            'unit': 'mg/dL'
        })
        
        # Crear rangos de referencia
        self.range_general = self.Range.create({
            'parameter_id': self.param_glucose.id,
            'name': 'General',
            'normal_min': 70.0,
            'normal_max': 100.0,
            'critical_min': 50.0,
            'critical_max': 200.0
        })
        
        self.range_pregnant = self.Range.create({
            'parameter_id': self.param_glucose.id,
            'name': 'Embarazada',
            'gender': 'female',
            'pregnant': True,
            'normal_min': 60.0,
            'normal_max': 95.0,
            'critical_min': 45.0,
            'critical_max': 180.0
        })
        
        # Crear análisis de prueba
        self.analysis = self.Product.create({
            'name': 'Glucosa en Sangre Test',
            'type': 'service',
            'is_analysis': True,
            'categ_id': self.env.ref('lims_management.product_category_clinical_analysis').id,
        })
        
        # Configurar parámetro en el análisis
        self.env['product.template.parameter'].create({
            'product_tmpl_id': self.analysis.id,
            'parameter_id': self.param_glucose.id,
            'sequence': 10
        })
        
    def test_result_parameter_assignment(self):
        """Test asignación de parámetro a resultado"""
        # Crear test
        test = self.Test.create({
            'patient_id': self.patient_male.id,
            'product_id': self.analysis.product_variant_id.id,
            'state': 'draft'
        })
        
        # Crear resultado
        result = self.Result.create({
            'test_id': test.id,
            'parameter_id': self.param_glucose.id,
            'value_numeric': 85.0
        })
        
        self.assertEqual(result.parameter_id, self.param_glucose)
        self.assertEqual(result.value_type, 'numeric')
        self.assertEqual(result.unit, 'mg/dL')
        
    def test_applicable_range_selection(self):
        """Test selección automática de rango aplicable"""
        # Test para paciente masculino
        test_male = self.Test.create({
            'patient_id': self.patient_male.id,
            'product_id': self.analysis.product_variant_id.id,
            'state': 'draft'
        })
        
        result_male = self.Result.create({
            'test_id': test_male.id,
            'parameter_id': self.param_glucose.id,
            'value_numeric': 85.0
        })
        
        # Debe usar el rango general
        self.assertEqual(result_male.applicable_range_id, self.range_general)
        self.assertFalse(result_male.is_out_of_range)
        self.assertFalse(result_male.is_critical)
        
        # Test para paciente embarazada
        test_pregnant = self.Test.create({
            'patient_id': self.patient_female_pregnant.id,
            'product_id': self.analysis.product_variant_id.id,
            'state': 'draft'
        })
        
        result_pregnant = self.Result.create({
            'test_id': test_pregnant.id,
            'parameter_id': self.param_glucose.id,
            'value_numeric': 98.0  # Fuera de rango para embarazada
        })
        
        # Debe usar el rango para embarazadas
        self.assertEqual(result_pregnant.applicable_range_id, self.range_pregnant)
        self.assertTrue(result_pregnant.is_out_of_range)
        self.assertFalse(result_pregnant.is_critical)
        
    def test_out_of_range_detection(self):
        """Test detección de valores fuera de rango"""
        test = self.Test.create({
            'patient_id': self.patient_male.id,
            'product_id': self.analysis.product_variant_id.id,
            'state': 'draft'
        })
        
        # Valor normal
        result_normal = self.Result.create({
            'test_id': test.id,
            'parameter_id': self.param_glucose.id,
            'value_numeric': 85.0
        })
        self.assertFalse(result_normal.is_out_of_range)
        self.assertFalse(result_normal.is_critical)
        
        # Valor alto pero no crítico
        result_high = self.Result.create({
            'test_id': test.id,
            'parameter_id': self.param_glucose.id,
            'value_numeric': 115.0
        })
        self.assertTrue(result_high.is_out_of_range)
        self.assertFalse(result_high.is_critical)
        
        # Valor crítico alto
        result_critical = self.Result.create({
            'test_id': test.id,
            'parameter_id': self.param_glucose.id,
            'value_numeric': 250.0
        })
        self.assertTrue(result_critical.is_out_of_range)
        self.assertTrue(result_critical.is_critical)
        
    def test_selection_parameter_result(self):
        """Test resultado con parámetro de selección"""
        # Crear parámetro de selección
        param_culture = self.Parameter.create({
            'code': 'CULT_TEST',
            'name': 'Cultivo Test',
            'value_type': 'selection',
            'selection_values': 'Negativo,Positivo'
        })
        
        test = self.Test.create({
            'patient_id': self.patient_male.id,
            'product_id': self.analysis.product_variant_id.id,
            'state': 'draft'
        })
        
        result = self.Result.create({
            'test_id': test.id,
            'parameter_id': param_culture.id,
            'value_selection': 'Positivo'
        })
        
        self.assertEqual(result.value_type, 'selection')
        self.assertEqual(result.value_selection, 'Positivo')
        self.assertFalse(result.applicable_range_id)  # Selection no tiene rangos
        
    def test_text_parameter_result(self):
        """Test resultado con parámetro de texto"""
        param_observation = self.Parameter.create({
            'code': 'OBS_TEST',
            'name': 'Observación Test',
            'value_type': 'text'
        })
        
        test = self.Test.create({
            'patient_id': self.patient_male.id,
            'product_id': self.analysis.product_variant_id.id,
            'state': 'draft'
        })
        
        result = self.Result.create({
            'test_id': test.id,
            'parameter_id': param_observation.id,
            'value_text': 'Muestra hemolizada levemente'
        })
        
        self.assertEqual(result.value_type, 'text')
        self.assertEqual(result.value_text, 'Muestra hemolizada levemente')
        
    def test_boolean_parameter_result(self):
        """Test resultado con parámetro booleano"""
        param_pregnancy = self.Parameter.create({
            'code': 'PREG_TEST',
            'name': 'Embarazo Test',
            'value_type': 'boolean'
        })
        
        test = self.Test.create({
            'patient_id': self.patient_female_pregnant.id,
            'product_id': self.analysis.product_variant_id.id,
            'state': 'draft'
        })
        
        result = self.Result.create({
            'test_id': test.id,
            'parameter_id': param_pregnancy.id,
            'value_boolean': True
        })
        
        self.assertEqual(result.value_type, 'boolean')
        self.assertTrue(result.value_boolean)
        
    def test_formatted_value_display(self):
        """Test formato de visualización de valores"""
        test = self.Test.create({
            'patient_id': self.patient_male.id,
            'product_id': self.analysis.product_variant_id.id,
            'state': 'draft'
        })
        
        # Valor numérico
        result_numeric = self.Result.create({
            'test_id': test.id,
            'parameter_id': self.param_glucose.id,
            'value_numeric': 85.5
        })
        self.assertEqual(result_numeric.formatted_value, '85.5 mg/dL')
        
        # Valor de selección
        param_selection = self.Parameter.create({
            'code': 'SEL_FORMAT',
            'name': 'Selection Format',
            'value_type': 'selection',
            'selection_values': 'Opción A,Opción B'
        })
        
        result_selection = self.Result.create({
            'test_id': test.id,
            'parameter_id': param_selection.id,
            'value_selection': 'Opción A'
        })
        self.assertEqual(result_selection.formatted_value, 'Opción A')
        
        # Valor booleano
        param_bool = self.Parameter.create({
            'code': 'BOOL_FORMAT',
            'name': 'Boolean Format',
            'value_type': 'boolean'
        })
        
        result_bool = self.Result.create({
            'test_id': test.id,
            'parameter_id': param_bool.id,
            'value_boolean': True
        })
        self.assertEqual(result_bool.formatted_value, 'Sí')