{{--* Interactions *--}}
<script>
    $(document).ready(function () {
      //- Initial Loading
        $('#credit_days_block, #due_date_block, #accordion-tax-global').toggle(false);

      //- Elements
        // Toggle Accordions with custom Header
        $(document).on('click', '.title-decorators', function () {
            const $accordionItem = $(this).closest('.accordion-item');
            const $collapse = $accordionItem.find('.accordion-collapse');

            $collapse.collapse('toggle');
        });

      //- Inputs
        $(function () {
            $('#is_moral_person').on('change', toggleTaxFormats);
            $('#tax_identifier').on('change', toggleGlobalSection);
            $('#individual_country').on('change', toggleCountryRequirement);
            $('#invoice_type').on('change', defineInvoiceRequirements);
            $('#currency').on('change', defineExchangeRate);
            $('#payment_method').on('change', definePaymentModel);
            $('#due_date, #credit_days, #date').on('change', defineDueDate);
        });

        // On change important texts
        $('.tax-text').on('input change keyup paste', function () {
            $(this).val($(this).val().toUpperCase());
        });

        $(document).on('paste', 'input, textarea', function (e) {
            e.preventDefault();

            let value = (e.originalEvent || e).clipboardData.getData('text');
            value = cleanPastedValues(value);

            $(this).val(value);
        });
    });
</script>

