# -*- 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.

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

_logger = logging.getLogger(__name__)


# =============================================================================
# DEFAULT FIELD MAPPINGS
# =============================================================================
# These define the default FC field mappings and their config parameter keys

DEFAULT_FIELD_MAPPINGS = [
    # Sale Order Header Fields
    {
        'model_name': 'sale.order',
        'label': 'Sale Type',
        'default_fc_field': 'x_fc_sale_type',
        'config_param_key': 'fusion_claims.field_sale_type',
    },
    {
        'model_name': 'sale.order',
        'label': 'Client Type',
        'default_fc_field': 'x_fc_client_type',
        'config_param_key': 'fusion_claims.field_so_client_type',
    },
    {
        'model_name': 'sale.order',
        'label': 'Authorizer',
        'default_fc_field': 'x_fc_authorizer_id',
        'config_param_key': 'fusion_claims.field_so_authorizer',
    },
    {
        'model_name': 'sale.order',
        'label': 'Claim Number',
        'default_fc_field': 'x_fc_claim_number',
        'config_param_key': 'fusion_claims.field_so_claim_number',
    },
    {
        'model_name': 'sale.order',
        'label': 'Client Reference 1',
        'default_fc_field': 'x_fc_client_ref_1',
        'config_param_key': 'fusion_claims.field_so_client_ref_1',
    },
    {
        'model_name': 'sale.order',
        'label': 'Client Reference 2',
        'default_fc_field': 'x_fc_client_ref_2',
        'config_param_key': 'fusion_claims.field_so_client_ref_2',
    },
    {
        'model_name': 'sale.order',
        'label': 'Delivery Date',
        'default_fc_field': 'x_fc_adp_delivery_date',
        'config_param_key': 'fusion_claims.field_so_delivery_date',
    },
    {
        'model_name': 'sale.order',
        'label': 'Service Start Date',
        'default_fc_field': 'x_fc_service_start_date',
        'config_param_key': 'fusion_claims.field_so_service_start',
    },
    {
        'model_name': 'sale.order',
        'label': 'Service End Date',
        'default_fc_field': 'x_fc_service_end_date',
        'config_param_key': 'fusion_claims.field_so_service_end',
    },
    {
        'model_name': 'sale.order',
        'label': 'ADP Status',
        'default_fc_field': 'x_fc_adp_status',
        'config_param_key': 'fusion_claims.field_so_adp_status',
    },
    {
        'model_name': 'sale.order',
        'label': 'Primary Serial Number',
        'default_fc_field': 'x_fc_primary_serial',
        'config_param_key': 'fusion_claims.field_so_primary_serial',
    },
    # Sale Order Line Fields
    {
        'model_name': 'sale.order.line',
        'label': 'Serial Number',
        'default_fc_field': 'x_fc_serial_number',
        'config_param_key': 'fusion_claims.field_sol_serial',
    },
    {
        'model_name': 'sale.order.line',
        'label': 'Device Placement',
        'default_fc_field': 'x_fc_device_placement',
        'config_param_key': 'fusion_claims.field_sol_placement',
    },
    # Invoice Header Fields
    {
        'model_name': 'account.move',
        'label': 'Invoice Type',
        'default_fc_field': 'x_fc_invoice_type',
        'config_param_key': 'fusion_claims.field_invoice_type',
    },
    {
        'model_name': 'account.move',
        'label': 'Client Type',
        'default_fc_field': 'x_fc_client_type',
        'config_param_key': 'fusion_claims.field_inv_client_type',
    },
    {
        'model_name': 'account.move',
        'label': 'Authorizer',
        'default_fc_field': 'x_fc_authorizer_id',
        'config_param_key': 'fusion_claims.field_inv_authorizer',
    },
    {
        'model_name': 'account.move',
        'label': 'Claim Number',
        'default_fc_field': 'x_fc_claim_number',
        'config_param_key': 'fusion_claims.field_inv_claim_number',
    },
    {
        'model_name': 'account.move',
        'label': 'Client Reference 1',
        'default_fc_field': 'x_fc_client_ref_1',
        'config_param_key': 'fusion_claims.field_inv_client_ref_1',
    },
    {
        'model_name': 'account.move',
        'label': 'Client Reference 2',
        'default_fc_field': 'x_fc_client_ref_2',
        'config_param_key': 'fusion_claims.field_inv_client_ref_2',
    },
    {
        'model_name': 'account.move',
        'label': 'Delivery Date',
        'default_fc_field': 'x_fc_adp_delivery_date',
        'config_param_key': 'fusion_claims.field_inv_delivery_date',
    },
    {
        'model_name': 'account.move',
        'label': 'Service Start Date',
        'default_fc_field': 'x_fc_service_start_date',
        'config_param_key': 'fusion_claims.field_inv_service_start',
    },
    {
        'model_name': 'account.move',
        'label': 'Service End Date',
        'default_fc_field': 'x_fc_service_end_date',
        'config_param_key': 'fusion_claims.field_inv_service_end',
    },
    {
        'model_name': 'account.move',
        'label': 'Primary Serial Number',
        'default_fc_field': 'x_fc_primary_serial',
        'config_param_key': 'fusion_claims.field_inv_primary_serial',
    },
    # Invoice Line Fields
    {
        'model_name': 'account.move.line',
        'label': 'Serial Number',
        'default_fc_field': 'x_fc_serial_number',
        'config_param_key': 'fusion_claims.field_aml_serial',
    },
    {
        'model_name': 'account.move.line',
        'label': 'Device Placement',
        'default_fc_field': 'x_fc_device_placement',
        'config_param_key': 'fusion_claims.field_aml_placement',
    },
    # Product Fields
    {
        'model_name': 'product.template',
        'label': 'ADP Device Code',
        'default_fc_field': 'x_fc_adp_device_code',
        'config_param_key': 'fusion_claims.field_product_code',
    },
    {
        'model_name': 'product.template',
        'label': 'ADP Price',
        'default_fc_field': 'x_fc_adp_price',
        'config_param_key': 'fusion_claims.field_product_adp_price',
    },
]


