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

class FIR_Only(models.Model):
    _name = 'sos_fir'
    _description = 'Final Inspection Report'
    _rec_name='fir_no'
    _order = 'id desc'

    fir_no = fields.Char(string="FIR No",default=lambda self: self._generate_id(),readonly= True, required= True)
    fir_date = fields.Date(string="FIR Date")
    fg_name = fields.Many2many('sos_fg', string='FG Name')
    product_type = fields.Selection(
            [
               ('BHMS 1.2V', 'BHMS 1.2V'), 
                ('BHMS 2V', 'BHMS 2V'), 
                ('BHMS 12V', 'BHMS 12V'),  
                ('BHMS 48V', 'BHMS 48V'),
                ('BMS-HV', 'BMS-HV'),
                ('BMS-LV 100A', 'BMS-LV 100A'), 
                ('BMS-LV 40A', 'BMS-LV 40A'), 
                ('SBMS 55A', 'SBMS 55A'),              
                ('MC 250W', 'MC 250W'),                                
                ('HeartTarang', 'HeartTarang')                   
            ],
            string="Product Name")
    plan_ref_no = fields.Many2one('sos_fg_plan', string='Indent Ref No')
    batch_size = fields.Integer(string="Batch Size / Received Quantity")
    batch_No = fields.Char(string="Batch No")
    serial_no = fields.Char(string="Serial No")
    mfg_date = fields.Char(string="Manufacturing Date")
    sampling_size = fields.Integer(string="Sampling Size")
    calibration_line_ids = fields.One2many('sos_calibration_devices_fir_only', 'ref_id',copy=True)
    testing_parameter_line_ids = fields.One2many('sos_fir_line', 'ref_line_id',copy=True)
    approved_qty = fields.Integer(string="Approved Quantity")
    rejected_qty = fields.Integer(string="Rejected Quantity")
    rejection_percentage = fields.Float(string="Rejected Percentage", compute="_compute_rejected_percentage", store=True)
    rejection_percentage_display = fields.Char('Rejection Percentage', compute='_compute_rejected_percentage_display')
    qc_by_name = fields.Many2one('res.users', string='QC Tested&Provided by Sign')
    qc_by_image = fields.Image(related="qc_by_name.signature_image",string='Prepared by Sign',readonly=True)
    qc_tested_on = fields.Date(string="Approved On")
    reworked_count = fields.Integer(string="Reworked Count",default=0)
    qa_by_name = fields.Many2one('res.users', string='QA by Sign')
    qa_by_image = fields.Image(related="qa_by_name.signature_image",string='Prepared by Sign',readonly=True)
    qa_tested_on = fields.Date(string="Approved On")
    ppm = fields.Integer(string="PPM",compute="_compute_ppm")
    stores_received_by = fields.Many2one('res.users', string='Store Received by Sign')
    stores_received_image = fields.Image(related="stores_received_by.signature_image",string='Stores Received by Sign',readonly=True)
    stores_received_on = fields.Date(string="Stores Received On")
    ncmr_ref = fields.Many2one('sos_ncmr',string="NCMR Reference (If any Rejected)")
    customer_name = fields.Many2one('sos_inventory_customers', string="Customer Name", required=True)
    remarks = fields.Text(string="Remarks")
    test_log = fields.Binary("Test Log", required=False, attachment=True)
    test_log_filename = fields.Char("Test Log Filename")
    rejected_line_ids = fields.One2many('sos_fir_rejected_lines', 'ref_id', string="Finished Goods",copy=True, ondelete='cascade')
    serial_no_line_ids = fields.One2many('sos_fir_serial_no_lines', 'ref_id',copy=True)
    sd_card_data = fields.Binary("SD Card Data", required=False, attachment=True)
    sd_card_data_filename = fields.Char("SD Card Data Filename")
    cloud_data = fields.Binary("Cloud Data", required=False, attachment=True)
    cloud_data_filename = fields.Char("Cloud Data Filename")
    firmware_data = fields.Binary("Firmware Data", required=False, attachment=True)
    firmware_data_filename = fields.Char("Firmware Data Filename")
    serial_no_parse = fields.Text(string="Serial no's to parse")
    def parse_serial_nos(self):
        self.ensure_one()
        if not self.serial_no_parse:
            return

        # Split into clean serial numbers
        serial_numbers = [
            line.strip() for line in self.serial_no_parse.splitlines() if line.strip()
        ]

        SerialLine = self.env['sos_fir_serial_no_lines']

        for serial in serial_numbers:
            # Check if already exists for this ref_id
            exists = SerialLine.search([
                ('ref_id', '=', self.id),
                ('serial_no', '=', serial)
            ], limit=1)

            if not exists:
                SerialLine.create({
                    'ref_id': self.id,
                    'serial_no': serial,
                    'inspection_decision': 'PASS',  # default
                })


    @api.onchange('batch_size')
    def _onchange_batch_size(self):
        if self._origin and self.batch_size is not False:
            lines = self.env['sos_fir_line'].search([('ref_line_id', '=', self._origin.id)])
            line_values = [
                (1, line.id, {
                    'sampled_qty': self.batch_size,
                    'accepted_qty': self.batch_size
                }) for line in lines
            ]
            self.testing_parameter_line_ids = line_values

    @api.constrains('test_log_filename', 'sd_card_data_filename', 'cloud_data_filename', 'firmware_data_filename')
    def _check_file_extension(self):
        allowed_extensions = ['xlsx', 'xls', 'csv', 'zip', 'pdf']
        for record in self:
            for field_name in ['test_log_filename', 'sd_card_data_filename', 'cloud_data_filename','firmware_data_filename']:
                file_name = getattr(record, field_name)
                if file_name:
                    ext = file_name.split('.')[-1].lower()
                    if ext not in allowed_extensions:
                        raise ValidationError("Only .pdf, .xlsx, .xls, .csv, and .zip files are allowed!")
    def action_report_fir_btn(self):
        try:
            action = self.env.ref("sos_inventory.action_report_fir").report_action(self)
            return action
        except ValueError as e:
            print(f"Failed to find report action: {e}")
    @api.depends('batch_size', 'rejected_qty')
    def _compute_ppm(self):
        for record in self:
            if record.rejected_qty != 0:
                record.ppm = (record.rejected_qty / record.batch_size) * 10**6
            else:
                record.ppm = 0 
    @api.depends('rejection_percentage')
    def _compute_rejected_percentage_display(self):
        for record in self:
            record.rejection_percentage_display = "{:.2f}%".format(record.rejection_percentage)
    @api.depends('batch_size', 'rejected_qty')
    def _compute_rejected_percentage(self):
        for record in self:
            if record.batch_size > 0:
                record.rejection_percentage = (record.rejected_qty / record.batch_size) * 100
            else:
                record.rejection_percentage = 0
    def action_qc_esign_btn(self):          
        ncmr_record = False
        sequence_util = self.env['sos_common_scripts']
        ncmr_id = sequence_util.generate_sequence('sos_ncmr', 'NCMR', 'ncmr_no')
        if self.rejected_qty > 0:  
            for line in self.rejected_line_ids    :
                ncmr_record = self.env['sos_ncmr'].create({
                            'ncmr_no': ncmr_id,
                            'fg_option':True,
                            'material_option':False,
                            'sfg_option':False,
                            'batch_no':self.batch_No,
                            'rejected_qty':line.quantity,
                            'fg_name': line.fg_name.id,
                            'fir_incoming_doc_ref':self.id,
                            'department':'Quality Control'
                        })
                self.ncmr_ref = ncmr_record.id
                ncmr_body_html = f"""
                    <p>Below <b>NCMR</b> is waiting for your Inspection</p>
                    """
                sequence_util.send_group_email(self.env,'sos_ncmr',ncmr_id,"deenalaura.m@sosaley.in","NCMR Inspection Pending",ncmr_body_html,'sos_inventory.sos_qc_user')

        # Email part
        body_html = f"""
        <p>Below <b>Final Inspection Report</b> is waiting for your Approval</p>
        """
       
        sequence_util.send_group_email(self.env,"sos_fir",self.id,"deenalaura.m@sosaley.in","FIR Approval Request",body_html,'sos_inventory.sos_qa_user')

        # Email part ends
        return sequence_util.action_assign_signature(
        self, 
        'qc_by_name',
        'qc_tested_on'
    )
    def action_qa_esign_btn(self):
        # Email part
        body_html = f"""
        <p>Below <b>FIR</b> is waiting for your Approval</p>
        """
        
        send_email = self.env['sos_common_scripts']
        send_email.send_group_email(self.env,"sos_fir",self.id,"deenalaura.m@sosaley.in","FIR Approval Request",body_html,'sos_inventory.sos_scg_group_user')
        # Email part ends
        sequence_util = self.env['sos_common_scripts']
        return sequence_util.action_assign_signature(
        self, 
        'qa_by_name',
        'qa_tested_on'
    )
    def action_stores_esign_btn(self):
        for serial in self.serial_no_line_ids: 
            self.env['sos_serial_nos'].create({
                     'customer_name': self.customer_name.id,
                    #  'fg_name': self.fg_name.id,
                     'serial_no': serial.serial_no,  
                     'batch_no': self.batch_No,
                     'delivery_date': fields.Date.today()
            })
        sequence_util = self.env['sos_common_scripts']
        sequence_util.action_assign_signature(
        self, 
        'stores_received_by',
        'stores_received_on',
        'sos_inventory.sos_scg_group_user'
    )

        
    def _generate_id(self):
        sequence_util = self.env['sos_common_scripts']
        return sequence_util.generate_sequence('sos_fir','FIR', 'fir_no')
    
    @api.onchange('product_type')
    def _onchange_product_type(self):
        if self.product_type:
            self._load_testing_parameters()

    # @api.model
    # def create(self, vals):
    #     record = super(FIR_Only, self).create(vals)
    #     if record.product_type:
    #         record._load_testing_parameters()
    #     return record

    # def write(self, vals):
    #     result = super(FIR_Only, self).write(vals)
    #     if 'product_type' in vals:
    #         self._load_testing_parameters()
    #     return result

    def _load_testing_parameters(self):
        if self.product_type:
            testing_parameters = self.env['sos_fir_testing_parameters'].search([('product_type', '=', self.product_type)])
            if not testing_parameters:
                raise UserError('No testing parameters found for this Product.')

            # Clear any existing lines
            lines = [(5, 0, 0)]

            sorted_parameters = testing_parameters.fir_parameter_ids.sorted(key=lambda param: param.sequence)
            # Append the sorted parameters
            for param in sorted_parameters:
                lines.append((0, 0, {
                    'testing_parameter': param.id,
                    'sequence': param.sequence,
                    'specification': param.specification,
                    'results': param.results,
                    'inspection_decision':param.inspection_decision
                }))

            # Set the sorted lines to testing_parameter_line_ids
            self.testing_parameter_line_ids = lines