{{--* Triggered Functions *--}}
<script>
    function toggleTaxFormats() {
        const is_moral = $('#is_moral_person').prop('checked');

        // Define fields requirements and values
        const prefix = is_moral ? 'Moral' : 'Physical';
            window[`define${prefix}TaxIdFormat`]('tax_identifier');
            window[`define${prefix}TaxSystems`]('tax_system');
            window[`define${prefix}CfdiUses`]('cfdi_use');

        // Visual Adjustments
        $('#tax_person_type').text(is_moral ? "Moral" : "Física");
        toggleCountryRequirement();
    }

    function toggleGlobalSection() {
      // Sections
        const $globalAccordion = $('#accordion-tax-global');
        const $globalFormFields = $globalAccordion.find('input, select, textarea');

      // Control Variables
        const receiver_rfc = $('#tax_identifier').val();
        const is_generic_rfc = receiver_rfc === "XAXX010101000";

      // Cases
        if (!is_generic_rfc) {
            $('#individual_zip, #tax_system, #cfdi_use')
                .prop({ readonly: false, disabled: false }).removeClass('disabled-fields');

            $globalAccordion.hide();
            $globalFormFields.prop('disabled', true);
        } else {
            $('#cfdi_use').val("S01").prop({ readonly: true, disabled: true }).addClass('disabled-fields');
            $('#individual_zip').val(@json($establishment->zip)).prop({ readonly: true, disabled: true }).addClass('disabled-fields');
            $('#tax_system').val("616").prop({ readonly: true, disabled: true }).addClass('disabled-fields');

            $globalAccordion.show();
            $globalFormFields.prop('disabled', false);
        }
    }

    function toggleCountryRequirement() {
        const country = $('#individual_country').val();
        const is_mex_receiver = country === "MEX";

        if (is_mex_receiver) {
            $('#tax_identifier, #individual_zip, #tax_system, #cfdi_use').trigger('change')
                .prop({ readonly: false, disabled: false }).removeClass('disabled-fields');
        } else {
            $('#cfdi_use').val("S01").prop({ readonly: true, disabled: true }).addClass('disabled-fields');
            $('#individual_zip').val("00000").prop({ readonly: true, disabled: true }).addClass('disabled-fields');
            $('#tax_identifier').val("XEXX010101000").trigger('change').prop({ readonly: true, disabled: true }).addClass('disabled-fields');
            $('#tax_system').val("616").prop({ readonly: true, disabled: true }).addClass('disabled-fields');
        }
    }

    function defineInvoiceRequirements() {
        const invoice_type = $('#invoice_type').val();

        const $export = $('#export');
        const $payment_method = $('#payment_method');
        const $payment_form = $('#payment_form');

        const allow_export = ['I', 'E'].includes(invoice_type);
        const allow_payment_config = ['I', 'E', 'N'].includes(invoice_type);

        if (allow_export) {
            $export.prop({ readonly: false, /* disabled: false */ }).removeClass('disabled-fields');
        } else {
            $export.prop({ readonly: true, /* disabled: true */ }).addClass('disabled-fields')
                .val('01');
        }

        if (allow_payment_config) {
            $payment_method.prop({ readonly: false, /* disabled: false */ }).removeClass('disabled-fields');
            $payment_form.prop({ readonly: false, /* disabled: false */ }).removeClass('disabled-fields');
        } else {
            $payment_form.prop({ readonly: true, /* disabled: true */ }).addClass('disabled-fields');
            $payment_method.prop({ readonly: true, /* disabled: true */ }).addClass('disabled-fields')
                .val('PUE').trigger('change');
        }
    }


    function defineExchangeRate(){
      // Get selected currency
        const selected_currency = $('#currency').val();
        const $exchange_rate = $('#exchange_rate');

      // Mexican Currency
        if (selected_currency  === "MXN") {
            $exchange_rate.val('1.00').prop('readonly', true).toggleClass('disabled-fields');
            return;
        }

      // Foreign Currency
        $.ajax({
            url: `/banxico/${selected_currency}`,
            method: 'GET',
            beforeSend: function(){
                // Transform input into text input temporary
                $exchange_rate.attr('type','text')
                    .val("{{__('common_responses_and_messages')['loading']}}")
                    .prop('readonly',true)
                    .toggleClass('disabled-fields');
            },

            success: function(response){
                // Reset input text
                $exchange_rate.attr('type','number');

                // On success request
                if(response.status === 'ok'){
                    $exchange_rate.val(response.rate).prop('readonly', false)
                        .removeClass('disabled-fields');
                    return;
                }

                // Fallback
                $exchange_rate.val('').prop('readonly',false)
                    .removeClass('disabled-fields').focus();

            },
            error: function(){
                $exchange_rate.val('').prop('readonly', false)
                    .toggleClass('disabled-fields');
            }
        });

    }

    function definePaymentModel() {
        const is_deferred_payment = $('#payment_method').val() === 'PPD';
        const $payment_form = $('#payment_form');
        const $credit_days = $('#credit_days');
        const $due_date = $('#due_date');

        $('#credit_days_block, #due_date_block').toggle(is_deferred_payment);

        $payment_form
            .val(is_deferred_payment ? '99' : '')
            .prop('readonly', is_deferred_payment).toggleClass('disabled-fields', is_deferred_payment);

        $credit_days
            .val(null).trigger('change')
            // .val('30').trigger('change')
            .prop({
                // required: is_deferred_payment,
                readonly: !is_deferred_payment,
                disabled: !is_deferred_payment
            });

        $due_date.prop({
            // required: is_deferred_payment,
            readonly: true,
            disabled: !is_deferred_payment
        });

    }

    function defineDueDate() {
        const $date = $('#date');
        const $due_date = $('#due_date');
        const $credit_days = $('#credit_days');

        const base = moment($date.val(), moment.ISO_8601, true);
        let credit = parseInt($credit_days.val(), 10);

        if (!base.isValid()) {
            $due_date.val('');
            return;
        }

        // if (isNaN(credit) || credit < 0) credit = 0;
        if (isNaN(credit) || credit < 0) {
            $due_date.val(null); return;
        }

        // Agrupar por meses y agregar días restantes
        const months = Math.floor(credit / 30);
        const days = credit % 30;

        const result = base.clone()
            .add(months, 'months')  // respeta Febrero/año bisiesto (p. ej. 31-ene + 1 mes = 29-feb en 2024)
            .add(days, 'days');

        $due_date.val(result.format('YYYY-MM-DD'));
    }
</script>

{{--* Secondary Tables *--}}
<script>
  //* Shared
    function removeRow(row, colspan, {is_concepts_table = false} = {}) {
        const row_to_delete = $(row).closest('tr'); // Fila a eliminar
        const tbody = row_to_delete.closest('tbody'); // TBody Correspondiente

        // Eliminamos Fila
        row_to_delete.remove(); // Eliminar Fila

        // Revisamos si aun hay filas en la tabla
        const remaining_rows = tbody.find('tr').length;

        // Si no quedan filas, dibujar mensaje por defecto
        if (remaining_rows === 0) {
            if (is_concepts_table) {
                restoreConceptsSection();
            }else {
                $(`#${tbody.attr('id')}`).html(`
                    <tr>
                        <td colspan="${colspan}" class="pt-4 pb-3">
                            ${translateAndReplace('data_tables.sEmptyTable')}
                        </td>
                    </tr>
                `)
            }
        }

        launchSwalToast(
            'success',
            "{{ __('common_responses_and_messages')['deleted_successfully'] }}",
        );

        // Update Draft if concept table was edited
        if (is_concepts_table) {
            setTimeout(() => syncDraftData(false), 1000);
        }
    }