# =============================================================================
# AUTO-DETECT PATTERNS
# =============================================================================
# Keywords to look for when auto-detecting existing custom fields

AUTO_DETECT_PATTERNS = {
    # Sale Order Header
    'fusion_claims.field_sale_type': ['sale_type', 'saletype', 'type_of_sale', 'order_type'],
    'fusion_claims.field_so_client_type': ['client_type', 'clienttype', 'customer_type', 'cust_type'],
    'fusion_claims.field_so_authorizer': ['authorizer', 'authorized', 'approver', 'authorizer_name'],
    'fusion_claims.field_so_claim_number': ['claim_number', 'claimnumber', 'claim_no', 'adp_claim', 'claim_num'],
    'fusion_claims.field_so_client_ref_1': ['client_ref_1', 'clientref1', 'reference_1', 'client_reference_1', 'ref1', 'ref_1'],
    'fusion_claims.field_so_client_ref_2': ['client_ref_2', 'clientref2', 'reference_2', 'client_reference_2', 'ref2', 'ref_2'],
    'fusion_claims.field_so_delivery_date': ['delivery_date', 'deliverydate', 'adp_delivery', 'deliver_date', 'date_delivery'],
    'fusion_claims.field_so_service_start': ['service_start', 'servicestart', 'start_date', 'service_start_date', 'svc_start'],
    'fusion_claims.field_so_service_end': ['service_end', 'serviceend', 'end_date', 'service_end_date', 'svc_end'],
    'fusion_claims.field_so_adp_status': ['adp_status', 'adpstatus', 'claim_status', 'status'],
    'fusion_claims.field_so_primary_serial': ['primary_serial', 'primaryserial', 'main_serial', 'serial_primary'],
    # Sale Order Line
    'fusion_claims.field_sol_serial': ['serial_number', 'serial', 'sn', 'serialno'],
    'fusion_claims.field_sol_placement': ['placement', 'device_placement', 'place'],
    # Invoice Header
    'fusion_claims.field_invoice_type': ['invoice_type', 'invoicetype', 'inv_type', 'type_of_invoice', 'bill_type'],
    'fusion_claims.field_inv_client_type': ['client_type', 'clienttype', 'customer_type', 'cust_type'],
    'fusion_claims.field_inv_authorizer': ['authorizer', 'authorized', 'approver', 'authorizer_name'],
    'fusion_claims.field_inv_claim_number': ['claim_number', 'claimnumber', 'claim_no', 'claim_num'],
    'fusion_claims.field_inv_client_ref_1': ['client_ref_1', 'clientref1', 'reference_1', 'client_reference_1', 'ref1', 'ref_1'],
    'fusion_claims.field_inv_client_ref_2': ['client_ref_2', 'clientref2', 'reference_2', 'client_reference_2', 'ref2', 'ref_2'],
    'fusion_claims.field_inv_delivery_date': ['delivery_date', 'deliverydate', 'adp_delivery', 'deliver_date', 'date_delivery'],
    'fusion_claims.field_inv_service_start': ['service_start', 'servicestart', 'start_date', 'service_start_date', 'svc_start'],
    'fusion_claims.field_inv_service_end': ['service_end', 'serviceend', 'end_date', 'service_end_date', 'svc_end'],
    'fusion_claims.field_inv_primary_serial': ['primary_serial', 'primaryserial', 'main_serial', 'serial_primary'],
    # Invoice Line
    'fusion_claims.field_aml_serial': ['serial_number', 'serial', 'sn', 'serialno'],
    'fusion_claims.field_aml_placement': ['placement', 'device_placement', 'place'],
    # Product
    'fusion_claims.field_product_code': ['adp_code', 'adp_device', 'device_code', 'adp_sku', 'product_code'],
    'fusion_claims.field_product_adp_price': ['adp_price', 'adp_retail_price', 'retail_price'],
}