class FIR_Only_Line(models.Model):
    _name = 'sos_fir_line'
    _description = 'Final Inspection Report Line Items'

    ref_line_id = fields.Many2one('sos_fir',  ondelete="cascade")
    sequence = fields.Integer(string="sequence")
    testing_parameter = fields.Many2one('sos_fir_testing_parameters_lines', string='Testing Parameter')
    sampled_qty = fields.Integer(string="Sampled Quantity")
    accepted_qty = fields.Integer(string="Accepted Quantity")
    rejected_qty = fields.Integer(string="Rejected Quantity")
    inspection_decision = fields.Selection([('PASS','PASS'),('FAIL','FAIL')],string="Inspection Decision")
    specification = fields.Char(string="Specification")
    results = fields.Text(string="Results")
  
class Calibration_devices(models.Model):
    _name = 'sos_calibration_devices_fir_only'
    _description = 'Calibartion Devices List'
    
    ref_id = fields.Many2one('sos_fir',  ondelete="cascade")
    calibration_device = fields.Many2one('sos_calibration_devices',string="Equipment Name", required=True)
    identification_No = fields.Char(string="Identification No",related="calibration_device.identification_no")
    certification_No = fields.Char(string="Certification No",related="calibration_device.certification_no")
    calibrated_date = fields.Date(string="Calibrated Date",related="calibration_device.calibrated_on")
    due_date = fields.Date(string="Due Date",related="calibration_device.calibrated_due")

class firModel_Rejected_Lines(models.Model):
    _name = 'sos_fir_rejected_lines'
    _description = 'Rejected FG Lines'

    ref_id = fields.Many2one('sos_fir')
    fg_name = fields.Many2one('sos_fg',string="FG Name")
    quantity = fields.Integer(string="Rejected Quantity")
    available_fg_names = fields.Many2many('sos_fg', compute="_compute_available_fg_names", store=False)

    @api.depends('ref_id')
    def _compute_available_fg_names(self):
        for record in self:
            record.available_fg_names = record.ref_id.fg_name.ids if record.ref_id else []

class BRR_serial_no_Lines(models.Model):
    _name = 'sos_fir_serial_no_lines'
    _description = 'Serial No FIR Line Items'

    ref_id = fields.Many2one('sos_fir',  ondelete="cascade")
    serial_no = fields.Char(string="Serial No")
    inspection_decision = fields.Selection([('PASS','PASS'),('FAIL','FAIL')],string="Inspection Decision",default="PASS")