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

_logger = logging.getLogger(__name__)

class SaleOrder(models.Model):
    _inherit = 'sale.order'

    is_lab_request = fields.Boolean(
        string="Es Orden de Laboratorio",
        default=False,
        copy=False,
        help="Campo técnico para identificar si la orden de venta es una solicitud de laboratorio."
    )
    
    doctor_id = fields.Many2one(
        'res.partner',
        string="Médico Referente",
        domain="[('is_doctor', '=', True)]",
        help="El médico que refirió al paciente para esta solicitud de laboratorio."
    )
    
    generated_sample_ids = fields.Many2many(
        'stock.lot',
        'sale_order_stock_lot_rel',
        'order_id',
        'lot_id',
        string='Muestras Generadas',
        domain="[('is_lab_sample', '=', True)]",
        readonly=True,
        help="Muestras de laboratorio generadas automáticamente cuando se confirmó esta orden"
    )
    
    def action_confirm(self):
        """Override to generate laboratory samples and tests automatically"""
        res = super(SaleOrder, self).action_confirm()
        
        # Generate samples and tests only for laboratory requests
        for order in self.filtered('is_lab_request'):
            try:
                order._generate_lab_samples()
                order._generate_lab_tests()
            except Exception as e:
                _logger.error(f"Error generating samples/tests for order {order.name}: {str(e)}")
                # Continue with order confirmation even if generation fails
                # But notify the user
                order.message_post(
                    body=_("Error al generar muestras/pruebas automáticamente: %s. "
                          "Por favor, genere las muestras y pruebas manualmente.") % str(e),
                    message_type='notification'
                )
        
        return res
    
    def _generate_lab_samples(self):
        """Generate laboratory samples based on the analyses in the order"""
        self.ensure_one()
        _logger.info(f"Generating laboratory samples for order {self.name}")
        
        # Group analyses by sample type
        sample_groups = self._group_analyses_by_sample_type()
        
        if not sample_groups:
            _logger.warning(f"No analyses with sample types found in order {self.name}")
            return
        
        # Create samples for each group
        created_samples = self.env['stock.lot']
        
        for sample_type_id, group_data in sample_groups.items():
            sample = self._create_sample_for_group(group_data)
            if sample:
                created_samples |= sample
        
        # Link created samples to the order
        if created_samples:
            self.generated_sample_ids = [(6, 0, created_samples.ids)]
            _logger.info(f"Created {len(created_samples)} samples for order {self.name}")
            
            # Post message with created samples
            sample_list = "<ul>"
            for sample in created_samples:
                sample_list += f"<li>{sample.name} - {sample.sample_type_product_id.name}</li>"
            sample_list += "</ul>"
            
            self.message_post(
                body=_("Muestras generadas automáticamente: %s") % sample_list,
                message_type='notification'
            )
    
    def _group_analyses_by_sample_type(self):
        """Group order lines by required sample type"""
        groups = {}
        
        for line in self.order_line:
            product = line.product_id
            
            # Skip non-analysis products
            if not product.is_analysis:
                continue
            
            # Check if analysis has a required sample type
            if not product.required_sample_type_id:
                _logger.warning(
                    f"Analysis {product.name} has no required sample type defined"
                )
                # Post warning message
                self.message_post(
                    body=_("Advertencia: El análisis '%s' no tiene tipo de muestra definido") % product.name,
                    message_type='notification'
                )
                continue
            
            sample_type = product.required_sample_type_id
            
            # Initialize group if not exists
            if sample_type.id not in groups:
                groups[sample_type.id] = {
                    'sample_type': sample_type,
                    'lines': [],
                    'total_volume': 0.0,
                    'analyses': []
                }
            
            # Add line to group
            groups[sample_type.id]['lines'].append(line)
            groups[sample_type.id]['analyses'].append(product.name)
            groups[sample_type.id]['total_volume'] += (product.sample_volume_ml or 0.0) * line.product_uom_qty
        
        return groups
    
    def _create_sample_for_group(self, group_data):
        """Create a single sample for a group of analyses"""
        try:
            sample_type = group_data['sample_type']
            
            # Generate a unique lot name using sequence
            sequence = self.env['ir.sequence'].next_by_code('stock.lot.serial')
            if not sequence:
                # Fallback to timestamp-based name if no sequence exists
                import time
                sequence = 'LAB-' + str(int(time.time()))[-8:]
            
            # Prepare sample values
            vals = {
                'name': sequence,  # Add the lot name
                'product_id': sample_type.product_variant_id.id,
                'patient_id': self.partner_id.id,
                'doctor_id': self.doctor_id.id if self.doctor_id else False,
                'origin': self.name,
                'sample_type_product_id': sample_type.id,
                'volume_ml': group_data['total_volume'],
                'is_lab_sample': True,
                'state': 'pending_collection',
                'analysis_names': ', '.join(group_data['analyses'][:3]) + 
                                ('...' if len(group_data['analyses']) > 3 else '')
            }
            
            # Create the sample
            sample = self.env['stock.lot'].create(vals)
            
            _logger.info(
                f"Created sample {sample.name} for {len(group_data['analyses'])} analyses"
            )
            
            return sample
            
        except Exception as e:
            _logger.error(f"Error creating sample: {str(e)}")
            raise UserError(
                _("Error al crear muestra para %s: %s") % (sample_type.name, str(e))
            )
    
    def _generate_lab_tests(self):
        """Generate laboratory tests for analysis order lines"""
        self.ensure_one()
        _logger.info(f"Generating laboratory tests for order {self.name}")
        
        # Get the test model
        TestModel = self.env['lims.test']
        created_tests = TestModel.browse()
        
        # Create a test for each analysis line
        for line in self.order_line:
            if not line.product_id.is_analysis:
                continue
            
            # Find appropriate sample for this analysis
            sample = self._find_sample_for_analysis(line.product_id)
            
            if not sample:
                _logger.warning(
                    f"No sample found for analysis {line.product_id.name} in order {self.name}"
                )
                self.message_post(
                    body=_("Advertencia: No se encontró muestra para el análisis '%s'") % line.product_id.name,
                    message_type='notification'
                )
                continue
            
            # Create the test
            try:
                test = TestModel.create({
                    'sale_order_line_id': line.id,
                    'sample_id': sample.id,
                })
                created_tests |= test
                _logger.info(f"Created test {test.name} for analysis {line.product_id.name}")
            except Exception as e:
                _logger.error(f"Error creating test for {line.product_id.name}: {str(e)}")
                self.message_post(
                    body=_("Error al crear prueba para '%s': %s") % (line.product_id.name, str(e)),
                    message_type='notification'
                )
        
        # Post message with created tests
        if created_tests:
            test_list = "<ul>"
            for test in created_tests:
                test_list += f"<li>{test.name} - {test.product_id.name}</li>"
            test_list += "</ul>"
            
            self.message_post(
                body=_("Pruebas generadas automáticamente: %s") % test_list,
                message_type='notification'
            )
            _logger.info(f"Created {len(created_tests)} tests for order {self.name}")
    
    def _find_sample_for_analysis(self, product):
        """Find the appropriate sample for an analysis product"""
        # Check if the analysis has a required sample type
        if not product.required_sample_type_id:
            return False
        
        # Find a generated sample with matching sample type
        for sample in self.generated_sample_ids:
            if sample.sample_type_product_id.id == product.required_sample_type_id.id:
                return sample
        
        return False