class FieldMappingLine(models.TransientModel):
    """Individual field mapping configuration line."""
    _name = 'fusion_claims.field_mapping_line'
    _description = 'Field Mapping Line'
    _order = 'sequence, id'

    wizard_id = fields.Many2one(
        'fusion_claims.field_mapping_config',
        string='Wizard',
        required=True,
        ondelete='cascade',
    )
    sequence = fields.Integer(default=10)
    
    model_name = fields.Selection(
        selection=[
            ('sale.order', 'Sale Order'),
            ('sale.order.line', 'Sale Order Line'),
            ('account.move', 'Invoice'),
            ('account.move.line', 'Invoice Line'),
            ('product.template', 'Product'),
        ],
        string='Model',
    )
    
    label = fields.Char(string='Field Label')
    field_name = fields.Char(string='Field Name', help='The field name to use on the model')
    default_fc_field = fields.Char(string='Default FC Field')
    config_param_key = fields.Char(string='Config Parameter')
    
    field_exists = fields.Boolean(
        string='Valid',
        compute='_compute_field_exists',
        help='Does this field exist on the model?',
    )
    
    @api.depends('field_name', 'model_name')
    def _compute_field_exists(self):
        """Check if the configured field exists on the model."""
        IrModelFields = self.env['ir.model.fields'].sudo()
        for line in self:
            line.field_exists = False
            if not line.field_name or not line.model_name:
                continue
            # Check database for field existence (more reliable for custom fields)
            field_count = IrModelFields.search_count([
                ('model', '=', line.model_name),
                ('name', '=', line.field_name),
            ])
            line.field_exists = field_count > 0
    
    @api.onchange('field_name')
    def _onchange_field_name(self):
        """Force recomputation of field_exists when field_name changes."""
        # This triggers the compute to run when user edits the field
        pass


