# -*- coding: utf-8 -*-

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

_logger = logging.getLogger(__name__)

# =========================================================================
# ADP device_type -> section code mapping
# Maps each device_type string from fusion.adp.device.code to the
# fusion.wc.section code where matched products should be placed.
# =========================================================================
DEVICE_TYPE_SECTION_MAP = {
    # =================================================================
    # MANUAL WHEELCHAIR FRAMES (Section 2b base devices)
    # =================================================================
    'Adult Standard Manual Type 1 Wheelchair': 'mw_frame',
    'Adult Lightweight Standard Type 1 Wheelchair': 'mw_frame',
    'Adult Lightweight Performance Type 3 Wheelchair': 'mw_frame',
    'Adult Lightweight Performance Manual Wheelchair': 'mw_frame',
    'Adult High Performance Rigid Type 4 Wheelchair': 'mw_frame',
    'Adult High Performance Rigid Manual Wheelchair': 'mw_frame',
    'Adult Manual Dynamic Tilt Type 5 Wheelchair': 'mw_frame',
    'Adult Manual Dynamic Tilt Wheelchair': 'mw_frame',
    'Standard Manual Wheelchair Frame with Manual Dynamic Tilt': 'mw_frame',
    'Paediatric Lightweight Standard Type 1 Wheelchair': 'mw_frame',
    'Paediatric Lightweight Performance Type 4 Wheelchair': 'mw_frame',
    'Paediatric High Performance Rigid Type 4 Wheelchair': 'mw_frame',
    'Paediatric High Performance Rigid Manual Wheelchair': 'mw_frame',
    'Paediatric Manual Dynamic Tilt Type 5 Wheelchair': 'mw_frame',
    'Paediatric Specific Specialty Stroller': 'mw_frame',

    # =================================================================
    # WALKER / ROLLATOR / AMBULATION AIDS FRAMES (Section 2a)
    # =================================================================
    'Adult Wheeled Walker Type 1': 'walker_frame',
    'Adult Wheeled Walker Type 2': 'walker_frame',
    'Adult Wheeled Walker Type 3': 'walker_frame',
    'Paediatric Wheeled Walker Type 1': 'walker_frame',
    'Paediatric Wheeled Walker Type 2': 'walker_frame',
    'Paediatric Walking Frame': 'walker_frame',
    'Paediatric Specific Walking Frame': 'walker_frame',
    'Paediatric Standing Frame Type 1': 'walker_frame',
    'Paediatric Standing Frame Type 2': 'walker_frame',
    'Forearm Crutches': 'walker_frame',
    'Walker Addons': 'walker_accessories',

    # Walker ADP options (adolescent size upgrades)
    'AA - Custom Modifications': 'walker_adp_options',

    # =================================================================
    # POWER BASE / SCOOTER FRAMES (Section 2c)
    # =================================================================
    'Adult Power Base Type 1': 'pw_frame',
    'Adult Power Base Type 2': 'pw_frame',
    'Adult Power Base Type 3': 'pw_frame',
    'Paediatric Power Base Type 2': 'pw_frame',
    'Paediatric Power Base Type 3': 'pw_frame',
    'Power Scooter': 'pw_frame',

    # Power base ADP funded options
    'MW - Adjustable Tension Back Upholstery up to 18" Frame Width': 'pw_adp_options',
    'MW - Adjustable Tension Back Upholstery over 18" Frame Width': 'pw_adp_options',
    'PW - Adjustable Tension Back Upholstery up to 18" Frame Width': 'pw_adp_options',
    'PW - Adjustable Tension Back Upholstery over 18" Frame Width': 'pw_adp_options',
    'Midline Control': 'pw_adp_options',
    'Manual Recline Option': 'pw_adp_options',
    'Recliner Option': 'pw_adp_options',
    'MW - Angle Adjustable Footplates (pair)': 'pw_adp_options',
    'PW - Angle Adjustable Footplates (pair)': 'pw_adp_options',
    'Manual Elevating Legrests (pair)': 'pw_adp_options',
    'Elevating Legrests (pair)': 'pw_adp_options',
    'Swingaway Mounting Bracket': 'pw_adp_options',
    'One Piece 90/90 Front Riggings': 'pw_adp_options',
    'Seat Package 1 for Power Bases': 'pw_adp_options',
    'Seat Package 2 for Power Bases': 'pw_adp_options',
    'PW - Oxygen Tank': 'pw_adp_options',
    'MW - Oxygen Tank Holder': 'pw_adp_options',
    'PW - Ventilator Tray': 'pw_adp_options',
    'MW - Ventilator Tray': 'pw_adp_options',

    # Power specialty controls (* require clinical rationale)
    'Specialty Controls 1 Non Standard Joystick*': 'pw_specialty_controls',
    'Specialty Controls 2 Chin/Rim Control*': 'pw_specialty_controls',
    'Specialty Controls 3 Simple Touch*': 'pw_specialty_controls',
    'Specialty Controls 4 Proximity Control*': 'pw_specialty_controls',
    'Specialty Controls 5 Breath Control*': 'pw_specialty_controls',
    'Specialty Controls 6 Scanners*': 'pw_specialty_controls',
    'Auto Correction System*': 'pw_specialty_controls',

    # Power positioning devices (require Justification for Funding Chart)
    'Power Tilt Only': 'pw_positioning',
    'Power Recline Only': 'pw_positioning',
    'Power Tilt and Recline': 'pw_positioning',
    'Power Elevating Footrests': 'pw_positioning',
    'Multi-function Control Box': 'pw_positioning',
    'Power Add-On Device': 'pw_positioning',

    # =================================================================
    # SEATING – SEAT CUSHION (shared across wheelchair types)
    # =================================================================
    'Seat Cushion': 'seat_cushion',
    'Seat Cushion Cover(s)': 'seat_cushion_cover',
    'Seat Options': 'seat_options',
    'Seat Hardware': 'seat_hardware',
    'Pommel/Adductors': 'pommel',
    'Pommel Hardware': 'pommel_hardware',

    # =================================================================
    # SEATING – BACK SUPPORT
    # =================================================================
    'Back Support': 'back_support',
    'Back Support Options': 'back_support_options',
    'Back Cover': 'back_cover',
    'Back Hardware': 'back_hardware',

    # =================================================================
    # SEATING – COMPLETE ASSEMBLY
    # =================================================================
    'Complete Assembly': 'complete_assembly',

    # =================================================================
    # SEATING – HEADREST / NECKREST
    # =================================================================
    'Headrest/Neckrest': 'headrest',
    'Headrest/Neckrest Options': 'headrest_options',
    'Headrest/Neckrest Hardware': 'headrest_hardware',

    # =================================================================
    # SEATING – POSITIONING BELTS
    # =================================================================
    'Positioning Belts': 'positioning_belts',
    'Positioning Belts Options': 'positioning_belt_options',

    # =================================================================
    # SEATING – ARM SUPPORT
    # =================================================================
    'Arm Support(s)': 'arm_support',
    'Arm Support Options': 'arm_support_options',
    'Arm Support Hardware': 'arm_support_hardware',

    # =================================================================
    # SEATING – TRAY
    # =================================================================
    'Tray': 'tray',
    'Tray Options': 'tray_options',

    # =================================================================
    # SEATING – LATERAL SUPPORT
    # =================================================================
    'Lateral Support(s)': 'lateral_support',
    'Lateral Support Options': 'lateral_support_options',
    'Lateral Support Hardware': 'lateral_support_hardware',

    # =================================================================
    # SEATING – FOOT / LEG SUPPORT
    # =================================================================
    'Foot/Leg Support(s)': 'foot_leg_support',
    'Foot/Leg Support Options': 'foot_leg_support_options',
    'Foot/Leg Support Hardware': 'foot_leg_support_hardware',

    # =================================================================
    # MANUAL WHEELCHAIR ACCESSORIES (Section 2b options/extras)
    # =================================================================
    'Amputee Axle Plates (pair)': 'mw_accessories',
    'Caster Pin Locks (pair)': 'mw_accessories',
    'Clothing Guards': 'mw_accessories',
    'Grade Aids (pair)': 'mw_accessories',
    'Heavy Duty Cross Braces & Upholstery': 'mw_accessories',
    'One Arm/Lever Drive': 'mw_accessories',
    'Plastic Coated Handrims': 'mw_accessories',
    'Projected Handrims (pair)': 'mw_accessories',
    'Quick Release Axles (pair)': 'mw_accessories',
    'Spoke Protectors (pair)': 'mw_accessories',
    'Stroller Handles/Paediatric': 'mw_accessories',
    'Titanium Frame *': 'mw_accessories',
    'Uni-Lateral Wheel Lock': 'mw_accessories',
    'Unilateral Hand Brake': 'mw_accessories',

    # =================================================================
    # MW ADP UPCHARGE / MODIFICATION CODES
    # =================================================================
    'MW - Seat Width Required is Greater Than 18"': 'mw_adp_options',
    'MW - Seat Depth Required is Greater Than 18"': 'mw_adp_options',
    'MW - Heavy Duty Model, Client Weight Exceeds 250 Lbs': 'mw_adp_options',
    'MW - Heavy Duty Model, Client Weight Exceeds 350 Lbs': 'mw_adp_options',
    'MW - Heavy Duty Model, Client Weight Exceeds 400 Lbs': 'mw_adp_options',
    'MW - Custom Modifications': 'mw_adp_options',

    # =================================================================
    # PW ADP UPCHARGE / MODIFICATION CODES
    # =================================================================
    'PW - Seat Width Required is Greater Than 18"': 'pw_adp_options',
    'PW - Seat Depth Required is Greater Than 18"': 'pw_adp_options',
    'PW - Heavy Duty Model, Client Weight Exceeds 250 Lbs': 'pw_adp_options',
    'PW - Heavy Duty Model, Client Weight Exceeds 350 Lbs': 'pw_adp_options',
    'PW - Heavy Duty Model, Client Weight Exceeds 400 Lbs': 'pw_adp_options',
    'PW - Custom Modifications': 'pw_adp_options',
    'SE - Custom Modifications': 'pw_adp_options',
}


