from odoo import models, fields, api
from datetime import date,datetime
from odoo.exceptions import ValidationError,UserError
import re

class SOS_TC(models.Model):
    _name = 'sos_transfer_challan'
    _description = 'Transfer Challan'
    _rec_name="tc_no"
    _order = 'tc_no desc' 
    
    plan_ref_no = fields.Char(
        readonly=False,string='Indent No'
    )
    tc_no = fields.Char(string="TC No",default=lambda self: self._generate_id(),readonly= True, required= True)
    fg_name = fields.Many2one('sos_fg', string='FG Name')
    product_name = fields.Char(related="fg_name.name", string='Product Name',readonly=True)
    sfg_name = fields.Many2one('sos_sfg', string='SFG Name')
    planned_qty = fields.Integer(string="Planned Qty")
    line_ids = fields.One2many('sos_transfer_challan_line', 'tc_id', string="Finished Goods",copy=True, ondelete='cascade')
    tc_status = fields.Selection([ ('open', 'Open'),('close', 'Closed')], default='open' , string="Status")
    indent_start_date = fields.Date(string="Indent Started On")
    indent_target_date = fields.Date(string="Indent Target On")
    sfg_option = fields.Boolean('Semi-Finished Goods')
    fg_option = fields.Boolean('Finished Goods', default=True)
    indent_no  = fields.Many2one('sos_fg_plan', string='Ref No')
    specification_line_ids = fields.One2many('sos_transfer_challan_specification_lines', 'specification_id',copy=True) 
    @api.onchange('fg_name')
    def _onchange_fg_name(self):
        if self.fg_name:
            specifications = self.env['sos_testing_parameters'].search([('fg_name', '=', self.fg_name.id)], limit=1)
            if not specifications:
                raise UserError('No specifications found for this Item.')
                        
            lines = [(5, 0, 0)] 
            for param in specifications.specification_ids:
                lines.append((0, 0, {
                    'specification': param.name,
                    'specification_value': ''
                }))
            self.specification_line_ids = lines
    @api.onchange('sfg_option')
    def _onchange_sfg_option(self):
        if self.sfg_option:
            self.fg_option = False
    @api.onchange('fg_option')
    def _onchange_fg_option(self):
        if self.fg_option:
            self.sfg_option = False
  
    # @api.depends('fg_name')
    # def _compute_specifications(self):
    #     for record in self:
    #         if record.fg_name:
    #             try:
    #                 specifications = self.env['sos_testing_parameters'].search([('fg_name', '=', record.fg_name.id)])
    #                 if not specifications:
    #                     continue
    #                 lines = [(5, 0, 0)] 
    #                 for param in specifications.specification_ids:
    #                     lines.append((0, 0, {
    #                         'specification': param.id
    #                     }))
    #                 record.line_ids = lines
    #             except Exception as e:
    #                 _logger.error("Error processing specifications for FG %s: %s", record.fg_name.name, str(e))
    #                 continue 
    # def _inverse_specifications(self):
    #     for record in self:
    #         for line in record.line_ids:
    #             line.write({
    #                 'specification_value': line.specification_value
    #             })


    def _generate_id(self):
        sequence_util = self.env['sos_common_scripts']
        return sequence_util.generate_sequence('sos_transfer_challan','TC', 'tc_no')
    
    def action_report_tc_btn(self):
        try:
            action = self.env.ref("sos_inventory.action_report_tc").report_action(self)
            return action
        except ValueError as e:
            print(f"Failed to find report action: {e}")