</script>

{{--* Receivers Section *--}}
<script>
    // General Control
    $(document).ready(function () {
      // Initial Loading
        defineMoralTaxIdFormat("tax_identifier");
        defineMoralTaxSystems("tax_system");
        defineMoralCfdiUses("cfdi_use");

        definePostalCodeFormat("individual_zip");
        restoreReceiverSection();

      // Searchbar
        $('#search_receiver').select2({
            placeholder: "Buscar Existente...",
            allowClear: false,
            minimumInputLength: 3,

            ajax: {
                url: "{{ route('tax-clients.find') }}",
                dataType: 'json',
                delay: 250,
                data: params => ({ q: params.term || '', page: params.page || 1 }),
                processResults: (data, params) => ({
                    results: data.results,
                    pagination: { more: data.pagination.more }
                }),
                cache: true
            },
            width: '100%',
        });

        $('#search_receiver').on('select2:select', async function (e) {
            // Control Data
            const meta = e.params.data.meta || {}; // Parse Data

            // Visual Changes
            $(this).val(null).trigger('change');
            $('#receiver-form, #clean_receiver_data').show();
            $('#receiver-empty, #search_receiver_block, #register_receiver_data').hide();

            // Seed Form
            $('#is_moral_person').prop('checked', meta.is_moral).trigger('change');
            $('#individual_country').val(meta.tax_address?.country || '').selectpicker('refresh').trigger("change");

            $('#tax_identifier').val(meta.tax_id || '').trigger('change');
            $('#client_id').val(e.params.data.id);

            $('#legal_name').val(meta.legal_name || meta.client_name || '');
            $('#tax_system').val(meta.tax_system || '');
            $('#cfdi_use').val(meta.cfdi_use || '');

            $('#email_billing').val(meta.email_billing || meta.client_email || '');
            $('#phone_billing').val(meta.client_phone || '');
            $('#individual_zip').val(meta.zip || '');

            $('#individual_street').val(meta.tax_address?.street || '');
            $('#individual_int_number').val(meta.tax_address?.interior || '');
            $('#individual_ext_number').val(meta.tax_address?.exterior || '');
            $('#individual_city').val(meta.tax_address?.city || '');
            $('#individual_municipality').val(meta.tax_address?.municipality || '');
            $('#individual_state').val(meta.tax_address?.state || '');

            try{
                await loadNeighborhoodsFromPostaliaOrFail(
                    meta.zip,
                    meta.tax_address?.neighborhood,
                    $('#individual_neighborhood'));
            }catch(error){
                console.error(error.message);
            }

            launchSwalToast(
                'success',
                "{{ __('common_responses_and_messages')['created_successfully'] }}"
            );

            setTimeout(() => syncDraftData(false), 1000);
        });
    });

    // Support
    function cleanReceiverData() {
        restoreReceiverSection();

        launchSwalToast(
            'success',
            "{{ __('common_responses_and_messages')['applying_changes'] }}"
        );
    }

    function restoreReceiverSection() {
        // Visual Changes
        $('#receiver-form, #clean_receiver_data').toggle(!window.allow_clean_receiver_section); // Hide for Create
        $('#receiver-empty, #search_receiver_block, #register_receiver_data').toggle(window.allow_clean_receiver_section); // Show for Create

        // Seed Form
        if (window.allow_clean_receiver_section) {
            $('#is_moral_person').prop('checked', false).trigger('change');
            $(`
                #client_id, #legal_name, #tax_system, #cfdi_use,
                #email_billing, #phone_billing, #individual_zip,
                #individual_street, #individual_int_number, #individual_ext_number,
                #individual_city, #individual_municipality, #individual_state
            `).val('');
            $('#tax_identifier').val("").trigger("change");
            $('#individual_country').val("").selectpicker('refresh').trigger("change");
            $('#individual_neighborhood').empty().selectpicker('refresh');
        }

        window.allow_clean_receiver_section = true;
    }
</script>

