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

class FptcModel(models.Model):
    _name = 'sos_fptc'
    _description = 'Finished Product Transfer Challan'
    _rec_name="fptc_no"
    _order = 'id desc' 
    
    plan_ref_no = fields.Many2one('sos_fg_plan',
        string='Indent No'
    )
    fptc_no = fields.Char(string="FPTC No",default=lambda self: self._generate_id(),readonly= True, required= True)
    fg_name = fields.Many2many('sos_fg', string='FG Name')
    sfg_name = fields.Many2one('sos_sfg', string='SFG Name')
    planned_qty = fields.Integer(string="Planned Qty")
    line_ids = fields.One2many('sos_fptc_line', 'fptc_id', string="Finished Goods",copy=True, ondelete='cascade')
    indent_start_date = fields.Date(string="Indent Started On")
    indent_target_date = fields.Date(string="Indent Target On")
    stores_to_production_lines= fields.One2many('sos_fptc_store_to_production', 'fptc_id',string="")
    customer_name = fields.Many2one('sos_inventory_customers', string="Customer Name")
    deliverables_ref_no = fields.Many2one('sos_deliverables_boq',string="Deliverables/BOQ Reference")
    production_witness_name = fields.Many2one('res.users')
    production_witness_image = fields.Image(related="production_witness_name.signature_image",readonly=True)
    production_witness_approved_on = fields.Datetime(string="Approved On")
    qc_witness_name = fields.Many2one('res.users')
    qc_witness_image = fields.Image(related="qc_witness_name.signature_image",readonly=True)
    qc_witness_approved_on = fields.Datetime(string="Approved On")
    stores_witness_name = fields.Many2one('res.users')
    stores_witness_image = fields.Image(related="stores_witness_name.signature_image",readonly=True)
    stores_witness_approved_on = fields.Datetime(string="Approved On")


    def action_production_esign_btn(self):
        sequence_util = self.env['sos_common_scripts']
        sequence_util.action_assign_signature(
        self, 
        'production_witness_name',
        'production_witness_approved_on',
        'sos_inventory.sos_production_user'
    )
    def action_stores_esign_btn(self):
        sequence_util = self.env['sos_common_scripts']
        sequence_util.action_assign_signature(
        self, 
        'stores_witness_name',
        'stores_witness_approved_on',
        'sos_inventory.sos_scg_group_user'
    )
    def action_qc_esign_btn(self):
        sequence_util = self.env['sos_common_scripts']
        sequence_util.action_assign_signature(
        self, 
        'qc_witness_name',
        'qc_witness_approved_on',
        'sos_inventory.sos_qc_user'
    )

  
    

    def _generate_id(self):
        sequence_util = self.env['sos_common_scripts']
        return sequence_util.generate_sequence('sos_fptc','FPTC', 'fptc_no')
    
    def action_report_fptc_btn(self):
        try:
            action = self.env.ref("sos_inventory.action_report_fptc").report_action(self)
            return action
        except ValueError as e:
            print(f"Failed to find report action: {e}")