class TC_Model_Line(models.Model):
    _name = 'sos_transfer_challan_line'
    _description = 'tc Lines'

    tc_id = fields.Many2one('sos_transfer_challan')
    sfg_option = fields.Boolean(related="tc_id.sfg_option",string='Semi-Finished Goods')
    fg_option = fields.Boolean(related="tc_id.fg_option",string='Finished Goods', default=True)
    specification = fields.Many2one('sos_specification', string='Specification Name')
    specification_value = fields.Char(string="Value")
    batch_no = fields.Char(string="Batch No")
    serial_no=fields.Text(string="Serial No",required=True)
    remarks=fields.Text(string="Remarks")
    qc_report = fields.Many2one('sos_fir_brr')
    production_to_qc_transfer_qty=fields.Integer(string="Transfer Quantity", compute="_compute_transfer_qty", store=True, readonly=False)    
    production_to_qc_transfer_by = fields.Many2one('res.users',string='Production to QC By',readonly=True)
    production_to_qc_transfer_on = fields.Date(string="Production to QC Transfered On")
    qc_to_stores_transfer_qty=fields.Integer(string="Approved Quantity",related="qc_report.approved_qty")
    qc_to_stores_rejected_qty=fields.Integer(string="Rejected Quantity",related="qc_report.rejected_qty")
    qc_to_stores_transfer_by = fields.Many2one('res.users',string='QC to Stores By',related="qc_report.qc_by_name")
    qc_to_stores_transfer_on = fields.Date(string="QC to Stores Transfered On",related="qc_report.qc_tested_on")
    stores_received_by = fields.Many2one('res.users',string='Stores Received by',related="qc_report.stores_received_by")
    stores_received_on = fields.Date(string="Stores Received On",related="qc_report.stores_received_on")
    sfg_qc_report = fields.Many2one('sos_iqi')
    sfg_qc_to_stores_transfer_qty=fields.Integer(string="Approved Quantity",related="sfg_qc_report.approved_qty")
    sfg_qc_to_stores_rejected_qty=fields.Integer(string="Rejected Quantity",related="sfg_qc_report.rejected_qty")
    sfg_stores_received_by = fields.Many2one('res.users',string='Stores Received by',related="sfg_qc_report.stores_received_by")
    sfg_stores_received_on = fields.Date(string="Stores Received On",related="sfg_qc_report.stores_received_on")
    sfg_qc_to_stores_transfer_by = fields.Many2one('res.users',string='QC to Stores By',related="sfg_qc_report.qc_by_name")
    sfg_qc_to_stores_transfer_on = fields.Date(string="QC to Stores Transfered On",related="sfg_qc_report.qc_tested_on")

    show_serial = fields.Boolean(default=True)
    def toggle_serial(self):
        for record in self:
            record.show_serial = not record.show_serial
    @api.model
    def create(self, vals):
        """Expand serial number ranges before saving"""
        if 'serial_no' in vals and vals['serial_no']:
            vals['show_serial'] = False
            vals['serial_no'] = self._expand_serial_numbers(vals['serial_no'])
        return super(TC_Model_Line, self).create(vals)

    def write(self, vals):
        """Expand serial number ranges on update"""
        if 'serial_no' in vals and vals['serial_no']:
            vals['serial_no'] = self._expand_serial_numbers(vals['serial_no'])
        return super(TC_Model_Line, self).write(vals)

    def _expand_serial_numbers(self, serial_text):
        """Convert serial number ranges into individual serial numbers only if 'to' is found"""
        lines = serial_text.split("\n")
        expanded_serials = []

        for line in lines:
            line = line.strip()
            if "to" in line:  # Process only if 'to' is present
                match = re.match(r"^(.+?)-(\d+)\s+to\s+(.+?)-(\d+)$", line)  # Match range format

                if match:
                    prefix1, start_num, prefix2, end_num = match.groups()

                    if prefix1 == prefix2:  # Ensure both prefixes are the same
                        start_num, end_num = int(start_num), int(end_num)

                        for num in range(start_num, end_num + 1):
                            expanded_serials.append(f"{prefix1}-{num:03d}")  # Format with leading zeros
                    else:
                        expanded_serials.append(line)  # Keep original if prefixes don't match
                else:
                    expanded_serials.append(line)  # Keep as is if not a valid range
            else:
                expanded_serials.append(line)  # Keep original if 'to' is not present

        return "\n".join(expanded_serials)  # Return expanded serials as multiline text

    @api.depends("serial_no")
    def _compute_transfer_qty(self):
        """Compute Transfer Quantity based on number of serial numbers entered, but allow manual override"""
        for record in self:
            if record.serial_no:
                serial_list = list(filter(None, map(str.strip, record.serial_no.split("\n"))))  # Remove empty lines & spaces
                record.production_to_qc_transfer_qty = len(serial_list)  # Count valid serials
            else:
                record.production_to_qc_transfer_qty = 0  # If no serials, set to 0
    def send_to_qc_btn(self):
        if self.production_to_qc_transfer_by:
            return
        sequence_util = self.env['sos_common_scripts']
        
        plan_ref_no = self.env['sos_fg_plan'].search([('plan_ref_no', '=', self.tc_id.plan_ref_no)], limit=1)
        brr_model = self.env['sos_fir_brr']
        brr_record = brr_model.create({
                    'fg_name': self.tc_id.fg_name.id,
                    'fir_date':self.production_to_qc_transfer_on,
                    'batch_size':self.production_to_qc_transfer_qty,
                    'sampling_size':self.production_to_qc_transfer_qty,
                    'plan_ref_no':plan_ref_no.id if plan_ref_no else '',
                    'batch_No':self.batch_no,
                    'fir_no': sequence_util.generate_sequence('sos_fir_brr','BRR', 'fir_no'),
                    
                    
                })
        if brr_record:
            serial_numbers = self.serial_no.split('\n')  # Split serial numbers into a list

            for serial in filter(None, map(str.strip, serial_numbers)):  # Removes empty lines & spaces
                self.env['sos_brr_serial_no_lines'].create({
                    'ref_id': brr_record.id,
                    'serial_no': serial,  # Each row gets a single serial number
                    'inspection_decision':'PASS'
                })
            # Email part
            body_html = f"""
            <p>Below <b>BRR</b> is waiting for Quality Inspection</p>
            """
            sequence_util.send_group_email(self.env,"sos_fir_brr", brr_record.id,"deenalaura.m@sosaley.in","BRR Inspection Request",body_html,'sos_inventory.sos_qc_user')

            # Email part ends
        self.production_to_qc_transfer_by = self.env.user.id
        sequence_util = self.env['sos_common_scripts']
        if self.tc_id.fg_option and self.tc_id.plan_ref_no:
            week_number = sequence_util.calculate_week_number(
                self.tc_id.indent_start_date,
                self.tc_id.indent_target_date,
                self.production_to_qc_transfer_on
            )
            field_name = f'actual_week_{week_number}'

            sos_record = self.env['sos_production_plan'].search([
                ('fg_name', '=', self.tc_id.fg_name.id),
                ('plan_ref_no', '=', self.tc_id.plan_ref_no)
            ], limit=1)

            if sos_record:
                current_value = getattr(sos_record, field_name, 0)
                sos_record.write({field_name: current_value + self.production_to_qc_transfer_qty})
                self.env['sos_transfer_challan_summary_lines'].create({
                    'ref_id': sos_record.id,
                    'name': self.env.user.id,
                    'date':self.production_to_qc_transfer_on,
                    'quantity':self.production_to_qc_transfer_qty
                })
        return {
                    'type': 'ir.actions.client',
                    'tag': 'display_notification',
                    'params': {
                        'message': "Moved to QC For Inspection",
                        'type': 'success',
                        'sticky': False
                    }
                }
class TC_Model_Spec_Line(models.Model):
    _name = 'sos_transfer_challan_specification_lines'
    _description = 'tc Lines'

    specification_id = fields.Many2one('sos_transfer_challan')
    specification = fields.Char(string="Specification")
    specification_value = fields.Char(string="Value")