# -*- coding: utf-8 -*-
from odoo import models, fields, api
from odoo.exceptions import ValidationError


class LimsParameterRange(models.Model):
    _name = 'lims.parameter.range'
    _description = 'Rangos de Referencia por Parámetro'
    _order = 'parameter_id, gender desc, age_min'
    _rec_name = 'name'

    parameter_id = fields.Many2one(
        'lims.analysis.parameter',
        string='Parámetro',
        required=True,
        ondelete='cascade',
        help='Parámetro al que aplica este rango de referencia'
    )
    
    name = fields.Char(
        string='Descripción',
        compute='_compute_name',
        store=True,
        help='Descripción automática del rango'
    )
    
    # Condiciones
    gender = fields.Selection([
        ('male', 'Masculino'),
        ('female', 'Femenino'),
        ('both', 'Ambos')
    ], 
        string='Género',
        default='both',
        required=True,
        help='Género al que aplica este rango'
    )
    
    age_min = fields.Integer(
        string='Edad Mínima',
        default=0,
        help='Edad mínima en años (inclusive)'
    )
    
    age_max = fields.Integer(
        string='Edad Máxima',
        default=150,
        help='Edad máxima en años (inclusive)'
    )
    
    pregnant = fields.Boolean(
        string='Embarazada',
        default=False,
        help='Marcar si este rango es específico para mujeres embarazadas'
    )
    
    # Valores de referencia
    normal_min = fields.Float(
        string='Valor Normal Mínimo',
        help='Límite inferior del rango normal'
    )
    
    normal_max = fields.Float(
        string='Valor Normal Máximo',
        help='Límite superior del rango normal'
    )
    
    critical_min = fields.Float(
        string='Valor Crítico Mínimo',
        help='Por debajo de este valor es crítico'
    )
    
    critical_max = fields.Float(
        string='Valor Crítico Máximo',
        help='Por encima de este valor es crítico'
    )
    
    # Información adicional
    interpretation = fields.Text(
        string='Interpretación',
        help='Guía de interpretación clínica para este rango'
    )
    
    # Campos relacionados para facilitar búsquedas
    parameter_name = fields.Char(
        related='parameter_id.name',
        string='Nombre del Parámetro',
        store=True,
        readonly=True
    )
    
    parameter_code = fields.Char(
        related='parameter_id.code',
        string='Código del Parámetro',
        store=True,
        readonly=True
    )
    
    parameter_unit = fields.Char(
        related='parameter_id.unit',
        string='Unidad',
        readonly=True
    )
    
    @api.depends('parameter_id', 'gender', 'age_min', 'age_max', 'pregnant')
    def _compute_name(self):
        for record in self:
            if not record.parameter_id:
                record.name = 'Nuevo rango'
                continue
                
            parts = [record.parameter_id.name]
            
            # Agregar género si no es ambos
            if record.gender != 'both':
                gender_name = dict(self._fields['gender'].selection).get(record.gender, '')
                parts.append(gender_name)
            
            # Agregar rango de edad
            if record.age_min == 0 and record.age_max == 150:
                parts.append('Todas las edades')
            else:
                parts.append(f"{record.age_min}-{record.age_max} años")
            
            # Agregar indicador de embarazo
            if record.pregnant:
                parts.append('Embarazada')
            
            record.name = ' - '.join(parts)
    
    @api.constrains('age_min', 'age_max')
    def _check_age_range(self):
        for record in self:
            if record.age_min < 0:
                raise ValidationError('La edad mínima no puede ser negativa.')
            if record.age_max < record.age_min:
                raise ValidationError('La edad máxima debe ser mayor o igual a la edad mínima.')
            if record.age_max > 150:
                raise ValidationError('La edad máxima no puede ser mayor a 150 años.')
    
    @api.constrains('normal_min', 'normal_max')
    def _check_normal_range(self):
        for record in self:
            if record.normal_min and record.normal_max and record.normal_min > record.normal_max:
                raise ValidationError('El valor normal mínimo debe ser menor o igual al valor normal máximo.')
    
    @api.constrains('critical_min', 'critical_max', 'normal_min', 'normal_max')
    def _check_critical_range(self):
        for record in self:
            # Validar que crítico mínimo sea menor que normal mínimo
            if record.critical_min and record.normal_min and record.critical_min > record.normal_min:
                raise ValidationError('El valor crítico mínimo debe ser menor o igual al valor normal mínimo.')
            
            # Validar que crítico máximo sea mayor que normal máximo
            if record.critical_max and record.normal_max and record.critical_max < record.normal_max:
                raise ValidationError('El valor crítico máximo debe ser mayor o igual al valor normal máximo.')
    
    @api.constrains('gender', 'pregnant')
    def _check_pregnant_gender(self):
        for record in self:
            if record.pregnant and record.gender == 'male':
                raise ValidationError('No se puede marcar "Embarazada" para rangos masculinos.')
    
    @api.constrains('parameter_id', 'gender', 'age_min', 'age_max', 'pregnant')
    def _check_unique_range(self):
        for record in self:
            # Buscar rangos duplicados
            domain = [
                ('parameter_id', '=', record.parameter_id.id),
                ('gender', '=', record.gender),
                ('age_min', '=', record.age_min),
                ('age_max', '=', record.age_max),
                ('pregnant', '=', record.pregnant),
                ('id', '!=', record.id)
            ]
            
            if self.search_count(domain) > 0:
                raise ValidationError('Ya existe un rango con estas mismas condiciones para este parámetro.')
    
    def is_value_normal(self, value):
        """Verifica si un valor está dentro del rango normal"""
        self.ensure_one()
        if not value or not self.normal_min or not self.normal_max:
            return True
        return self.normal_min <= value <= self.normal_max
    
    def is_value_critical(self, value):
        """Verifica si un valor está en rango crítico"""
        self.ensure_one()
        if not value:
            return False
        
        # Crítico por debajo
        if self.critical_min and value < self.critical_min:
            return True
        
        # Crítico por encima
        if self.critical_max and value > self.critical_max:
            return True
        
        return False
    
    def get_value_status(self, value):
        """Devuelve el estado del valor: 'normal', 'abnormal', 'critical'"""
        self.ensure_one()
        if not value:
            return 'normal'
        
        if self.is_value_critical(value):
            return 'critical'
        elif not self.is_value_normal(value):
            return 'abnormal'
        else:
            return 'normal'