# -*- coding: utf-8 -*-
"""
Tests para el modelo lims.parameter.range
"""
from odoo.tests import TransactionCase
from odoo.exceptions import ValidationError


class TestParameterRange(TransactionCase):
    """Tests para rangos de referencia de parámetros"""
    
    def setUp(self):
        super().setUp()
        self.Range = self.env['lims.parameter.range']
        self.Parameter = self.env['lims.analysis.parameter']
        
        # Crear parámetro de prueba
        self.test_param = self.Parameter.create({
            'code': 'HGB_TEST',
            'name': 'Hemoglobina Test',
            'value_type': 'numeric',
            'unit': 'g/dL'
        })
        
    def test_create_basic_range(self):
        """Test crear rango básico"""
        range_obj = self.Range.create({
            'parameter_id': self.test_param.id,
            'name': 'Adulto General',
            'normal_min': 12.0,
            'normal_max': 16.0
        })
        
        self.assertEqual(range_obj.parameter_id, self.test_param)
        self.assertEqual(range_obj.normal_min, 12.0)
        self.assertEqual(range_obj.normal_max, 16.0)
        self.assertFalse(range_obj.gender)  # Sin género específico
        
    def test_range_validation_min_max(self):
        """Test validación que min < max"""
        with self.assertRaises(ValidationError) as e:
            self.Range.create({
                'parameter_id': self.test_param.id,
                'name': 'Rango Inválido',
                'normal_min': 20.0,
                'normal_max': 10.0  # Max menor que min
            })
        self.assertIn('menor o igual', str(e.exception))
        
    def test_range_validation_age(self):
        """Test validación de rangos de edad"""
        with self.assertRaises(ValidationError) as e:
            self.Range.create({
                'parameter_id': self.test_param.id,
                'name': 'Rango Edad Inválida',
                'age_min': 65,
                'age_max': 18,  # Max menor que min
                'normal_min': 12.0,
                'normal_max': 16.0
            })
        self.assertIn('edad', str(e.exception))
        
    def test_critical_values_validation(self):
        """Test validación de valores críticos"""
        # Crítico min debe ser menor que normal min
        with self.assertRaises(ValidationError) as e:
            self.Range.create({
                'parameter_id': self.test_param.id,
                'name': 'Crítico Inválido',
                'normal_min': 12.0,
                'normal_max': 16.0,
                'critical_min': 13.0  # Mayor que normal_min
            })
        self.assertIn('crítico mínimo', str(e.exception))
        
        # Crítico max debe ser mayor que normal max
        with self.assertRaises(ValidationError) as e:
            self.Range.create({
                'parameter_id': self.test_param.id,
                'name': 'Crítico Inválido 2',
                'normal_min': 12.0,
                'normal_max': 16.0,
                'critical_max': 15.0  # Menor que normal_max
            })
        self.assertIn('crítico máximo', str(e.exception))
        
    def test_gender_specific_ranges(self):
        """Test rangos específicos por género"""
        # Rango para hombres
        male_range = self.Range.create({
            'parameter_id': self.test_param.id,
            'name': 'Hombre Adulto',
            'gender': 'male',
            'age_min': 18,
            'age_max': 65,
            'normal_min': 14.0,
            'normal_max': 18.0
        })
        
        # Rango para mujeres
        female_range = self.Range.create({
            'parameter_id': self.test_param.id,
            'name': 'Mujer Adulta',
            'gender': 'female',
            'age_min': 18,
            'age_max': 65,
            'normal_min': 12.0,
            'normal_max': 16.0
        })
        
        self.assertEqual(male_range.gender, 'male')
        self.assertEqual(female_range.gender, 'female')
        
    def test_pregnancy_specific_range(self):
        """Test rangos para embarazadas"""
        pregnancy_range = self.Range.create({
            'parameter_id': self.test_param.id,
            'name': 'Embarazada',
            'gender': 'female',
            'pregnant': True,
            'age_min': 15,
            'age_max': 50,
            'normal_min': 11.0,
            'normal_max': 14.0
        })
        
        self.assertTrue(pregnancy_range.pregnant)
        self.assertEqual(pregnancy_range.gender, 'female')
        
    def test_find_applicable_range(self):
        """Test encontrar rango aplicable según características del paciente"""
        # Crear varios rangos
        general_range = self.Range.create({
            'parameter_id': self.test_param.id,
            'name': 'General',
            'normal_min': 12.0,
            'normal_max': 16.0
        })
        
        male_adult_range = self.Range.create({
            'parameter_id': self.test_param.id,
            'name': 'Hombre Adulto',
            'gender': 'male',
            'age_min': 18,
            'age_max': 65,
            'normal_min': 14.0,
            'normal_max': 18.0
        })
        
        child_range = self.Range.create({
            'parameter_id': self.test_param.id,
            'name': 'Niño',
            'age_max': 12,
            'normal_min': 11.0,
            'normal_max': 14.0
        })
        
        pregnant_range = self.Range.create({
            'parameter_id': self.test_param.id,
            'name': 'Embarazada',
            'gender': 'female',
            'pregnant': True,
            'normal_min': 11.0,
            'normal_max': 14.0
        })
        
        # Test para hombre adulto de 30 años
        applicable = self.Range._find_applicable_range(
            self.test_param.id,
            gender='male',
            age=30,
            is_pregnant=False
        )
        self.assertEqual(applicable, male_adult_range)
        
        # Test para niño de 8 años
        applicable = self.Range._find_applicable_range(
            self.test_param.id,
            gender='male',
            age=8,
            is_pregnant=False
        )
        self.assertEqual(applicable, child_range)
        
        # Test para mujer embarazada
        applicable = self.Range._find_applicable_range(
            self.test_param.id,
            gender='female',
            age=28,
            is_pregnant=True
        )
        self.assertEqual(applicable, pregnant_range)
        
        # Test para caso sin rango específico (mujer no embarazada)
        applicable = self.Range._find_applicable_range(
            self.test_param.id,
            gender='female',
            age=35,
            is_pregnant=False
        )
        self.assertEqual(applicable, general_range)  # Debe devolver el rango general
        
    def test_range_overlap_allowed(self):
        """Test que se permiten rangos superpuestos"""
        # Rango 1: 0-18 años
        range1 = self.Range.create({
            'parameter_id': self.test_param.id,
            'name': 'Pediátrico',
            'age_max': 18,
            'normal_min': 11.0,
            'normal_max': 15.0
        })
        
        # Rango 2: 12-65 años (se superpone con rango 1)
        range2 = self.Range.create({
            'parameter_id': self.test_param.id,
            'name': 'Adolescente-Adulto',
            'age_min': 12,
            'age_max': 65,
            'normal_min': 12.0,
            'normal_max': 16.0
        })
        
        # Ambos rangos deben existir sin error
        self.assertTrue(range1.exists())
        self.assertTrue(range2.exists())
        
    def test_range_description_compute(self):
        """Test generación automática de descripción"""
        # Rango con todas las características
        full_range = self.Range.create({
            'parameter_id': self.test_param.id,
            'name': 'Completo',
            'gender': 'female',
            'age_min': 18,
            'age_max': 45,
            'pregnant': True,
            'normal_min': 11.0,
            'normal_max': 14.0,
            'critical_min': 8.0,
            'critical_max': 20.0
        })
        
        description = full_range.description
        self.assertIn('Mujer', description)
        self.assertIn('18-45 años', description)
        self.assertIn('Embarazada', description)
        self.assertIn('11.0 - 14.0', description)
        self.assertIn('Críticos', description)