class Stores_to_Production(models.Model):
    _name = 'sos_fptc_store_to_production'
    _description = 'Stores to Production Lines'

    fptc_id = fields.Many2one('sos_fptc')
    fg_name = fields.Many2one('sos_fg', string='FG Name')
    batch_no = fields.Char(string="Batch No")
    serial_no=fields.Text(string="Serial No")
    from_dept = fields.Selection([('production', 'Production'),('stores', 'Stores')], string="From Department",default="stores")
    stores_to_production_transfer_qty = fields.Integer(
        string="Transfer Quantity", compute="_compute_transfer_qty", store=True, readonly=False
    )    
    stores_to_production_transfer_on=fields.Date(string="Transfered On")
    available_fg_names = fields.Many2many('sos_fg', compute="_compute_available_fg_names", store=False)
    send_to_production_btn_display = fields.Boolean(default=True)
    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['serial_no'] = self._expand_serial_numbers(vals['serial_no'])
        return super(Stores_to_Production, 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(Stores_to_Production, 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.stores_to_production_transfer_qty = len(serial_list)  # Count valid serials
            else:
                record.stores_to_production_transfer_qty = 0  # If no serials, set to 0
    @api.depends("fptc_id")
    def _compute_available_fg_names(self):
        for record in self:
            if record.fptc_id:
                fg_ids = record.fptc_id.fg_name.ids
                record.available_fg_names = [(6, 0, fg_ids)]
                
                # Auto-select FG name only if exactly one exists
                if len(fg_ids) == 1:
                    record.fg_name = fg_ids[0]
                # Don't reset if multiple exist; let user select
            else:
                record.available_fg_names = [(6, 0, [])]
                record.fg_name = False  # Clear selection only if no options exist
    @api.onchange('fptc_id')
    def _onchange_fptc_id(self):
        if self.fptc_id and len(self.fptc_id.fg_name) == 1:
            self.fg_name = self.fptc_id.fg_name.id
        else:
            self.fg_name = False
    def send_to_production_btn(self):
        new_record = self.fptc_id.line_ids
        new_record.create({
            'fptc_id': self.fptc_id.id,
            'batch_no' : self.batch_no,
            'serial_no' : self.serial_no,
            'fg_name' : self.fg_name.id,
            'production_to_qc_transfer_qty':self.stores_to_production_transfer_qty

        })
        self.send_to_production_btn_display = False
        body_html = f"""
            <p>Below <b>FPTC</b> is waiting for your response</p>
            """
            
        send_email = self.env['sos_common_scripts']
        send_email.send_group_email(self.env,"sos_fptc",self.id,"deenalaura.m@sosaley.in","Transfer Challan Received",body_html,'sos_inventory.sos_production_user')
        return {
                    'type': 'ir.actions.client',
                    'tag': 'display_notification',
                    'params': {
                        'message': "Moved to Production",
                        'type': 'success',
                        'sticky': False
                    }
                }
class FptcModel_Line(models.Model):
    _name = 'sos_fptc_line'
    _description = 'FPTC Lines'

    fptc_id = fields.Many2one('sos_fptc')
    fg_name = fields.Many2one('sos_fg',string="FG Name")
    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")
    qc_report = fields.Many2one('sos_fir_brr')
    fir_qc_report = fields.Many2one('sos_fir')
    production_to_qc_transfer_qty=fields.Integer(string="Transfer Quantity")
    production_to_qc_transfer_by = fields.Many2one('res.users',string='Production to QC By')
    production_to_qc_transfer_on = fields.Date(string="Production to QC Transfered On")
    qc_to_stores_transfer_qty=fields.Integer(string="Approved Quantity")
    qc_to_stores_rejected_qty=fields.Integer(string="Rejected Quantity")
    qc_to_stores_transfer_by = fields.Many2one('res.users',string='QC to Stores By')
    qc_to_stores_transfer_on = fields.Date(string="QC to Stores Transfered On")
    stores_received_by = fields.Many2one('res.users',string='Stores Received by')
    stores_received_on = fields.Date(string="Stores Received On")
    from_dept = fields.Selection([('production', 'Production'),('stores', 'Stores')], string="From Department",default="production")
    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")
    available_fg_names = fields.Many2many('sos_fg', compute="_compute_available_fg_names", store=False)
    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):
    #     """Create multiple rows in `sos_serial_nos` for each serial number in the list"""
    #     res = super(FptcModel_Line, self).create(vals)  # Create the main record first
    #     res._update_serial_numbers()  # Call helper method to insert serials
    #     return res

    # def write(self, vals):
    #     """Update related serial numbers in `sos_serial_nos` when this record is modified"""
    #     res = super(FptcModel_Line, self).write(vals)  # Update the main record first
    #     if 'serial_no' in vals or 'batch_no' in vals or 'fg_name' in vals:
    #         self._update_serial_numbers()  # Call helper method to update serials
    #     return res

    # def unlink(self):
    #     """Delete associated serial numbers when this record is deleted"""
    #     for record in self:
    #         self.env['sos_serial_nos'].search([
    #             ('batch_no', '=', record.batch_no),
    #             ('fg_name', '=', record.fg_name.id)
    #         ]).unlink()
        
    #     return super(FptcModel_Line, self).unlink()

    # def _update_serial_numbers(self):
    #     """Helper function to update serial numbers in `sos_serial_nos`"""
    #     for record in self:
    #         # Remove old serial numbers before inserting new ones
    #         self.env['sos_serial_nos'].search([
    #             ('batch_no', '=', record.batch_no),
    #             ('fg_name', '=', record.fg_name.id)
    #         ]).unlink()

    #         if record.serial_no:
    #             serial_numbers = record.serial_no.split('\n')  # Split serial numbers into a list

    #             # Create separate rows in sos_serial_nos for each serial number
    #             for serial in filter(None, map(str.strip, serial_numbers)):  # Removes empty lines & spaces
    #                 self.env['sos_serial_nos'].create({
    #                     'customer_name': record.fptc_id.customer_name,
    #                     'fg_name': record.fg_name.id,
    #                     'serial_no': serial,  # Each row gets a single serial number
    #                     'batch_no': record.batch_no
    #                 })
   
    @api.depends("fptc_id")
    def _compute_available_fg_names(self):
        for record in self:
            if record.fptc_id:
                fg_ids = record.fptc_id.fg_name.ids
                record.available_fg_names = [(6, 0, fg_ids)]
                
                # Auto-select FG name only if exactly one exists
                if len(fg_ids) == 1:
                    record.fg_name = fg_ids[0]
            else:
                record.available_fg_names = [(6, 0, [])]
                record.fg_name = False  # Clear selection only if no options exist
    
    
    def send_to_qc_btn(self):
        self.production_to_qc_transfer_by = self.env.user.id
        
        sequence_util = self.env['sos_common_scripts']
        if self.fptc_id.plan_ref_no:
            week_number = sequence_util.calculate_week_number(
                self.fptc_id.indent_start_date,
                self.fptc_id.indent_target_date,
                date.today()
            )
            field_name = f'actual_week_{week_number}'

            sos_record = self.env['sos_production_plan'].search([
                ('fg_name', '=', self.fg_name.id),
                ('plan_ref_no', '=', self.fptc_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})
        #end production status update


        return {
                    'type': 'ir.actions.client',
                    'tag': 'display_notification',
                    'params': {
                        'message': "Moved to QC For Inspection",
                        'type': 'success',
                        'sticky': False
                    }
                }
class Fptc_Serial_lines(models.Model):
    _name = 'sos_serial_nos'
    _description = 'Batch & Serial Numbers'

    fg_name = fields.Many2one('sos_fg',string="FG Name")
    customer_name = fields.Many2one('sos_inventory_customers', string="Customer Name")
    serial_no = fields.Char(string="Serial No")
    batch_no = fields.Char(string="Batch No")
    delivery_date = fields.Date(string="Delivery Date")