class WheelchairSection(models.Model):
    _name = 'fusion.wc.section'
    _description = 'Wheelchair Configuration Section'
    _order = 'sequence, id'

    name = fields.Char(string='Name', required=True)
    code = fields.Char(string='Code', required=True, index=True,
        help='Unique identifier e.g. frame, cushion, backrest')
    sequence = fields.Integer(string='Sequence', default=10)
    active = fields.Boolean(string='Active', default=True)

    equipment_type = fields.Selection(
        selection='_get_equipment_type_selection',
        string='Equipment Type', default='both', required=True)

    @api.model
    def _get_equipment_type_selection(self):
        types = self.env['fusion.equipment.type'].sudo().search([], order='sequence')
        if types:
            result = [(t.code, t.name) for t in types]
            # Group options for shared sections
            result.append(('wheelchair', 'All Wheelchairs (Manual + Power)'))
            result.append(('both', 'All Equipment Types'))
            return result
        return [
            ('manual_wheelchair', 'Manual Wheelchair'),
            ('power_wheelchair', 'Power Wheelchair'),
            ('walker', 'Walker / Ambulation Aid'),
            ('wheelchair', 'All Wheelchairs (Manual + Power)'),
            ('both', 'All Equipment Types'),
        ]

    icon = fields.Char(string='Icon', help='FontAwesome icon class e.g. fa-wheelchair')
    description = fields.Text(string='Description',
        help='Help text shown to sales reps during assessment')

    # Section behavior flags
    is_adp_options_section = fields.Boolean(string='ADP Options Section',
        help='If true, this section shows as a checkbox grid of ADP funded options')
    has_build_type = fields.Boolean(string='Has Build Type',
        help='If true, shows Modular / Custom Fabricated toggle for items in this section')
    allow_multiple = fields.Boolean(string='Allow Multiple', default=True,
        help='Can select multiple products in this section')
    required = fields.Boolean(string='Required', default=False,
        help='Must have at least one selection')

    # Measurement fields configuration
    has_width = fields.Boolean(string='Collect Width')
    has_depth = fields.Boolean(string='Collect Depth')
    has_height = fields.Boolean(string='Collect Height')
    has_length = fields.Boolean(string='Collect Length')

    width_label = fields.Char(string='Width Label', default='Width (inches)')
    depth_label = fields.Char(string='Depth Label', default='Depth (inches)')
    height_label = fields.Char(string='Height Label', default='Height (inches)')
    length_label = fields.Char(string='Length Label', default='Length (inches)')

    # Product filter for custom search
    product_category_id = fields.Many2one('product.category',
        string='Product Category Filter',
        help='Default category to filter products when searching in this section')

    # Hierarchy
    parent_id = fields.Many2one('fusion.wc.section', string='Parent Section',
        ondelete='cascade', index=True)
    child_ids = fields.One2many('fusion.wc.section', 'parent_id',
        string='Sub-Sections')

    # Options
    option_ids = fields.One2many('fusion.wc.section.option', 'section_id',
        string='Product Options')
    option_count = fields.Integer(string='Options', compute='_compute_option_count')

    @api.depends('option_ids')
    def _compute_option_count(self):
        for record in self:
            record.option_count = len(record.option_ids)

    @api.depends('name', 'code')
    def _compute_display_name(self):
        for record in self:
            if record.parent_id:
                record.display_name = f"{record.parent_id.name} / {record.name}"
            else:
                record.display_name = record.name or ''

    # =====================================================================
    # AUTO-POPULATE OPTIONS FROM INVENTORY
    # =====================================================================
    def action_auto_populate_options(self):
        """Auto-populate product options for THIS section by matching
        products in inventory whose ADP device code maps to this section
        via the ADP device type lookup.

        Called from a button on the section form view.
        """
        self.ensure_one()
        stats = self._populate_section_from_products()
        return {
            'type': 'ir.actions.client',
            'tag': 'display_notification',
            'params': {
                'title': _('Auto-Populate Complete'),
                'message': _(
                    'Section "%(section)s": %(added)d products added, '
                    '%(skipped)d already existed, %(unmapped)d unmapped.',
                    section=self.name,
                    added=stats['added'],
                    skipped=stats['skipped'],
                    unmapped=stats['unmapped'],
                ),
                'type': 'success',
                'sticky': False,
            },
        }

    @api.model
    def action_auto_populate_all_sections(self):
        """Auto-populate ALL sections at once. Called from a menu action."""
        sections = self.search([])
        totals = {'added': 0, 'skipped': 0, 'unmapped': 0}
        section_results = []

        for section in sections:
            stats = section._populate_section_from_products()
            totals['added'] += stats['added']
            totals['skipped'] += stats['skipped']
            totals['unmapped'] += stats['unmapped']
            if stats['added'] > 0:
                section_results.append(f"{section.name}: +{stats['added']}")

        details = ', '.join(section_results) if section_results else 'No new products found'

        return {
            'type': 'ir.actions.client',
            'tag': 'display_notification',
            'params': {
                'title': _('Auto-Populate All Sections Complete'),
                'message': _(
                    'Total: %(added)d products added across all sections. '
                    '%(skipped)d already existed. '
                    '%(unmapped)d products had unmapped device types.\n'
                    '%(details)s',
                    added=totals['added'],
                    skipped=totals['skipped'],
                    unmapped=totals['unmapped'],
                    details=details,
                ),
                'type': 'success',
                'sticky': True,
            },
        }

    def _populate_section_from_products(self):
        """Find products whose ADP device type maps to this section,
        and create one fusion.wc.section.option per product *template*.

        Variants (size, colour, etc.) live under the template and are
        selected when the sales rep adds the item to an assessment.
        This keeps the option list compact and manageable.

        Returns dict with counts: {added, skipped, unmapped}
        """
        self.ensure_one()
        SectionOption = self.env['fusion.wc.section.option'].sudo()
        ADPDevice = self.env['fusion.adp.device.code'].sudo()
        ProductTemplate = self.env['product.template'].sudo()

        # Build reverse map: which device_types map to THIS section's code
        my_device_types = [
            dtype for dtype, section_code in DEVICE_TYPE_SECTION_MAP.items()
            if section_code == self.code
        ]

        if not my_device_types:
            return {'added': 0, 'skipped': 0, 'unmapped': 0}

        # Find ADP device codes with matching device_type
        matching_adp_codes = ADPDevice.search([
            ('device_type', 'in', my_device_types),
            ('active', '=', True),
        ])
        adp_code_strings = matching_adp_codes.mapped('device_code')

        if not adp_code_strings:
            return {'added': 0, 'skipped': 0, 'unmapped': 0}

        # Find product templates with those ADP codes
        products = ProductTemplate.search([
            ('x_fc_adp_device_code', 'in', adp_code_strings),
        ])

        if not products:
            return {'added': 0, 'skipped': 0, 'unmapped': 0}

        # Get existing option template IDs for this section (avoid duplicates)
        existing_tmpl_ids = set(
            SectionOption.search([
                ('section_id', '=', self.id),
            ]).mapped('product_tmpl_id.id')
        )

        # Pre-fetch build types: ADP code -> build_type
        build_type_cache = {}
        for adp_code_str in set(products.mapped('x_fc_adp_device_code')):
            adp_device = ADPDevice.search([
                ('device_code', '=', adp_code_str),
                ('active', '=', True),
            ], limit=1)
            build_type = 'both'
            if adp_device and adp_device.build_type:
                if adp_device.build_type == 'modular':
                    build_type = 'modular'
                elif adp_device.build_type == 'custom_fabricated':
                    build_type = 'custom_fabricated'
            build_type_cache[adp_code_str] = build_type

        added = 0
        skipped = 0
        unmapped = 0

        # Batch-create one option record per product template
        vals_list = []
        for tmpl in products:
            if tmpl.id in existing_tmpl_ids:
                skipped += 1
                continue

            adp_code = tmpl.x_fc_adp_device_code
            build_type = build_type_cache.get(adp_code, 'both')

            vals_list.append({
                'section_id': self.id,
                'product_tmpl_id': tmpl.id,
                'is_standard': True,
                'available_build_types': build_type,
                'sequence': 10 + added,
            })
            added += 1
            existing_tmpl_ids.add(tmpl.id)

        # Bulk create for performance
        if vals_list:
            SectionOption.create(vals_list)

        _logger.info(
            'Section "%s" auto-populate: %d product templates added, '
            '%d already existed, %d unmapped',
            self.name, added, skipped, unmapped,
        )
        return {'added': added, 'skipped': skipped, 'unmapped': unmapped}
