# -*- coding: utf-8 -*-
# Copyright 2024-2025 Nexa Systems Inc.
# License OPL-1 (Odoo Proprietary License v1.0)
# Part of the Fusion Claim Assistant product family.

from odoo import models, fields, api, _
from odoo.exceptions import UserError
import json
import logging

_logger = logging.getLogger(__name__)


class SubmissionVerificationWizard(models.TransientModel):
    """Wizard to verify which device types are being submitted in the ADP application.
    
    This is Stage 1 of the two-stage verification system:
    - Stage 1 (Submission): Verify what device types are being applied for
    - Stage 2 (Approval): Verify what device types were approved by ADP
    """
    _name = 'fusion_claims.submission.verification.wizard'
    _description = 'ADP Submission Verification Wizard'

    # ==========================================================================
    # MAIN FIELDS
    # ==========================================================================
    sale_order_id = fields.Many2one(
        'sale.order',
        string='Sale Order',
        required=True,
        readonly=True,
    )
    line_ids = fields.One2many(
        'fusion_claims.submission.verification.wizard.line',
        'wizard_id',
        string='Device Type Lines',
    )
    
    # Store device type mapping as JSON - needed because readonly fields aren't sent back
    # Format: {"line_index": "device_type_name", ...}
    device_type_mapping = fields.Text(
        string='Device Type Mapping (JSON)',
        help='Internal field to store device type names by line index',
    )
    
    # Summary fields
    total_device_types = fields.Integer(
        string='Total Device Types',
        compute='_compute_summary',
    )
    selected_device_types = fields.Integer(
        string='Selected Device Types',
        compute='_compute_summary',
    )
    
    # ==========================================================================
    # DOCUMENT UPLOAD FIELDS (for Submit Application mode)
    # ==========================================================================
    is_submit_mode = fields.Boolean(
        string='Submit Mode',
        default=False,
        help='True if this wizard is being used to submit the application (not just verify)',
    )
    
    final_application = fields.Binary(
        string='Final Submitted Application',
        help='Upload the final application PDF being submitted to ADP',
    )
    final_application_filename = fields.Char(
        string='Final Application Filename',
    )
    
    xml_file = fields.Binary(
        string='XML Data File',
        help='Upload the XML data file for ADP submission',
    )
    xml_filename = fields.Char(
        string='XML Filename',
    )
    
    # ==========================================================================
    # COMPUTED METHODS
    # ==========================================================================
    @api.depends('line_ids', 'line_ids.selected')
    def _compute_summary(self):
        for wizard in self:
            wizard.total_device_types = len(wizard.line_ids)
            wizard.selected_device_types = len(wizard.line_ids.filtered(lambda l: l.selected))

    # ==========================================================================
    # DEFAULT GET - Populate with device types from order
    # ==========================================================================
    @api.model
    def default_get(self, fields_list):
        res = super().default_get(fields_list)

        active_id = self._context.get('active_id')
        if not active_id:
            return res

        order = self.env['sale.order'].browse(active_id)
        res['sale_order_id'] = order.id
        
        # Set submit mode based on context
        res['is_submit_mode'] = self._context.get('submit_application', False)
        
        # Group order lines by device type
        ADPDevice = self.env['fusion.adp.device.code'].sudo()
        device_type_data = {}  # {device_type: {'products': [], 'total_amount': 0}}
        
        for so_line in order.order_line:
            # Skip non-product lines
            if so_line.display_type in ('line_section', 'line_note'):
                continue
            if not so_line.product_id or so_line.product_uom_qty <= 0:
                continue
            
            # Get device code and look up device type
            device_code = so_line._get_adp_device_code()
            if not device_code:
                continue
            
            adp_device = ADPDevice.search([
                ('device_code', '=', device_code), 
                ('active', '=', True)
            ], limit=1)
            
            if not adp_device:
                continue
            
            device_type = adp_device.device_type or 'Unknown'
            
            if device_type not in device_type_data:
                device_type_data[device_type] = {
                    'products': [],
                    'total_amount': 0,
                    'adp_portion': 0,
                }
            
            device_type_data[device_type]['products'].append({
                'name': so_line.product_id.display_name,
                'code': device_code,
                'qty': so_line.product_uom_qty,
                'price': so_line.price_subtotal,
            })
            device_type_data[device_type]['total_amount'] += so_line.price_subtotal
            device_type_data[device_type]['adp_portion'] += so_line.x_fc_adp_portion
        
        # Check if there are previously submitted device types
        previous_selection = {}
        if order.x_fc_submitted_device_types:
            try:
                previous_selection = json.loads(order.x_fc_submitted_device_types)
                _logger.info(f"Loaded previous selection from order {order.id}: {previous_selection}")
            except (json.JSONDecodeError, TypeError) as e:
                _logger.warning(f"Failed to parse submitted_device_types for order {order.id}: {e}")
        else:
            _logger.info(f"No previous selection found for order {order.id}")
        
        # Build wizard lines and device type mapping
        lines_data = []
        device_type_mapping = {}  # {line_index: device_type_name}
        
        for idx, (device_type, data) in enumerate(sorted(device_type_data.items())):
            product_list = ', '.join([
                f"{p['name']} ({p['code']}) x{p['qty']}"
                for p in data['products']
            ])
            
            # Check if previously selected
            was_selected = previous_selection.get(device_type, False)
            _logger.info(f"Device type '{device_type}' - was_selected: {was_selected} (previous_selection keys: {list(previous_selection.keys())})")
            
            # Store mapping by index
            device_type_mapping[str(idx)] = device_type
            
            lines_data.append((0, 0, {
                'device_type': device_type,
                'product_details': product_list,
                'product_count': len(data['products']),
                'total_amount': data['total_amount'],
                'adp_portion': data['adp_portion'],
                'selected': was_selected,  # Default to previously selected state
            }))
        
        res['line_ids'] = lines_data
        res['device_type_mapping'] = json.dumps(device_type_mapping)
        _logger.info(f"Created device_type_mapping: {device_type_mapping}")
        return res

    # ==========================================================================
    # ACTION METHODS
    # ==========================================================================
    def action_confirm_submission(self):
        """Confirm the selected device types and store them for Stage 2 comparison."""
        self.ensure_one()
        
        # Load the device type mapping (stored during default_get)
        # This is needed because readonly fields aren't sent back from the form
        device_type_mapping = {}
        if self.device_type_mapping:
            try:
                device_type_mapping = json.loads(self.device_type_mapping)
            except (json.JSONDecodeError, TypeError):
                pass
        
        _logger.info(f"Loaded device_type_mapping: {device_type_mapping}")
        
        # Get selected lines and map them to device types using the stored mapping
        selected_device_types = []
        for idx, line in enumerate(self.line_ids):
            if line.selected:
                # Get device type from mapping (use index as key)
                device_type = device_type_mapping.get(str(idx))
                if device_type:
                    selected_device_types.append(device_type)
                    _logger.info(f"Line {idx} selected - device_type from mapping: {device_type}")
                else:
                    # Fallback to line.device_type (might be False due to readonly issue)
                    _logger.warning(f"Line {idx} selected but no mapping found, line.device_type={line.device_type}")
                    if line.device_type:
                        selected_device_types.append(line.device_type)
        
        if not selected_device_types:
            raise UserError(
                "Please select at least one device type that is being submitted.\n\n"
                "If none of these device types are being applied for, "
                "please verify the order lines have the correct ADP device codes."
            )
        
        # Store the selection as JSON
        selection_data = {
            device_type: True for device_type in selected_device_types
        }
        _logger.info(f"Saving selection for order {self.sale_order_id.id}: {selection_data}")
        
        # Update the sale order
        self.sale_order_id.write({
            'x_fc_submission_verified': True,
            'x_fc_submitted_device_types': json.dumps(selection_data),
        })
        _logger.info(f"Saved x_fc_submitted_device_types: {json.dumps(selection_data)}")
        
        # Post to chatter with nice card style
        from markupsafe import Markup
        from datetime import date
        
        # Build HTML list from selected device types
        device_list_html = ''.join([
            f'<li>{device_type}</li>'
            for device_type in selected_device_types
        ])
        
        self.sale_order_id.message_post(
            body=Markup(
                '<div style="background: #e8f4fd; border-left: 4px solid #17a2b8; padding: 12px; margin: 8px 0; border-radius: 4px;">'
                '<h4 style="color: #17a2b8; margin: 0 0 8px 0;"><i class="fa fa-check-square"/> Submission Verification Complete</h4>'
                f'<p style="margin: 0;"><strong>Date:</strong> {date.today().strftime("%B %d, %Y")}</p>'
                '<p style="margin: 8px 0 4px 0;"><strong>Device Types:</strong></p>'
                f'<ul style="margin: 0; padding-left: 20px;">{device_list_html}</ul>'
                f'<p style="margin: 8px 0 0 0; color: #666; font-size: 0.9em;">Verified by {self.env.user.name}</p>'
                '</div>'
            ),
            message_type='notification',
            subtype_xmlid='mail.mt_note',
        )
        
        # If we're in submit mode (changing status to submitted), update status and save documents
        if self.is_submit_mode:
            # Validate documents are uploaded
            if not self.final_application:
                raise UserError("Please upload the Final Submitted Application PDF.")
            if not self.xml_file:
                raise UserError("Please upload the XML Data File.")
            
            # Validate file types
            if self.final_application_filename and not self.final_application_filename.lower().endswith('.pdf'):
                raise UserError(f"Final Application must be a PDF file. Uploaded: '{self.final_application_filename}'")
            if self.xml_filename and not self.xml_filename.lower().endswith('.xml'):
                raise UserError(f"XML file must have .xml extension. Uploaded: '{self.xml_filename}'")
            
            # Determine target status (submitted or resubmitted)
            current_status = self.sale_order_id.x_fc_adp_application_status
            new_status = 'resubmitted' if current_status == 'needs_correction' else 'submitted'
            
            # Update status and save documents with skip flag
            self.sale_order_id.with_context(skip_status_validation=True).write({
                'x_fc_adp_application_status': new_status,
                'x_fc_final_submitted_application': self.final_application,
                'x_fc_final_application_filename': self.final_application_filename,
                'x_fc_xml_file': self.xml_file,
                'x_fc_xml_filename': self.xml_filename,
            })
            
            # Post status change to chatter with nice card style
            status_label = 'Resubmitted' if new_status == 'resubmitted' else 'Submitted'
            self.sale_order_id.message_post(
                body=Markup(
                    '<div style="background: #d4edda; border-left: 4px solid #28a745; padding: 12px; margin: 8px 0; border-radius: 4px;">'
                    f'<h4 style="color: #28a745; margin: 0 0 8px 0;"><i class="fa fa-paper-plane"/> Application {status_label}</h4>'
                    f'<p style="margin: 0;"><strong>Date:</strong> {date.today().strftime("%B %d, %Y")}</p>'
                    '<p style="margin: 8px 0 4px 0;"><strong>Device Types Submitted:</strong></p>'
                    f'<ul style="margin: 0; padding-left: 20px;">{device_list_html}</ul>'
                    f'<p style="margin: 8px 0 0 0; color: #666; font-size: 0.9em;">Submitted by {self.env.user.name}</p>'
                    '</div>'
                ),
                message_type='notification',
                subtype_xmlid='mail.mt_note',
            )
            
            return {
                'type': 'ir.actions.act_window_close',
                'infos': {
                    'type': 'ir.actions.client',
                    'tag': 'display_notification',
                    'params': {
                        'title': _('Application Submitted'),
                        'message': _('Application submitted with %d device type(s).') % len(selected_device_types),
                        'type': 'success',
                        'sticky': False,
                    }
                }
            }

        return {
            'type': 'ir.actions.act_window_close',
            'infos': {
                'type': 'ir.actions.client',
                'tag': 'display_notification',
                'params': {
                    'title': _('Submission Verified'),
                    'message': _('%d device type(s) confirmed for submission.') % len(selected_device_types),
                    'type': 'success',
                    'sticky': False,
                }
            }
        }

    def action_select_all(self):
        """Select all device types."""
        self.ensure_one()
        for line in self.line_ids:
            line.selected = True
        
        return {
            'type': 'ir.actions.act_window',
            'res_model': self._name,
            'res_id': self.id,
            'view_mode': 'form',
            'target': 'new',
        }


class SubmissionVerificationWizardLine(models.TransientModel):
    """Lines for the submission verification wizard - grouped by device type."""
    _name = 'fusion_claims.submission.verification.wizard.line'
    _description = 'Submission Verification Wizard Line'

    wizard_id = fields.Many2one(
        'fusion_claims.submission.verification.wizard',
        string='Wizard',
        required=True,
        ondelete='cascade',
    )
    device_type = fields.Char(
        string='Device Type',
        readonly=True,
    )
    product_details = fields.Text(
        string='Products',
        readonly=True,
        help='List of products in this device type',
    )
    product_count = fields.Integer(
        string='# Products',
        readonly=True,
    )
    total_amount = fields.Monetary(
        string='Total Amount',
        readonly=True,
        currency_field='currency_id',
    )
    adp_portion = fields.Monetary(
        string='ADP Portion',
        readonly=True,
        currency_field='currency_id',
    )
    currency_id = fields.Many2one(
        'res.currency',
        related='wizard_id.sale_order_id.currency_id',
        readonly=True,
    )
    selected = fields.Boolean(
        string='Submitting',
        default=False,
        help='Check if this device type is being submitted in the ADP application',
    )