{{--* Concepts Section *--}}
<script>
    // General Control
    $(document).ready(function () {
      // Initial Loading
        restoreConceptsSection();

      // Searchbar
        $('#search_concept').select2({
            placeholder: "Buscar Existente...",
            allowClear: false,
            minimumInputLength: 2,

            ajax: {
                url: "{{ route('tax-prod-servs.find') }}",
                dataType: 'json',
                delay: 300,

                data: params => ({ q: params.term || '', page: params.page || 1 }),
                processResults: (data, params) => ({
                    results: data.results,
                    pagination: { more: data.pagination.more }
                }),
                cache: true
            },
            width: '100%',
        });

        $('#search_concept').on('select2:select', async function (e) {
          // Control Data
            const meta = e.params.data.meta || {};

          // Visual Changes
            $(this).val(null).trigger('change'); // Clean Select
            $('#external_concept_submit').prop('disabled', true); // Disable concept submit button

            window.loader.show(); // Start Loader
            window.conceptModalContext.skipResetOnOpen = true;
            initConceptSelect2Once();

            try {
              // Seed sync fields
                $('#sku_concept_block').show();
                $('#sku').val(e.params.data.id);
                $('#concept_description').val(meta.description);

                $('#concept_prod_serv_id').val(meta.id);
                $('#concept_name').val(meta.name);

              // Define async tasks (Seeds Select2s)
                const tasks = [
                    preloadSelect2('#concept_prod_serv_key', meta.prod_serv_key, {
                        fetchUrl: "{{ route('catalogs.prod-serv.find') }}"
                    }),
                    preloadSelect2('#concept_unit_key', meta.unit_key, {
                        fetchUrl: "{{ route('catalogs.units.find') }}"
                    })
                ];

              // Await Task executions
                await Promise.all(tasks);

              // Fill depended fields
                $('#concept_sat_description').val(meta.sat_description);
                $('#concept_object_tax').val(meta.object_tax).trigger('change');

              // Fill Taxes Table
                // Federal Taxes
                const taxes = meta.tax_profile.taxes;
                const wh_taxes = meta.tax_profile.withholding_taxes;

                    if(taxes.iva !== null && meta.object_tax != "04") // IVA Trasladado (Solo se dibuja si el ObjetoImpuesto no es 04-Si objeto, no impuestos)
                        await buildTaxRow(tax_types_keys.iva, taxes.iva.rate, {show_toast: false});
                    if(taxes.ieps !== null) // IEPS Trasladado
                        await buildTaxRow(tax_types_keys.ieps, taxes.ieps.rate, {show_toast: false});

                    if(wh_taxes.isr !== null) // ISR Retenido
                        await buildTaxRow(tax_types_keys.isr, wh_taxes.isr.rate, {show_toast: false});
                    if(wh_taxes.iva !== null) // IVA Retenido
                        await buildTaxRow(tax_types_keys.iva, wh_taxes.iva.rate, {is_iva_tr: false, show_toast: false});

                // Local Taxes
                const local_taxes = meta.local_tax_profile?.transferred ?? [];
                local_taxes.forEach(ltx => {
                    buildLocalTaxRow(ltx.name, "tr", ltx.rate, {tax_application_form = quantity_application_types.percentage, show_toast = false} = {})
                });

                const wh_local_taxes = meta.local_tax_profile?.withheld ?? [];
                wh_local_taxes.forEach(ltx => {
                    buildLocalTaxRow(ltx.name, "rt", ltx.rate, {tax_application_form = quantity_application_types.percentage, show_toast = false} = {})
                });

              // Fill Totals and Prices
                $('#total_illusionary, #subtotal_illusionary').text(meta.total);
                $('#total, #subtotal').val(meta.total);

                $('#concept_unit_price').val(meta.unit_price).trigger('change');
                $('#concept_quantity').val(1).trigger('change');

            } finally {
              // Reset window constants
                window.loader.hide(); // Close loader
                window.conceptModalContext.skipResetOnOpen = false;

              // Repair view
                window.conceptModalContext.allowDbStorage = false;
                $('#conceptFormModal').modal('show'); // Display Concept Form Modal
                $('#external_concept_submit').prop('disabled', false);
            }
        });
    });

    // CRUD Actions
    function restoreConceptsSection() {
        $('#concepts-table-body').html(`
            <tr>
                <td colspan="8" class="pt-4 pb-3">
                    ${translateAndReplace('data_tables.sEmptyTable')}
                </td>
            </tr>
        `);

        $('#concepts-table-footer').html(`
            <tr>
                <td colspan="7" class="py-0 text-end minus-title">
                    Subtotal
                </td>
                <td id="visual_subtotal">{{ $default_price }}</td>
            </tr>

            <tr>
                <td colspan="7" class="py-0 text-end visual-title">
                    Total
                </td>
                <td id="visual_total">{{ $default_price }}</td>
            </tr>
        `);

        $('#invoice_subtotal, #invoice_total').val('0.00'). trigger('change');

        return;
    }

    async function editConcept(btn, hashed_data, is_editing = true) {
      //- Control Data
        const byte_data = CryptoJS.AES.decrypt(hashed_data || "", window.tax_decrypt_data);
        const concept_data = JSON.parse(byte_data.toString(CryptoJS.enc.Utf8) || "{}");

      //- Internal Control
        let lineNumber = "";

        if (btn && typeof btn?.closest === 'function') { // Extract from row
            const row = btn.closest('tr');
            const current_line = $(btn).closest('tr').find('input[name="line_numbers[]"]').val();

            if(is_editing)
                lineNumber = current_line;
            else
                lineNumber = "";

        } else if(is_editing && window.conceptModalContext.lineNumber) { // Use stored data
            lineNumber = window.conceptModalContext.lineNumber;
        }
        window.conceptModalContext.lineNumber = lineNumber;

      //- Visual Changes
        $('#external_concept_submit').prop('disabled', true); // Disable concept submit button

        window.loader.show(); // Start Loader
        window.conceptModalContext.skipResetOnOpen = true;
        window.conceptModalContext.isEditing = is_editing;
        initConceptSelect2Once();

        try {
          //- Seed independent fields
            $('#sku').val(hashed_data);
            $('#concept_description').val(concept_data.concept_description);

            $('#concept_prod_serv_id').val(concept_data.concept_prod_serv_id);
            $('#concept_name').val(concept_data.concept_name);

            $('#third_account_tax_identifier').val(concept_data.third_account_tax_identifier);
            $('#third_account_legal_name').val(concept_data.third_account_legal_name);
            $('#third_account_tax_system').val(concept_data.third_account_tax_system);
            $('#third_account_zip').val(concept_data.third_account_zip);

            $('#concept_property_tax_account').val(concept_data.concept_property_tax_account);

          //- Define async tasks (Seeds Select2s)
            const tasks = [
                preloadSelect2('#concept_prod_serv_key', concept_data.concept_prod_serv_key, {
                    fetchUrl: "{{ route('catalogs.prod-serv.find') }}"
                }),
                preloadSelect2('#concept_unit_key', concept_data.concept_unit_key, {
                    fetchUrl: "{{ route('catalogs.units.find') }}"
                })
            ];

            // Await Task executions
            await Promise.all(tasks);

          //- Fill depended fields
            $('#concept_sat_description').val(concept_data.concept_sat_description);
            $('#concept_object_tax').val(concept_data.concept_object_tax).trigger('change');

            // Fill Taxes Table
                const tx_applications = concept_data.tax_application_summary || [];
                const taxes = concept_data.tax_summary || [];
                const tx_quotes = concept_data.rate_quotes_summary || [];

                for (let i = 0; i < taxes.length; i++) {
                    const is_transfer = tx_applications[i] === format_types_keys.transfer;

                    // IVA Trasladado (Solo se dibuja si el ObjetoImpuesto no es 04-Si objeto)
                    if(is_transfer && taxes[i] === tax_types_keys.iva && concept_data.concept_object_tax != "04")
                        await buildTaxRow(tax_types_keys.iva, tx_quotes[i], {show_toast: false});
                    // IEPS Trasladado
                    if(is_transfer && taxes[i] === tax_types_keys.ieps)
                        await buildTaxRow(tax_types_keys.ieps, tx_quotes[i], {show_toast: false});

                    // ISR Retenido
                    if(!is_transfer && taxes[i] === tax_types_keys.isr)
                        await buildTaxRow(tax_types_keys.isr, tx_quotes[i], {show_toast: false});
                    // IVA Retenido
                    if(!is_transfer && taxes[i] === tax_types_keys.iva)
                        await buildTaxRow(tax_types_keys.iva, tx_quotes[i], {is_iva_tr: false, show_toast: false});
                }


            // Fill Local Taxes Table
                const ltx_applications = concept_data.local_tax_application_summary || [];
                const local_taxes = concept_data.local_tax_names_summary || [];
                const ltx_quotes = concept_data.local_rate_quotes_summary || [];

                for (let i = 0; i < local_taxes.length; i++) {
                    const is_transfer = ltx_applications[i] === format_types_keys.transfer;
                    await buildLocalTaxRow(local_taxes[i], ltx_applications[i], ltx_quotes[i]);
                }

            // Fill Prices & Quantities
            $('#concept_unit_price').val(concept_data.concept_unit_price);
            $('#concept_quantity').val(concept_data.concept_quantity);
            $('#discount_format').val(concept_data.discount_format);
            $('#concept_discount_rate').val(concept_data.concept_discount_rate);
            $('#concept_discount').val(concept_data.concept_discount).trigger('change');

        } finally {
          //- Reset window constants
            window.loader.hide(); // Close loader
            window.conceptModalContext.skipResetOnOpen = false;

            // Repair view
            window.conceptModalContext.allowDbStorage = false;
            $('#conceptFormModal').modal('show'); // Display Concept Form Modal
            $('#external_concept_submit, #concept-modal-title-action').text(
                is_editing ? "{{ __('common_actions')['update'] }}" : "{{ __('common_actions')['add'] }}"
            );
            $('#external_concept_submit').prop('disabled', false);
        }
    }

    // Support
    function calculateInvoiceTotal() {
      //* Control Data
        // Accumulators Control
        let subtotal  = 0.0; // Subtotal por Conceptos
        let total = 0.0; // Total por Conceptos con Impuestos

        // Taxes Breakdown
        const tax_footer_summary = { transfers: new Map(), withholdings: new Map() }; // Desglose de Impuestos Federales
        const local_tax_footer_summary = { transfers: new Map(), withholdings: new Map() }; // Desglose de Impuestos Locales
            /* transfers || withholdings: [
                { name: "", rate: "0.000000", charge: 0.00 },
                ...
            ]*/

        // Visual controls
        const $concepts_tbody = $('#concepts-table-body'); // Body of Table (Concepts)
        const $concepts_tfoot = $('#concepts-table-footer'); // Footer of Table (Concepts)

      //* Helpers
        // Acumulación y claves
            const build_tax_key = (name, rate) => `${name}||${Number(rate ?? 0).toFixed(6)}`;

            const accumulate_tax = (summary_tax_map, { is_transfer, name, rate, charge }) => {
                const bucket = is_transfer ? summary_tax_map.transfers : summary_tax_map.withholdings;
                const key = build_tax_key(name, rate);
                const prev = bucket.get(key);
                const new_charge = (prev?.charge ?? 0) + Number(charge ?? 0);

                bucket.set(key, {
                    name,
                    rate: Number(rate ?? 0),
                    charge: new_charge,
                });
            };

            const maps_to_list = (summary_tax_map) => {
                return ['transfers', 'withholdings'].flatMap(type => Array.from(summary_tax_map[type].values()));
            };


        // Renderizado
            const draw_tax_row = (tax_data = {}, is_low_decimal = true) => {
                return `
                    <tr>
                        <td colspan="7" class="py-0 text-end minus-title">
                            ${tax_data?.name}
                            ${
                                parseFloat(tax_data?.rate).toFixed(2) === '0.00'
                                    ?  `- 0.00%` //`- Exento`
                                    : strToStrPercentage(tax_data?.rate, {is_low_decimal})
                            }
                        </td>
                        <td id="visual_subtotal">${formatCurrency((tax_data?.charge ?? 0).toFixed(2))}</td>
                    </tr>
                `;
            }

            const draw_full_tax_summary = (summary_tax_map, decimal_percentage = true) => {
                return maps_to_list(summary_tax_map)
                    .map(tax_data => draw_tax_row(tax_data, decimal_percentage)).join('');
            };

      //* Calculate Totals
        $concepts_tbody.find('tr').each(function () {
          // Extract Data
            const $row = $(this);
            const concept_data = $row.find('input[name="concept_summary[]"]').val();

            const byte_data = CryptoJS.AES.decrypt(concept_data || "", window.tax_decrypt_data);
            const parsed_data = JSON.parse(byte_data.toString(CryptoJS.enc.Utf8) || "{}");

          // Calculate Totals
            const concept_subtotal = parseFloat(parsed_data.subtotal ?? 0.00);
            const concept_discount_rate = parseFloat(parsed_data.concept_discount_rate ?? 0.00);

            subtotal += parseFloat(concept_subtotal - concept_discount_rate); // Update Subtotal
            total += parseFloat(parsed_data.total ?? 0.00); // Update Total

          // Break down Taxes
            const tax_applications = parsed_data.tax_application_summary ?? [];
            const taxes = parsed_data.tax_summary ?? [];
            const tax_quotes = parsed_data.rate_quotes_summary ?? [];
            const tax_charges = parsed_data.tax_charges_summary ?? [];

            for (let i = 0; i < taxes.length; i++) {
                const is_transfer = tax_applications[i] === format_types_keys.transfer;
                const type_text = is_transfer ? "Trasladado" : "Retenido";

                accumulate_tax(tax_footer_summary, {
                    is_transfer,
                    name: `${defineTaxName(taxes[i])} ${type_text}`,
                    rate: tax_quotes[i],
                    charge: parseFloat(tax_charges[i]),
                });
            }

          // Break down Taxes
            const ltx_applications = parsed_data.local_tax_application_summary ?? [];
            const local_taxes = parsed_data.local_tax_names_summary ?? [];
            const ltx_quotes = parsed_data.local_rate_quotes_summary ?? [];
            const ltx_charges = parsed_data.local_tax_charges_summary ?? [];

            for (let j = 0; j < local_taxes.length; j++) {
                const is_transfer = ltx_applications[j] === format_types_keys.transfer;
                const type_text = `Impuesto Local ${is_transfer ? "Trasladado" : "Retenido"}`;

                accumulate_tax(local_tax_footer_summary, {
                    is_transfer,
                    name: `${type_text} (${(local_taxes[j] ?? '').toString().trim()})`,
                    rate: ltx_quotes[j],
                    charge: parseFloat(ltx_charges[j]),
                });
            }
        });

      //* Render Totals Footer
        // Visual Data
        subtotal_display = formatCurrency(subtotal.toFixed(2));
        total_display = formatCurrency(total.toFixed(2));

        // Build taxes presentation
        const tx_structure  = draw_full_tax_summary(tax_footer_summary, true);
        const ltx_structure = draw_full_tax_summary(local_tax_footer_summary, false);

        // Draw Row
        $('#concepts-table-footer').html(`
            <tr>
                <td colspan="7" class="py-0 text-end minus-title">
                    Subtotal
                </td>
                <td id="visual_subtotal">${subtotal_display}</td>
            </tr>
            ${tx_structure}
            ${ltx_structure}
            <tr>
                <td colspan="7" class="py-0 text-end visual-title">
                    Total
                </td>
                <td id="visual_total">${total_display}</td>
            </tr>
        `);

        $('#invoice_subtotal').val(subtotal). trigger('change');
        $('#invoice_total').val(total). trigger('change');
    }

    function buildTaxSummaries(concept_db_taxes) {
        // Helpers
        const roundTwoDecimals = (n) => Number(n).toFixed(2);
        const roundSixDecimals = (n) => Number(n).toFixed(6);
        const asString = (n) => String(Number(n));

        // Support Data
        const object_tax = concept_db_taxes.object_tax

        // Parse Federal Taxes
        const tax_application_summary = [];
        const tax_summary = [];
        const rate_quotes_summary = [];
        const tax_charges_summary = [];

        [
            { group: 'taxes', app: "tr" },
            { group: 'withholding_taxes', app: "rt" },
        ].forEach(({ group, app }) => {
            const profile = (concept_db_taxes.tax_profile && concept_db_taxes.tax_profile[group]) || {};
            const charges = (concept_db_taxes.tax_charges_summary && concept_db_taxes.tax_charges_summary[group]) || {};

            ['iva', 'ieps', 'isr'].forEach((tax) => {
                if (!(tax in profile)) return;

                const rate = profile[tax] && profile[tax].rate != null ? profile[tax].rate : 0;
                const charge = Number(charges[tax] || 0);

                if ((rate >= 0 && profile[tax]?.rate != null) || (object_tax === "04" && tax === "iva" && app === "tr")) {
                    tax_application_summary.push(app);
                    tax_summary.push(tax_types_keys[tax]);
                    rate_quotes_summary.push(asString(rate));
                    tax_charges_summary.push(roundSixDecimals(charge));
                }
            });
        });

        // Parse Local Taxes
        const local_tax_names_summary = [];
        const local_rate_quotes_summary = [];
        const local_tax_charges_summary = [];
        const local_tax_application_summary = [];

        const pushLocal = (items, app) => {
            (items || []).forEach((it) => {
            if (Number(it.charge) > 0) {
                local_tax_names_summary.push(it.name);
                local_rate_quotes_summary.push(roundSixDecimals(it.rate));
                local_tax_charges_summary.push(roundSixDecimals(it.charge));
                local_tax_application_summary.push(app);
            }
            });
        };

        pushLocal(concept_db_taxes.local_tax_profile && concept_db_taxes.local_tax_profile.transferred, 'tr');
        pushLocal(concept_db_taxes.local_tax_profile && concept_db_taxes.local_tax_profile.withheld, 'rt');

        return {
            tax_application_summary,
            tax_summary,
            rate_quotes_summary,
            tax_charges_summary,

            local_tax_names_summary,
            local_rate_quotes_summary,
            local_tax_charges_summary,
            local_tax_application_summary,
        };
    }

    $(document).on('input', '#individual_zip', async function(){
        try{
            await getTaxAddressByZipAndFillFields({
                zip: $(this).val(),
                municipality_field: '#individual_municipality',
                city_field: '#individual_city',
                state_field: '#individual_state',
                neighborhood_field: '#individual_neighborhood'
            });
        }catch(error){
            showToast(
                error.message, "#C34808", '#78350F'
            );
        }
    });