class FieldMappingConfigWizard(models.TransientModel):
    """Wizard for configuring field mappings."""
    _name = 'fusion_claims.field_mapping_config'
    _description = 'Field Mapping Configuration Wizard'

    # =========================================================================
    # FIELD MAPPINGS
    # =========================================================================
    mapping_ids = fields.One2many(
        'fusion_claims.field_mapping_line',
        'wizard_id',
        string='Field Mappings',
    )
    
    # =========================================================================
    # SUMMARY FIELDS
    # =========================================================================
    total_mappings = fields.Integer(
        string='Total Mappings',
        compute='_compute_summary',
    )
    valid_mappings = fields.Integer(
        string='Valid Mappings',
        compute='_compute_summary',
    )
    invalid_mappings = fields.Integer(
        string='Invalid Mappings',
        compute='_compute_summary',
    )
    
    @api.depends('mapping_ids.field_exists')
    def _compute_summary(self):
        """Compute summary statistics."""
        for wizard in self:
            wizard.total_mappings = len(wizard.mapping_ids)
            wizard.valid_mappings = len(wizard.mapping_ids.filtered('field_exists'))
            wizard.invalid_mappings = wizard.total_mappings - wizard.valid_mappings

    # =========================================================================
    # DEFAULT VALUES
    # =========================================================================
    
    @api.model
    def default_get(self, fields_list):
        """Load field mappings from ir.config_parameter when wizard opens."""
        res = super().default_get(fields_list)
        
        if 'mapping_ids' in fields_list:
            ICP = self.env['ir.config_parameter'].sudo()
            mappings = []
            seq = 10
            
            for mapping_def in DEFAULT_FIELD_MAPPINGS:
                # Get current value from config, fall back to default
                current_value = ICP.get_param(
                    mapping_def['config_param_key'],
                    mapping_def['default_fc_field']
                )
                
                mappings.append((0, 0, {
                    'sequence': seq,
                    'model_name': mapping_def['model_name'],
                    'label': mapping_def['label'],
                    'field_name': current_value,
                    'default_fc_field': mapping_def['default_fc_field'],
                    'config_param_key': mapping_def['config_param_key'],
                }))
                seq += 10
            
            res['mapping_ids'] = mappings
        
        return res

    # =========================================================================
    # ACTION METHODS
    # =========================================================================
    
    def action_save(self):
        """Save all field mappings to ir.config_parameter."""
        ICP = self.env['ir.config_parameter'].sudo()
        saved_count = 0
        
        for line in self.mapping_ids:
            if line.config_param_key and line.field_name:
                ICP.set_param(line.config_param_key, line.field_name)
                saved_count += 1
        
        _logger.info("Saved %d field mapping configurations", saved_count)
        # Return False to indicate no follow-up action needed
        return False
    
    def action_save_and_close(self):
        """Save mappings and close the wizard."""
        self.action_save()
        return {'type': 'ir.actions.act_window_close'}
    
    def action_reset_defaults(self):
        """Reset all mappings to their default FC field values."""
        ICP = self.env['ir.config_parameter'].sudo()
        reset_count = 0
        
        for line in self.mapping_ids:
            if line.config_param_key and line.default_fc_field:
                # Update the transient record so the form shows the new value
                line.field_name = line.default_fc_field
                # Also save to ir.config_parameter so it persists
                ICP.set_param(line.config_param_key, line.default_fc_field)
                reset_count += 1
        
        _logger.info("Reset %d field mappings to defaults", reset_count)
        # Return False to indicate no follow-up action needed
        return False
    
    def action_auto_detect(self):
        """Auto-detect existing custom fields and update mappings."""
        IrModelFields = self.env['ir.model.fields'].sudo()
        ICP = self.env['ir.config_parameter'].sudo()
        detected_count = 0
        detected_fields = []
        
        # Get all custom fields
        models_to_search = ['sale.order', 'sale.order.line', 'account.move', 'account.move.line', 'product.template']
        all_custom_fields = IrModelFields.search([
            ('model', 'in', models_to_search),
            ('name', '=like', 'x_%'),
            ('state', '=', 'manual'),
        ])
        
        for line in self.mapping_ids:
            if not line.config_param_key:
                continue
            
            patterns = AUTO_DETECT_PATTERNS.get(line.config_param_key, [])
            if not patterns:
                continue
            
            # Get fields for this model
            model_fields = all_custom_fields.filtered(lambda f: f.model == line.model_name)
            
            model_fields_sorted = sorted(model_fields, key=lambda f: f.name)
            
            # Find matching field
            matched_field = None
            for field in model_fields_sorted:
                # Skip our own x_fc_* fields
                if field.name.startswith('x_fc_'):
                    continue
                
                field_name_lower = field.name.lower()
                for pattern in patterns:
                    if pattern in field_name_lower:
                        matched_field = field
                        break
                if matched_field:
                    break
            
            if matched_field and matched_field.name != line.field_name:
                # Update the transient record so the form shows the new value
                line.field_name = matched_field.name
                # Also save to ir.config_parameter so it persists across sessions
                ICP.set_param(line.config_param_key, matched_field.name)
                detected_fields.append(f"{line.label}: {matched_field.name}")
                detected_count += 1
        
        # Log results
        _logger.info("Auto-detected %d Studio field mappings: %s", detected_count, detected_fields)
        
        # Return False to indicate no follow-up action needed
        return False
    
    def action_close(self):
        """Close the wizard without saving."""
        return {'type': 'ir.actions.act_window_close'}
