/*
 * NGBVD Data Entry overview functional fixes.
 * Scope: JavaScript behaviour only. No UI/UX layout or styling changes.
 */
(function (window, document, $) {
    'use strict';

    if (!$) {
        return;
    }

    var nsRequest = null;

    function trim(value) {
        return $.trim(value || '');
    }

    function getCsrfToken() {
        return $('meta[name="csrf-token"]').attr('content') || $('input[name="_token"]').first().val() || '';
    }

    function normaliseItems(response) {
        if (!response) {
            return [];
        }
        if (Array.isArray(response)) {
            return response;
        }
        if (Array.isArray(response.data)) {
            return response.data;
        }
        if (Array.isArray(response.items)) {
            return response.items;
        }
        if (Array.isArray(response.results)) {
            return response.results;
        }
        return [];
    }

    function itemValue(item) {
        return item && (item.id || item.uuid || item.value || item.key || '');
    }

    function itemText(item) {
        return item && (item.name || item.title || item.label || item.text || item.value || '');
    }

    function destroySelectizeIfNeeded($select) {
        if ($select.length && $select[0] && $select[0].selectize) {
            $select[0].selectize.destroy();
        }
    }

    function refreshSelectizeIfAvailable($select) {
        // The project initializes .search-select globally. Triggering change is enough for the existing plugin flow.
        $select.trigger('change.select2').trigger('change');
    }

    function ensureCategorySelect() {
        var $category = $('#nstatuscategory');

        if (!$category.length) {
            $category = $('[name="ns_categornsy"]').first();
        }

        if (!$category.length) {
            var $container = $('#ns_category');
            if ($container.length) {
                $container.html('<select class="form-control search-select" name="ns_categornsy" id="nstatuscategory" data-national-status-category="true" required><option value="">Choose One</option></select>');
                $category = $('#nstatuscategory');
            }
        }

        if ($category.length && !$category.attr('id')) {
            $category.attr('id', 'nstatuscategory');
        }

        return $category;
    }

    function setSelectOptions($select, items, selectedValue, allowNoCategory) {
        var selected = selectedValue || $select.attr('data-selected') || $select.val() || '';
        var html = '<option value="">Choose One</option>';

        items.forEach(function (item) {
            var value = String(itemValue(item));
            var text = itemText(item);
            if (!value) {
                return;
            }
            html += '<option value="' + value.replace(/"/g, '&quot;') + '"' + (selected && String(selected) === value ? ' selected' : '') + '>' + text + '</option>';
        });

        // Selectize keeps its own hidden structure. Destroy it before rebuilding the underlying select.
        destroySelectizeIfNeeded($select);
        $select.html(html);

        if (allowNoCategory && items.length === 0) {
            $select.prop('required', false).removeAttr('required').attr('data-required-suspended', 'true');
        } else {
            $select.prop('required', true).attr('required', 'required').removeAttr('data-required-suspended');
        }

        if (selected && $select.find('option[value="' + String(selected).replace(/"/g, '\\"') + '"]').length) {
            $select.val(String(selected));
        }

        refreshSelectizeIfAvailable($select);
    }

    function syncSurvivorCode() {
        var ref = trim($('#crb_number').val());
        var $survivorCode = $('#survivor_code');

        if ($survivorCode.length && ref !== '') {
            $survivorCode.val(ref);
        }
    }

    function cascadeNationalityStatusCategory(preselectedValue) {
        var $status = $('#nstatus');
        var $category = ensureCategorySelect();

        if (!$status.length || !$category.length) {
            return;
        }

        var statusId = $status.val();
        var selected = preselectedValue || $category.attr('data-selected') || $category.val() || '';

        if (!statusId) {
            setSelectOptions($category, [], selected, true);
            return;
        }

        if (nsRequest && nsRequest.readyState !== 4) {
            nsRequest.abort();
        }

        $category.prop('disabled', true).attr('data-disabled-for-loading', 'true');

        nsRequest = $.ajax({
            type: 'GET',
            url: window.NGBVD_FIND_NS_CATEGORY_URL || '/findNSCategory',
            data: { id: statusId },
            headers: { 'X-CSRF-TOKEN': getCsrfToken(), 'Accept': 'application/json' }
        }).done(function (response) {
            var items = normaliseItems(response);
            setSelectOptions($category, items, selected, true);
        }).fail(function (xhr, status) {
            if (status === 'abort') {
                return;
            }
            // Do not block saving because of a lookup failure. Leave the field optional only for this request failure.
            setSelectOptions($category, [], selected, true);
        }).always(function () {
            $category.prop('disabled', false).removeAttr('data-disabled-for-loading');
        });
    }

    function updateReporterRelationshipRequired() {
        var reporterType = $('input[name="reporter_type"]:checked').val();
        var $relation = $('[name="reporter_relation"]').first();

        if (!$relation.length) {
            return;
        }

        if (String(reporterType) === '2') {
            $relation.prop('required', true).attr('required', 'required');
        } else {
            $relation.prop('required', false).removeAttr('required');
        }
    }

    function prepareFormForSubmit($form) {
        syncSurvivorCode();
        updateReporterRelationshipRequired();

        var $category = ensureCategorySelect();
        if ($category.length) {
            $category.prop('disabled', false).removeAttr('data-disabled-for-loading');
            if (!$category.val() && $category.find('option').filter(function () { return trim($(this).val()) !== ''; }).length === 0) {
                $category.prop('required', false).removeAttr('required').attr('data-required-suspended', 'true');
            }
        }

        var $action = $form.find('input[name="action"]').first();
        if (!$action.length) {
            $action = $('<input type="hidden" name="action" id="action">').appendTo($form);
        }
        if (!$action.val()) {
            $action.val('save_continue');
        }
    }

    function boot() {
        // Namespaced handlers are used so reloading partials does not create duplicate handlers.
        $(document)
            .off('.ngbvdOverviewFix')
            .on('input.ngbvdOverviewFix keyup.ngbvdOverviewFix change.ngbvdOverviewFix paste.ngbvdOverviewFix', '#crb_number', function () {
                setTimeout(syncSurvivorCode, 0);
            })
            .on('change.ngbvdOverviewFix', '#nstatus', function () {
                cascadeNationalityStatusCategory(null);
            })
            .on('change.ngbvdOverviewFix', 'input[name="reporter_type"]', updateReporterRelationshipRequired)
            .on('click.ngbvdOverviewFix', 'form#indexform button[type="submit"], form.ngbvd-form-section button[type="submit"]', function () {
                prepareFormForSubmit($(this).closest('form'));
            })
            .on('submit.ngbvdOverviewFix', 'form#indexform, form.ngbvd-form-section', function () {
                prepareFormForSubmit($(this));
                return true;
            });

        syncSurvivorCode();
        updateReporterRelationshipRequired();

        var $status = $('#nstatus');
        var $category = ensureCategorySelect();
        if ($status.length && $status.val()) {
            var hasRealCategory = $category.find('option').filter(function () { return trim($(this).val()) !== ''; }).length > 0;
            if (!hasRealCategory) {
                cascadeNationalityStatusCategory($category.attr('data-selected') || null);
            }
        }
    }

    $(document).ready(boot);
})(window, document, window.jQuery);