</script>

{{--* Support *--}}
<script>
  // Format Data
    // Common
    function roundInteger(input, default_value = 0) {
        const value = parseFloat(input.value);

        if (!isNaN(value))
            input.value =  Math.abs( (value % 1 >= 0.5) ? Math.ceil(value) : Math.floor(value) );
        else
            input.value = default_value ;

        return;
    }

    function roundDecimals(input, decimal_limit = 2, default_value = 0.0) {
        let valor = parseFloat(input.value);

        if (isNaN(valor)) valor= default_value;

        const result = parseFloat(valor.toFixed(decimal_limit));
        const exceedsTwoDecimals = /\d\.\d{3,}/.test(valor);

        if (exceedsTwoDecimals) {
            input.value = Math.abs(result).toFixed(decimal_limit);
        } else {
            input.value = Math.abs(result === 0 ? 0 : valor).toFixed(decimal_limit);
        }

        return;
    }

    function strToStrPercentage(number, {decimals = 2, is_low_decimal = true} = {}) {
        let percentage_quantity;
        if (is_low_decimal) {
            percentage_quantity = (parseFloat(number) * 100).toFixed(decimals);
        } else {
            percentage_quantity = parseFloat(number).toFixed(decimals);
        }

        percentage_quantity = removeUnnecessaryDecimal(percentage_quantity);
        return `${percentage_quantity}%`;
    }

    function truncateString(text, limit) {
        if (text.length <= limit) return text;

        return `${text.substring(0, limit)} ...`;
    }

    function cleanPastedValues(value) {
        return value
            .replace(/\r?\n|\r/g, ' ')     // Remove line breaks
            .replace(/\t/g, ' ')           // Remove tabs
            .replace(/\u00A0/g, ' ')       // Remove &nbsp;
            .replace(/\s+/g, ' ')          // Reduce multiple spaces to one
            .trim();                       // Remove spaces at the beginning and end
    }

    // Timers
    function debounce(func, wait) {
        let timeout;

        return function (...args) {
            const context = this;

            clearTimeout(timeout);

            timeout = setTimeout(function () {
                func.apply(context, args);
            }, wait);
        };
    }

    // SAT CATALOGS
    function defineTaxName(tax_key) {
        return tax_types.find(i => i.item_key === tax_key)?.label || null;
    }

  // Messages
    function showToast(text, gradient_from, gradient_to) {
        Toastify({
            text,
            duration: 4000,
            close: false,
            gravity: "bottom",
            position: "center",
            avatar: "{{ asset('images/toast-info-icon.png') }}",

            selector: document.body,
            offset: { x: 0, y: 24 },
            style: {
                background: `linear-gradient(to right, ${gradient_from}, ${gradient_to})`,
            },
        }).showToast();
    }

    function launchSwalToast(icon, title) {
        Swal.fire({
            toast: true,
            position: 'top-end',
            showConfirmButton: false,
            timer: 5000,
            // timerProgressBar: true,
            title,
            icon,
        });
    }

</script>
