/** @odoo-module **/

import publicWidget from "@web/legacy/js/public/public_widget";

publicWidget.registry.WCAssessmentForm = publicWidget.Widget.extend({
    selector: '.wc-assessment-form',
    events: {
        'click #btnNext': '_onClickNext',
        'click #btnPrev': '_onClickPrev',
        'click .wc-step-indicator': '_onClickStep',
        'input #clientSearch': '_onClientSearch',
        'click #clearClient': '_onClearClient',
        'input #frameSearch': '_onFrameSearch',
        'click #clearFrame': '_onClearFrame',
        'change .wc-frame-attribute-select': '_onFrameAttributeChange',
        'input .wc-measurement-input': '_onMeasurementChange',
        'change .wc-unit-select': '_onMeasurementChange',
        // equipment_type is now a hidden field — no change event needed
        'click .wc-tab-btn': '_onSeatingTabClick',
        'click .wc-group-header': '_onGroupHeaderClick',
        'input .wc-option-filter': '_onOptionFilter',
        'change .wc-radio-btn input[type="radio"]': '_onRadioBtnChange',
        'click #btnGenerate': '_onClickGenerate',
        'submit #wcForm': '_onFormSubmit',
    },

    start: function () {
        this._super.apply(this, arguments);
        this.currentStep = 1;
        // Dynamic step count from DOM instead of hardcoded 6
        this.totalSteps = this.el.querySelectorAll('.wc-step').length || 6;
        this.selectedLines = [];
        this._debounceTimer = null;
        this._upchargeTimer = null;

        // Detect public (token) mode — token is set via hidden input
        var tokenEl = this.el.querySelector('#accessToken');
        this._accessToken = tokenEl ? tokenEl.value : '';
        this._isPublic = !!this._accessToken;

        this._initForm();
        this._loadSectionOptions();
        return Promise.resolve();
    },

    /**
     * Build the correct API URL depending on auth mode.
     *  - Logged-in portal:  /my/quotation/api/{endpoint}
     *  - Public (token):    /quotation/api/{token}/{endpoint}
     */
    _apiUrl: function (endpoint) {
        if (this._isPublic) {
            return '/quotation/api/' + this._accessToken + '/' + endpoint;
        }
        return '/my/quotation/api/' + endpoint;
    },

    /**
     * Convert a string to Title Case.
     * "ROHO HIGH-PROFILE CUSHION" → "Roho High-Profile Cushion"
     */
    _toTitleCase: function (str) {
        if (!str) return '';
        return str.toLowerCase().replace(/(?:^|\s|[-/])\S/g, function (c) {
            return c.toUpperCase();
        });
    },

    /**
     * Strip leading bracketed codes like [SESND1045] or (SESND1045) from a
     * product name AND strip trailing parenthesised ADP codes like (SE0001692).
     * Returns the cleaned display name in Title Case.
     */
    _cleanProductName: function (name) {
        if (!name) return '';
        // Remove leading [CODE] or (CODE)
        var cleaned = name.replace(/^\s*[\[(][A-Z0-9]+[\])]\s*/i, '');
        // Remove trailing (CODE) that matches an ADP-style pattern
        cleaned = cleaned.replace(/\s*\([A-Z]{2,}[A-Z0-9]*\)\s*$/i, '');
        // Trim any leftover dashes/spaces
        cleaned = cleaned.replace(/^\s*[-–—]\s*/, '').trim();
        return this._toTitleCase(cleaned);
    },

    // =====================================================================
    // INITIALIZATION
    // =====================================================================
    _initForm: function () {
        // Set .active class on all checked radio buttons (for CSS styling fallback)
        this._syncRadioActiveState();
        this._onEquipmentTypeChange();

        var assessmentId = this.el.querySelector('input[name="assessment_id"]');
        if (assessmentId && parseInt(assessmentId.value) > 0) {
            var partnerId = this.el.querySelector('#partnerId');
            if (partnerId && parseInt(partnerId.value) > 0) {
                var selClient = this.el.querySelector('#selectedClient');
                if (selClient) selClient.classList.remove('d-none');
                var newFields = this.el.querySelector('#newClientFields');
                if (newFields) newFields.style.display = 'none';
            }

            // If editing and we have a frame template, show the selected frame
            var tmplId = this.el.querySelector('#frameProductTmplId');
            if (tmplId && tmplId.value) {
                var selectedFrame = this.el.querySelector('#selectedFrame');
                if (selectedFrame) selectedFrame.classList.remove('d-none');
            }
        }
    },

    _getEquipmentPrefix: function () {
        // Determine section code prefix based on equipment type
        var hiddenInput = this.el.querySelector('input[name="equipment_type"]');
        var equipType = hiddenInput ? hiddenInput.value : 'manual_wheelchair';
        var prefixMap = {
            'manual_wheelchair': 'mw',
            'power_wheelchair': 'pw',
            'walker': 'walker',
            'stair_lift': 'sl',
            'porch_lift': 'pl',
        };
        return prefixMap[equipType] || equipType.replace(/_/g, '');
    },

    _loadSectionOptions: function () {
        var self = this;
        var prefix = this._getEquipmentPrefix();

        // Load standard options for seating sections
        var sectionContainers = this.el.querySelectorAll('.wc-section-options');
        sectionContainers.forEach(function (container) {
            var sectionCode = container.dataset.section;
            if (!sectionCode) return;

            self._rpc(self._apiUrl('get_section_options'), {
                section_code: sectionCode,
            }).then(function (options) {
                self._renderSectionOptions(container, options);
            }).catch(function (e) {
                console.warn('Failed to load options for section:', sectionCode, e);
            });
        });

        // ADP options and accessories are loaded by _reloadEquipmentOptions()
        // (called from _onEquipmentTypeChange in _initForm) — do NOT load here
        // to avoid duplicate rendering.
    },

    // =====================================================================
    // STEP NAVIGATION
    // =====================================================================
    _onClickNext: function (ev) {
        ev.preventDefault();
        if (this.currentStep < this.totalSteps) {
            this._goToStep(this.currentStep + 1);
        }
    },

    _onClickPrev: function (ev) {
        ev.preventDefault();
        if (this.currentStep > 1) {
            this._goToStep(this.currentStep - 1);
        }
    },

    _onClickStep: function (ev) {
        var step = parseInt(ev.currentTarget.dataset.step);
        if (step && step >= 1 && step <= this.totalSteps) {
            this._goToStep(step);
        }
    },

    _goToStep: function (step) {
        // Hide all steps
        this.el.querySelectorAll('.wc-step').forEach(function (s) {
            s.classList.add('d-none');
        });
        // Show target step
        var target = this.el.querySelector('.wc-step[data-step="' + step + '"]');
        if (target) {
            target.classList.remove('d-none');
        }

        // Update indicators — completed steps get green checkmark
        this.el.querySelectorAll('.wc-step-indicator').forEach(function (ind) {
            var s = parseInt(ind.dataset.step);
            var isActive = s === step;
            var isCompleted = s < step;
            ind.classList.toggle('active', isActive);
            ind.classList.toggle('completed', isCompleted);

            var numEl = ind.querySelector('.wc-step-number');
            if (!numEl) return;

            if (isCompleted) {
                numEl.innerHTML = '&#10003;';
                numEl.style.cssText = 'width:36px;height:36px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;background:#198754;color:#fff;font-weight:700;font-size:16px;';
            } else if (isActive) {
                numEl.textContent = s;
                numEl.style.cssText = 'width:36px;height:36px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;background:#0d6efd;color:#fff;font-weight:700;font-size:14px;box-shadow:0 0 0 4px rgba(13,110,253,0.2);';
            } else {
                numEl.textContent = s;
                numEl.style.cssText = 'width:36px;height:36px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;background:#e9ecef;color:#6c757d;font-weight:700;font-size:14px;';
            }
        });

        // Update nav buttons
        this.el.querySelector('#btnPrev').style.display = step > 1 ? '' : 'none';
        this.el.querySelector('#btnNext').classList.toggle('d-none', step === this.totalSteps);
        this.el.querySelector('#btnGenerate').classList.toggle('d-none', step !== this.totalSteps);

        // Update hidden step field
        this.el.querySelector('#currentStep').value = step;
        this.currentStep = step;

        // If going to review step, build summary
        if (step === this.totalSteps) {
            this._buildReviewSummary();
        }

        // Auto-save current data
        this._autoSave(step);

        // Scroll to top
        window.scrollTo({ top: 0, behavior: 'smooth' });
    },

    // =====================================================================
    // CLIENT SEARCH
    // =====================================================================
    _onClientSearch: function (ev) {
        var self = this;
        var query = ev.target.value.trim();
        clearTimeout(this._debounceTimer);

        if (query.length < 2) {
            var container = this.el.querySelector('#clientSearchResults');
            if (container) container.classList.add('d-none');
            return;
        }

        this._debounceTimer = setTimeout(function () {
            self._rpc(self._apiUrl('search_clients'), {
                query: query,
            }).then(function (results) {
                self._renderClientResults(results);
            }).catch(function (e) {
                console.error('Client search error:', e);
            });
        }, 300);
    },

    _renderClientResults: function (results) {
        var self = this;
        var container = this.el.querySelector('#clientSearchResults');
        if (!container) return;

        // Force inline dropdown styles (cache-proof)
        container.style.cssText = 'position:absolute;z-index:1060;width:100%;max-height:300px;overflow-y:auto;background:var(--bs-body-bg,#fff);box-shadow:0 8px 30px rgba(0,0,0,.18);border:1px solid var(--bs-border-color,#dee2e6);border-top:none;border-radius:0 0 .5rem .5rem;';

        container.innerHTML = '';
        if (!results || !results.length) {
            container.innerHTML = '<div class="list-group-item text-muted">No clients found</div>';
            container.classList.remove('d-none');
            return;
        }

        results.forEach(function (r) {
            var item = document.createElement('a');
            item.href = '#';
            item.className = 'list-group-item list-group-item-action';
            item.style.cssText = 'background:var(--bs-body-bg,#fff);cursor:pointer;';
            item.innerHTML = '<strong>' + (r.name || '') + '</strong> ' +
                '<small class="text-muted">' + (r.phone || '') + ' ' + (r.email || '') + '</small>';
            item.addEventListener('click', function (e) {
                e.preventDefault();
                self._selectClient(r);
                container.classList.add('d-none');
            });
            container.appendChild(item);
        });
        container.classList.remove('d-none');
    },

    _selectClient: function (client) {
        this.el.querySelector('#partnerId').value = client.id;
        this.el.querySelector('#selectedClientName').textContent = client.name + ' \u2014 ' + (client.phone || '');
        this.el.querySelector('#selectedClient').classList.remove('d-none');
        this.el.querySelector('#newClientFields').style.display = 'none';
        this.el.querySelector('#clientSearch').value = '';
    },

    _onClearClient: function () {
        this.el.querySelector('#partnerId').value = '0';
        this.el.querySelector('#selectedClient').classList.add('d-none');
        this.el.querySelector('#newClientFields').style.display = '';
    },

    // =====================================================================
    // FRAME SEARCH  (Templates + Configurator)
    // =====================================================================
    _onFrameSearch: function (ev) {
        var self = this;
        var query = ev.target.value.trim();
        // Read section_code from the template's data-section attribute (set dynamically)
        var sectionCode = ev.target.dataset.section || (self._getEquipmentPrefix() + '_frame');
        clearTimeout(this._debounceTimer);

        if (query.length < 2) {
            var container = this.el.querySelector('#frameSearchResults');
            if (container) container.classList.add('d-none');
            return;
        }

        this._debounceTimer = setTimeout(function () {
            self._rpc(self._apiUrl('search_products'), {
                query: query,
                section_code: sectionCode,
            }).then(function (results) {
                self._renderFrameResults(results);
            }).catch(function (e) {
                console.error('Frame search error:', e);
            });
        }, 300);
    },

    _renderFrameResults: function (results) {
        var self = this;
        var container = this.el.querySelector('#frameSearchResults');
        if (!container) return;

        // Force inline dropdown styles (cache-proof)
        container.style.cssText = 'position:absolute;z-index:1060;width:100%;max-height:300px;overflow-y:auto;background:var(--bs-body-bg,#fff);box-shadow:0 8px 30px rgba(0,0,0,.18);border:1px solid var(--bs-border-color,#dee2e6);border-top:none;border-radius:0 0 .5rem .5rem;';

        container.innerHTML = '';
        if (!results || !results.length) {
            container.innerHTML = '<div class="list-group-item text-muted">No frames found</div>';
            container.classList.remove('d-none');
            return;
        }

        results.forEach(function (r) {
            var item = document.createElement('a');
            item.href = '#';
            item.className = 'list-group-item list-group-item-action';
            item.style.cssText = 'background:var(--bs-body-bg,#fff);cursor:pointer;';
            var displayName = self._cleanProductName(r.name);
            var adpInfo = '';
            if (r.adp_device_code) adpInfo += 'Code: ' + r.adp_device_code;
            if (r.adp_price) adpInfo += ' \u2014 $' + r.adp_price.toFixed(2);
            var variantBadge = '';
            if (r.has_configurable_attributes) {
                variantBadge = ' <span class="badge text-bg-info ms-1">' +
                    r.variant_count + ' options</span>';
            }
            item.innerHTML = '<div class="d-flex justify-content-between align-items-center">' +
                '<div><strong>' + displayName + '</strong>' + variantBadge +
                (adpInfo ? '<div class="small text-muted">' + adpInfo + '</div>' : '') +
                '</div></div>';
            item.addEventListener('click', function (e) {
                e.preventDefault();
                self._selectFrameTemplate(r);
                container.classList.add('d-none');
            });
            container.appendChild(item);
        });
        container.classList.remove('d-none');
    },

    _selectFrameTemplate: function (template) {
        var self = this;

        // Store template ID
        this.el.querySelector('#frameProductTmplId').value = template.id;

        // Display selected template info (Title Case, cleaned)
        this.el.querySelector('#selectedFrameName').textContent = this._cleanProductName(template.name);
        this.el.querySelector('#selectedFrameCode').textContent = template.adp_device_code || 'N/A';
        this.el.querySelector('#selectedFramePrice').textContent = (template.adp_price || 0).toFixed(2);
        this.el.querySelector('#selectedFrame').classList.remove('d-none');
        this.el.querySelector('#frameSearch').value = '';

        // If single variant (no configurator needed), set the variant directly
        if (!template.has_configurable_attributes || template.variant_count <= 1) {
            if (template.single_variant_id) {
                this.el.querySelector('#frameProductId').value = template.single_variant_id;
            }
            this.el.querySelector('#frameConfigurator').classList.add('d-none');

            // Add to selected lines
            this._addSelectedLine({
                productTmplId: template.id,
                productName: template.name,
                sectionCode: 'frame',
                sectionId: '',
                adpCode: template.adp_device_code || '',
                price: template.list_price || template.adp_price || 0,
                quantity: 1,
                buildType: '',
                rationale: '',
            });
        } else {
            // Template has configurable attributes — load them
            this._loadFrameAttributes(template.id);
        }
    },

    _loadFrameAttributes: function (templateId) {
        var self = this;
        this._rpc(this._apiUrl('get_product_attributes'), {
            template_id: templateId,
        }).then(function (attributes) {
            self._renderFrameConfigurator(attributes);
        }).catch(function (e) {
            console.error('Failed to load frame attributes:', e);
        });
    },

    _renderFrameConfigurator: function (attributes) {
        var configurator = this.el.querySelector('#frameConfigurator');
        var selectorsDiv = this.el.querySelector('#frameAttributeSelectors');
        if (!configurator || !selectorsDiv) return;

        selectorsDiv.innerHTML = '';

        if (!attributes || !attributes.length) {
            configurator.classList.add('d-none');
            return;
        }

        attributes.forEach(function (attr) {
            var col = document.createElement('div');
            col.className = 'col-md-4 col-sm-6';

            var html = '<div class="wc-config-attr-group">' +
                '<div class="wc-config-attr-label">' + attr.attribute_name + '</div>' +
                '<select class="form-select wc-frame-attribute-select"' +
                '    data-attribute-id="' + attr.attribute_id + '">' +
                '    <option value="">Select...</option>';

            attr.values.forEach(function (val) {
                html += '<option value="' + val.id + '">' + val.name + '</option>';
            });

            html += '</select></div>';
            col.innerHTML = html;
            selectorsDiv.appendChild(col);
        });

        configurator.classList.remove('d-none');
        // Reset variant info
        this.el.querySelector('#frameVariantInfo').classList.add('d-none');
        this.el.querySelector('#frameProductId').value = '';
    },

    _onFrameAttributeChange: function () {
        var self = this;
        var selects = this.el.querySelectorAll('.wc-frame-attribute-select');
        var allSelected = true;
        var selectedValueIds = [];

        selects.forEach(function (sel) {
            if (!sel.value) {
                allSelected = false;
            } else {
                selectedValueIds.push(parseInt(sel.value));
            }
        });

        if (!allSelected || selectedValueIds.length === 0) {
            this.el.querySelector('#frameVariantInfo').classList.add('d-none');
            this.el.querySelector('#frameProductId').value = '';
            return;
        }

        // All attributes selected — resolve the variant
        var tmplId = this.el.querySelector('#frameProductTmplId').value;
        this._resolveFrameVariant(parseInt(tmplId), selectedValueIds);
    },

    _resolveFrameVariant: function (templateId, attributeValueIds) {
        var self = this;
        this._rpc(this._apiUrl('resolve_variant'), {
            template_id: templateId,
            attribute_value_ids: attributeValueIds,
        }).then(function (result) {
            if (result.error) {
                console.warn('Variant resolution error:', result.error);
                return;
            }

            // Store the resolved variant ID
            self.el.querySelector('#frameProductId').value = result.id;

            // Show variant info
            var infoDiv = self.el.querySelector('#frameVariantInfo');
            var nameEl = self.el.querySelector('#frameVariantName');
            if (infoDiv && nameEl) {
                nameEl.textContent = result.name;
                infoDiv.classList.remove('d-none');
            }

            // Update the selected line with the resolved variant info
            var tmplName = self.el.querySelector('#selectedFrameName').textContent || '';
            self._addSelectedLine({
                productTmplId: templateId,
                productName: result.name || tmplName,
                sectionCode: 'frame',
                sectionId: '',
                adpCode: self.el.querySelector('#selectedFrameCode').textContent || '',
                price: result.list_price || 0,
                quantity: 1,
                buildType: '',
                rationale: '',
            });
        }).catch(function (e) {
            console.error('Variant resolution failed:', e);
        });
    },

    _onClearFrame: function () {
        this.el.querySelector('#frameProductTmplId').value = '';
        this.el.querySelector('#frameProductId').value = '';
        this.el.querySelector('#selectedFrame').classList.add('d-none');
        this.el.querySelector('#frameConfigurator').classList.add('d-none');
        this.el.querySelector('#frameVariantInfo').classList.add('d-none');
        this._removeSelectedLine('frame');
    },

    // =====================================================================
    // MEASUREMENT CHANGE & UPCHARGE CHECK
    // =====================================================================
    _onMeasurementChange: function () {
        var self = this;
        clearTimeout(this._upchargeTimer);
        this._upchargeTimer = setTimeout(function () {
            self._checkUpcharges();
        }, 500);
    },

    _checkUpcharges: function () {
        var self = this;
        var data = this._collectMeasurementData();

        this._rpc(this._apiUrl('check_upcharges'), {
            assessment_data: data,
        }).then(function (upcharges) {
            self._renderUpchargeBadges(upcharges);
        }).catch(function (e) {
            console.warn('Upcharge check error:', e);
        });
    },

    _collectMeasurementData: function () {
        var form = this.el.querySelector('#wcForm');
        var getVal = function (sel) {
            var el = form.querySelector(sel);
            return el ? el.value : '';
        };
        return {
            equipment_type: getVal('input[name="equipment_type"]') || 'manual_wheelchair',
            seat_width: getVal('input[name="seat_width"]') || 0,
            seat_width_unit: getVal('select[name="seat_width_unit"]') || 'inches',
            seat_depth: getVal('input[name="seat_depth"]') || 0,
            seat_depth_unit: getVal('select[name="seat_depth_unit"]') || 'inches',
            finished_back_height: getVal('input[name="finished_back_height"]') || 0,
            back_height_unit: getVal('select[name="back_height_unit"]') || 'inches',
            client_weight: getVal('input[name="client_weight"]') || 0,
            client_weight_unit: getVal('select[name="client_weight_unit"]') || 'lbs',
        };
    },

    _renderUpchargeBadges: function (upcharges) {
        // Clear existing badges
        this.el.querySelectorAll('.wc-upcharge-badge').forEach(function (b) {
            b.classList.add('d-none');
            b.textContent = '';
        });

        var preview = this.el.querySelector('#upchargePreview');
        var list = this.el.querySelector('#upchargeList');
        if (list) list.innerHTML = '';

        if (!upcharges || !upcharges.length) {
            if (preview) preview.classList.add('d-none');
            return;
        }

        if (preview) preview.classList.remove('d-none');

        var self = this;
        var fieldMap = {
            'seat_width': 'seat_width',
            'seat_depth': 'seat_depth',
            'client_weight': 'client_weight',
        };

        upcharges.forEach(function (u) {
            var inputField = u.measurement_field || '';
            if (inputField && fieldMap[inputField]) {
                var input = self.el.querySelector('input[data-upcharge-field="' + fieldMap[inputField] + '"]');
                if (input) {
                    var flex = input.closest('.d-flex');
                    var badge = flex ? flex.querySelector('.wc-upcharge-badge') : null;
                    if (badge) {
                        badge.classList.remove('d-none');
                        badge.className = 'wc-upcharge-badge badge text-bg-warning';
                        badge.textContent = u.adp_device_code + ' ($' + u.adp_price.toFixed(2) + ')';
                    }
                }
            }

            if (list) {
                var item = document.createElement('div');
                item.className = 'alert alert-warning py-1 px-2 mb-1';
                item.innerHTML = '<strong>' + u.adp_device_code + '</strong> \u2014 ' +
                    u.name + ' ($' + u.adp_price.toFixed(2) + ')';
                list.appendChild(item);
            }
        });
    },

    // =====================================================================
    // EQUIPMENT TYPE TOGGLE
    // =====================================================================
    /**
     * Read equipment type from hidden input and initialize filters.
     * Equipment type is now set server-side (hidden field), not via radio buttons.
     * Type switching happens on the list page via the "New Assessment" dropdown.
     */
    _onEquipmentTypeChange: function () {
        var hiddenInput = this.el.querySelector('input[name="equipment_type"]');
        var equipType = hiddenInput ? hiddenInput.value : '';

        // Filter seating/positioning sections by equipment type
        this._filterSeatingSections(equipType);

        // Reload ADP options and accessories for the equipment type
        this._reloadEquipmentOptions();
    },

    /**
     * Handle seating tab click — switch active tab and panel.
     */
    _onSeatingTabClick: function (ev) {
        var clickedBtn = ev.currentTarget;
        if (clickedBtn.classList.contains('active')) return;

        var container = clickedBtn.closest('.wc-seating-tabs');
        if (!container) return;

        // Deactivate all tabs and panels
        container.querySelectorAll('.wc-tab-btn.active').forEach(function (btn) {
            btn.classList.remove('active');
        });
        container.querySelectorAll('.wc-tab-panel.active').forEach(function (panel) {
            panel.classList.remove('active');
        });

        // Activate clicked tab
        clickedBtn.classList.add('active');

        // Activate corresponding panel
        var targetId = clickedBtn.dataset.bsTarget;
        if (targetId) {
            var panel = container.querySelector(targetId);
            if (panel) panel.classList.add('active');
        }
    },

    /**
     * Real-time filter for product option cards within a seating tab.
     * Filters by product name and ADP code as the user types.
     */
    _onOptionFilter: function (ev) {
        var input = ev.currentTarget;
        var query = input.value.toLowerCase().trim();
        var sectionContainer = input.closest('.wc-section-options');
        if (!sectionContainer) return;

        var cards = sectionContainer.querySelectorAll('.wc-options-grid > div');
        cards.forEach(function (col) {
            var card = col.querySelector('.wc-option-card');
            if (!card) { col.style.display = ''; return; }
            var searchText = card.dataset.searchText || '';
            col.style.display = (!query || searchText.indexOf(query) !== -1) ? '' : 'none';
        });
    },

    /**
     * Toggle collapsible section groups within a seating tab.
     * Accordion behaviour: opening one group closes the others.
     */
    _onGroupHeaderClick: function (ev) {
        var group = ev.currentTarget.closest('.wc-section-group');
        if (!group) return;
        var container = group.closest('.wc-section-groups');
        if (!container) return;

        if (group.classList.contains('open')) {
            // Close it
            group.classList.remove('open');
        } else {
            // Close all siblings, open this one
            container.querySelectorAll('.wc-section-group.open').forEach(function (g) {
                g.classList.remove('open');
            });
            group.classList.add('open');
        }
    },

    /**
     * Update the selection count badge on each section group header.
     * Called after any checkbox change via _syncSelectedLines.
     */
    _updateGroupCounts: function () {
        var groups = this.el.querySelectorAll('.wc-section-group');
        groups.forEach(function (group) {
            var count = group.querySelectorAll('.wc-option-check:checked').length;
            var badge = group.querySelector('.wc-group-count');
            if (badge) {
                badge.textContent = count;
            }
            group.classList.toggle('has-selection', count > 0);
        });
    },

    /**
     * Show/hide seating tab buttons and panels based on their equipment_type
     * data attribute. Also ensures the first visible tab is active.
     * Filtering rules:
     *   - 'both' → always visible (all equipment types)
     *   - 'wheelchair' → visible for manual_wheelchair and power_wheelchair
     *   - exact match → visible only for that specific equipment type
     *   - no attribute → always visible (fallback)
     */
    _filterSeatingSections: function (equipType) {
        var wheelchairTypes = ['manual_wheelchair', 'power_wheelchair'];
        var container = this.el.querySelector('.wc-seating-tabs');
        if (!container) return;

        var firstVisibleBtn = null;
        var hasActive = false;

        // Filter tab buttons
        var tabBtns = container.querySelectorAll('.wc-tab-btn');
        tabBtns.forEach(function (btn) {
            var sectionEquipType = btn.dataset.equipmentType;
            var show = false;
            if (!sectionEquipType || sectionEquipType === 'both') {
                show = true;
            } else if (sectionEquipType === 'wheelchair') {
                show = wheelchairTypes.indexOf(equipType) !== -1;
            } else {
                show = sectionEquipType === equipType;
            }
            btn.style.display = show ? '' : 'none';
            if (show && !firstVisibleBtn) firstVisibleBtn = btn;
            if (show && btn.classList.contains('active')) hasActive = true;
        });

        // Filter tab panels
        var tabPanels = container.querySelectorAll('.wc-tab-panel');
        tabPanels.forEach(function (panel) {
            var sectionEquipType = panel.dataset.equipmentType;
            var show = false;
            if (!sectionEquipType || sectionEquipType === 'both') {
                show = true;
            } else if (sectionEquipType === 'wheelchair') {
                show = wheelchairTypes.indexOf(equipType) !== -1;
            } else {
                show = sectionEquipType === equipType;
            }
            if (!show) {
                panel.style.display = 'none';
                panel.classList.remove('active');
            } else {
                panel.style.display = '';
            }
        });

        // If no tab is active, activate the first visible one
        if (!hasActive && firstVisibleBtn) {
            firstVisibleBtn.classList.add('active');
            var targetId = firstVisibleBtn.dataset.bsTarget;
            if (targetId) {
                var panel = container.querySelector(targetId);
                if (panel) panel.classList.add('active');
            }
        }
    },

    _reloadEquipmentOptions: function () {
        var self = this;
        var prefix = this._getEquipmentPrefix();

        // Clear and reload ADP options
        var adpGrid = this.el.querySelector('#adpOptionsGrid');
        if (adpGrid) adpGrid.innerHTML = '';
        this._rpc(self._apiUrl('get_section_options'), {
            section_code: prefix + '_adp_options',
        }).then(function (options) {
            self._renderAdpOptions(options);
        }).catch(function (e) {
            console.warn('Failed to reload ADP options:', e);
        });

        // Clear and reload accessories
        var accGrid = this.el.querySelector('#accessoriesGrid');
        if (accGrid) accGrid.innerHTML = '';
        this._rpc(self._apiUrl('get_section_options'), {
            section_code: prefix + '_accessories',
        }).then(function (options) {
            self._renderAccessoryOptions(options);
        }).catch(function (e) {
            console.warn('Failed to reload accessories:', e);
        });
    },

    // =====================================================================
    // RADIO BUTTON ACTIVE STATE  (fallback for :has() CSS)
    // =====================================================================
    _onRadioBtnChange: function (ev) {
        var self = this;
        var name = ev.target.name;
        this.el.querySelectorAll('.wc-radio-btn input[name="' + name + '"]').forEach(function (radio) {
            var btn = radio.closest('.wc-radio-btn');
            if (btn) self._applyRadioBtnStyle(btn, radio.checked);
        });

        // If this is a build-type radio, filter products in the matching section
        if (ev.target.classList.contains('wc-section-build-type')) {
            var sectionCode = ev.target.dataset.section;
            var selectedBuildType = ev.target.value;
            this._filterByBuildType(sectionCode, selectedBuildType);
        }
    },

    /**
     * Filter product cards by build type.
     * Finds the tab panel containing this section and filters ALL option cards
     * in the entire panel (main section + children share the same build type).
     */
    _filterByBuildType: function (sectionCode, buildType) {
        // Find the build-type radio, then walk up to the tab panel
        var radio = this.el.querySelector(
            '.wc-section-build-type[data-section="' + sectionCode + '"]'
        );
        var panel = radio ? radio.closest('.wc-tab-panel') : null;

        // Fallback: search the whole form
        var scope = panel || this.el;

        var cards = scope.querySelectorAll('.wc-option-card[data-build-types]');
        cards.forEach(function (card) {
            var cardBuild = card.dataset.buildTypes || 'both';
            var col = card.closest('[class*="col-"]');
            if (!col) col = card.parentElement;
            if (cardBuild === 'both' || cardBuild === buildType) {
                col.style.display = '';
            } else {
                col.style.display = 'none';
                // Uncheck hidden cards so they don't get submitted
                var cb = card.querySelector('.wc-option-check');
                if (cb && cb.checked) {
                    cb.checked = false;
                }
            }
        });

        this._syncSelectedLines();
        this._updateGroupCounts();
    },

    _syncRadioActiveState: function () {
        var self = this;
        this.el.querySelectorAll('.wc-radio-btn input[type="radio"]').forEach(function (radio) {
            var btn = radio.closest('.wc-radio-btn');
            if (btn) self._applyRadioBtnStyle(btn, radio.checked);
        });
    },

    _applyRadioBtnStyle: function (btn, isActive) {
        // Hardcoded colours — no CSS variable lookups that can fail
        var isSecondary = btn.classList.contains('btn-outline-secondary');
        var activeColor = isSecondary ? '#6c757d' : '#0d6efd';

        btn.classList.toggle('active', isActive);
        if (isActive) {
            btn.style.backgroundColor = activeColor;
            btn.style.color = '#fff';
            btn.style.borderColor = activeColor;
        } else {
            btn.style.backgroundColor = 'transparent';
            btn.style.color = activeColor;
            btn.style.borderColor = activeColor;
        }
    },

    // =====================================================================
    // SECTION OPTIONS RENDERING
    // =====================================================================
    _renderSectionOptions: function (container, options) {
        var self = this;
        var grid = container.querySelector('.wc-options-grid');
        if (!grid || !options || !options.length) return;

        options.forEach(function (opt) {
            var col = document.createElement('div');
            col.className = 'col-md-4 col-6';
            var displayName = self._cleanProductName(opt.product_name);
            var priceHtml = opt.adp_price ? '<span class="text-success wc-opt-price">$' + opt.adp_price.toFixed(2) + '</span>' : '';
            var adpHtml = opt.adp_device_code ? '<span class="text-muted wc-opt-adp">Code: ' + opt.adp_device_code + '</span>' : '';
            var metaParts = [];
            if (adpHtml) metaParts.push(adpHtml);
            if (priceHtml) metaParts.push(priceHtml);
            col.innerHTML =
                '<div class="wc-option-card wc-option-compact h-100" data-product-tmpl-id="' + opt.product_tmpl_id + '"' +
                '     data-section-id="' + (container.dataset.sectionId || '') + '"' +
                '     data-section-code="' + (container.dataset.section || '') + '"' +
                '     data-adp-code="' + (opt.adp_device_code || '') + '"' +
                '     data-price="' + (opt.list_price || 0) + '"' +
                '     data-build-types="' + (opt.available_build_types || 'both') + '"' +
                '     data-search-text="' + (opt.product_name + ' ' + (opt.adp_device_code || '')).toLowerCase().replace(/"/g, '') + '"' +
                '     data-rationale="' + (opt.requires_clinical_rationale ? '1' : '0') + '">' +
                '    <div class="form-check mb-0">' +
                '        <input class="form-check-input wc-option-check" type="checkbox"' +
                '            id="opt_' + opt.id + '" value="' + opt.product_tmpl_id + '"/>' +
                '        <label class="form-check-label wc-opt-label" for="opt_' + opt.id + '">' +
                             displayName +
                '        </label>' +
                '    </div>' +
                (metaParts.length ? '    <div class="wc-opt-meta">' + metaParts.join(' ') + '</div>' : '') +
                (opt.requires_clinical_rationale ?
                    '<div class="wc-rationale-field d-none mt-1">' +
                    '<input type="text" class="form-control form-control-sm" placeholder="Clinical rationale *"/>' +
                    '</div>' : '') +
                '</div>';

            var checkbox = col.querySelector('.wc-option-check');
            checkbox.addEventListener('change', function () {
                var card = col.querySelector('.wc-option-card');
                card.classList.toggle('border-primary', checkbox.checked);
                var rationaleField = card.querySelector('.wc-rationale-field');
                if (rationaleField) {
                    rationaleField.classList.toggle('d-none', !checkbox.checked);
                }
                self._syncSelectedLines();
            });

            grid.appendChild(col);
        });

        // Apply build-type filter for newly rendered options
        // The build-type radio might be for this section or a parent section
        var sectionCode = container.dataset.section;
        if (sectionCode) {
            var buildRadio = this.el.querySelector(
                '.wc-section-build-type[data-section="' + sectionCode + '"]:checked'
            );
            if (!buildRadio) {
                // Child section: find the build-type radio in the same tab panel
                var panel = container.closest('.wc-tab-panel');
                if (panel) {
                    buildRadio = panel.querySelector('.wc-section-build-type:checked');
                }
            }
            if (buildRadio) {
                this._filterByBuildType(buildRadio.dataset.section, buildRadio.value);
            }
        }
    },

    _renderAdpOptions: function (options) {
        var self = this;
        var grid = this.el.querySelector('#adpOptionsGrid');
        if (!grid || !options || !options.length) return;

        options.forEach(function (opt) {
            var col = document.createElement('div');
            col.className = 'col-12 col-sm-6 col-lg-4 mb-2';

            var card = document.createElement('div');
            card.className = 'wc-option-card p-2 border rounded h-100';
            card.style.cssText = 'display:flex;gap:8px;align-items:flex-start;cursor:pointer;';
            card.dataset.productTmplId = opt.product_tmpl_id;
            card.dataset.sectionCode = 'adp_options';
            card.dataset.adpCode = opt.adp_device_code || '';
            card.dataset.price = opt.list_price || 0;
            card.dataset.rationale = opt.requires_clinical_rationale ? '1' : '0';

            var cb = document.createElement('input');
            cb.type = 'checkbox';
            cb.className = 'wc-option-check';
            cb.id = 'adp_opt_' + opt.id;
            cb.value = opt.product_tmpl_id;
            cb.style.cssText = 'width:18px;height:18px;min-width:18px;margin-top:2px;cursor:pointer;accent-color:var(--bs-primary);';

            var displayName = self._cleanProductName(opt.product_name);

            var content = document.createElement('div');
            content.style.cssText = 'flex:1;min-width:0;';
            var lbl = document.createElement('label');
            lbl.className = 'wc-option-label';
            lbl.setAttribute('for', cb.id);
            lbl.style.cssText = 'font-size:0.82rem;line-height:1.35;cursor:pointer;display:block;';
            lbl.textContent = displayName;
            if (opt.requires_clinical_rationale) {
                lbl.innerHTML = lbl.textContent + ' <span class="text-danger fw-bold">*</span>';
            }
            content.appendChild(lbl);

            // Meta line: Code + price
            var metaParts = [];
            if (opt.adp_device_code) metaParts.push('<span class="text-muted">Code: ' + opt.adp_device_code + '</span>');
            if (opt.adp_price) metaParts.push('<span class="text-success">$' + opt.adp_price.toFixed(2) + '</span>');
            if (metaParts.length) {
                var meta = document.createElement('div');
                meta.className = 'wc-opt-meta';
                meta.style.cssText = 'font-size:0.7rem;line-height:1.2;';
                meta.innerHTML = metaParts.join(' ');
                content.appendChild(meta);
            }

            card.appendChild(cb);
            card.appendChild(content);

            if (opt.requires_clinical_rationale) {
                var rf = document.createElement('div');
                rf.className = 'wc-rationale-field d-none w-100';
                rf.style.marginTop = '6px';
                rf.innerHTML = '<input type="text" class="form-control form-control-sm" placeholder="Clinical rationale required *"/>';
                card.appendChild(rf);
            }

            // Click anywhere on card toggles checkbox
            card.addEventListener('click', function (e) {
                if (e.target === cb) return; // let native checkbox click work
                cb.checked = !cb.checked;
                cb.dispatchEvent(new Event('change'));
            });
            cb.addEventListener('change', function () {
                card.classList.toggle('border-primary', cb.checked);
                var rf = card.querySelector('.wc-rationale-field');
                if (rf) rf.classList.toggle('d-none', !cb.checked);
                self._syncSelectedLines();
            });

            col.appendChild(card);
            grid.appendChild(col);
        });
    },

    _renderAccessoryOptions: function (options) {
        var self = this;
        var grid = this.el.querySelector('#accessoriesGrid');
        if (!grid || !options || !options.length) return;

        options.forEach(function (opt) {
            var col = document.createElement('div');
            col.className = 'col-12 col-sm-6 col-lg-4 mb-2';

            var card = document.createElement('div');
            card.className = 'wc-option-card p-2 border rounded h-100';
            card.style.cssText = 'display:flex;gap:8px;align-items:flex-start;cursor:pointer;';
            card.dataset.productTmplId = opt.product_tmpl_id;
            card.dataset.sectionCode = 'accessories';
            card.dataset.adpCode = opt.adp_device_code || '';
            card.dataset.price = opt.list_price || 0;

            var cb = document.createElement('input');
            cb.type = 'checkbox';
            cb.className = 'wc-option-check';
            cb.id = 'acc_opt_' + opt.id;
            cb.value = opt.product_tmpl_id;
            cb.style.cssText = 'width:18px;height:18px;min-width:18px;margin-top:2px;cursor:pointer;accent-color:var(--bs-primary);';

            var displayName = self._cleanProductName(opt.product_name);

            var content = document.createElement('div');
            content.style.cssText = 'flex:1;min-width:0;';
            var lbl = document.createElement('label');
            lbl.className = 'wc-option-label';
            lbl.setAttribute('for', cb.id);
            lbl.style.cssText = 'font-size:0.82rem;line-height:1.35;cursor:pointer;display:block;';
            lbl.textContent = displayName;
            content.appendChild(lbl);

            // Meta line: Code + price
            var metaParts = [];
            if (opt.adp_device_code) metaParts.push('<span class="text-muted">Code: ' + opt.adp_device_code + '</span>');
            if (opt.adp_price) metaParts.push('<span class="text-success">$' + opt.adp_price.toFixed(2) + '</span>');
            if (metaParts.length) {
                var meta = document.createElement('div');
                meta.className = 'wc-opt-meta';
                meta.style.cssText = 'font-size:0.7rem;line-height:1.2;';
                meta.innerHTML = metaParts.join(' ');
                content.appendChild(meta);
            }

            card.appendChild(cb);
            card.appendChild(content);

            // Click anywhere on card toggles checkbox
            card.addEventListener('click', function (e) {
                if (e.target === cb) return;
                cb.checked = !cb.checked;
                cb.dispatchEvent(new Event('change'));
            });
            cb.addEventListener('change', function () {
                card.classList.toggle('border-primary', cb.checked);
                self._syncSelectedLines();
            });

            col.appendChild(card);
            grid.appendChild(col);
        });
    },

    // =====================================================================
    // LINE MANAGEMENT
    // =====================================================================
    _addSelectedLine: function (line) {
        this._removeSelectedLine(line.sectionCode);
        this.selectedLines.push(line);
    },

    _removeSelectedLine: function (sectionCode) {
        this.selectedLines = this.selectedLines.filter(function (l) {
            return l.sectionCode !== sectionCode;
        });
    },

    _syncSelectedLines: function () {
        var self = this;
        var checkedOptions = this.el.querySelectorAll('.wc-option-check:checked');

        // Keep frame line, remove all others
        var frameLine = this.selectedLines.find(function (l) {
            return l.sectionCode === 'frame';
        });
        this.selectedLines = frameLine ? [frameLine] : [];

        checkedOptions.forEach(function (cb) {
            var card = cb.closest('.wc-option-card');
            if (!card) return;

            var rationaleInput = card.querySelector('.wc-rationale-field input');
            var buildTypeInput = self.el.querySelector(
                '.wc-section-build-type[data-section="' + card.dataset.sectionCode + '"]:checked'
            );
            var labelEl = cb.closest('.form-check');
            var labelText = labelEl ? labelEl.querySelector('label') : null;

            self.selectedLines.push({
                productTmplId: card.dataset.productTmplId || '',
                productName: labelText ? labelText.textContent.trim() : '',
                sectionCode: card.dataset.sectionCode || '',
                sectionId: card.dataset.sectionId || '',
                adpCode: card.dataset.adpCode || '',
                price: parseFloat(card.dataset.price) || 0,
                quantity: 1,
                buildType: buildTypeInput ? buildTypeInput.value : '',
                rationale: rationaleInput ? rationaleInput.value : '',
            });
        });

        // Update collapsible group count badges
        this._updateGroupCounts();
    },

    _populateHiddenLineFields: function () {
        this._syncSelectedLines();

        var productIds = [];
        var sectionIds = [];
        var buildTypes = [];
        var quantities = [];
        var rationales = [];

        this.selectedLines.forEach(function (l) {
            productIds.push(l.productTmplId);
            sectionIds.push(l.sectionId);
            buildTypes.push(l.buildType);
            quantities.push(l.quantity);
            rationales.push(l.rationale);
        });

        this.el.querySelector('#lineProductIds').value = productIds.join(',');
        this.el.querySelector('#lineSectionIds').value = sectionIds.join(',');
        this.el.querySelector('#lineBuildTypes').value = buildTypes.join(',');
        this.el.querySelector('#lineQuantities').value = quantities.join(',');
        this.el.querySelector('#lineRationales').value = rationales.join('|||');
    },

    // =====================================================================
    // REVIEW SUMMARY
    // =====================================================================
    _buildReviewSummary: function () {
        this._syncSelectedLines();

        var tbody = this.el.querySelector('#reviewTableBody');
        if (!tbody) return;
        tbody.innerHTML = '';

        var total = 0;
        var self = this;

        this.selectedLines.forEach(function (line) {
            var tr = document.createElement('tr');
            var lineTotal = line.price * line.quantity;
            total += lineTotal;
            tr.innerHTML =
                '<td>' + line.sectionCode + '</td>' +
                '<td>' + line.productName + '</td>' +
                '<td>' + line.adpCode + '</td>' +
                '<td>' + (line.buildType || '-') + '</td>' +
                '<td class="text-end">' + line.quantity + '</td>' +
                '<td class="text-end">$' + lineTotal.toFixed(2) + '</td>';
            tbody.appendChild(tr);
        });

        this.el.querySelector('#reviewTotal').textContent = '$' + total.toFixed(2);

        // Measurements summary — dynamically collect all measurement inputs
        var measDiv = this.el.querySelector('#reviewMeasurements');
        if (measDiv) {
            var html = '<div class="row g-2">';
            var measInputs = self.el.querySelectorAll('.wc-measurement-input');
            if (measInputs.length > 0) {
                measInputs.forEach(function (input) {
                    var label = '';
                    var field = input.closest('.wc-measurement-field');
                    if (field) {
                        var labelEl = field.querySelector('.form-label');
                        label = labelEl ? labelEl.textContent.trim() : input.name;
                    } else {
                        label = input.name;
                    }
                    var unit = '';
                    var unitSelect = input.closest('.d-flex') ?
                        input.closest('.d-flex').querySelector('.wc-unit-select') : null;
                    if (unitSelect) {
                        unit = unitSelect.options[unitSelect.selectedIndex] ?
                            unitSelect.options[unitSelect.selectedIndex].text : '';
                    }
                    var val = input.value || '-';
                    html += '<div class="col-md-3"><strong>' + label + ':</strong> ' + val + ' ' + unit + '</div>';
                });
            } else {
                // Fallback: try known wheelchair fields
                var data = this._collectMeasurementData();
                var fields = [
                    ['seat_width', 'Seat Width', data.seat_width_unit],
                    ['seat_depth', 'Seat Depth', data.seat_depth_unit],
                    ['client_weight', 'Client Weight', data.client_weight_unit],
                ];
                fields.forEach(function (f) {
                    var input = self.el.querySelector('input[name="' + f[0] + '"]');
                    var val = input ? input.value : '-';
                    html += '<div class="col-md-3"><strong>' + f[1] + ':</strong> ' + (val || '-') + ' ' + f[2] + '</div>';
                });
            }
            html += '</div>';
            measDiv.innerHTML = html;
        }
    },

    // =====================================================================
    // FORM SUBMIT
    // =====================================================================
    _onClickGenerate: function (ev) {
        ev.preventDefault();
        this.el.querySelector('#formAction').value = 'generate';
        this._populateHiddenLineFields();
        this.el.querySelector('#wcForm').submit();
    },

    _onFormSubmit: function () {
        this._populateHiddenLineFields();
    },

    // =====================================================================
    // AUTO-SAVE
    // =====================================================================
    _autoSave: function (step) {
        var assessmentInput = this.el.querySelector('input[name="assessment_id"]');
        var assessmentId = assessmentInput ? assessmentInput.value : '0';
        if (!assessmentId || assessmentId === '0') return;

        this._rpc(this._apiUrl('save_step'), {
            assessment_id: parseInt(assessmentId),
            step: step,
        }).catch(function () {
            // Silent fail for auto-save
        });
    },

    // =====================================================================
    // JSONRPC HELPER
    // =====================================================================
    _rpc: function (url, params) {
        params = params || {};
        return fetch(url, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({
                jsonrpc: '2.0',
                method: 'call',
                id: new Date().getTime(),
                params: params,
            }),
        }).then(function (response) {
            if (!response.ok) {
                throw new Error('HTTP ' + response.status);
            }
            return response.json();
        }).then(function (data) {
            if (data.error) {
                console.error('RPC Error:', url, data.error);
                throw new Error(data.error.data ? data.error.data.message : (data.error.message || 'RPC Error'));
            }
            return data.result;
        });
    },
});

export default publicWidget.registry.WCAssessmentForm;
