import $ from 'jquery';
import modal, {state as modalState} from './elements/modal';
import {preloader, preloaderCenter} from './elements/preloaders';

import * as logsFields from './elements/fields-logs';

(function($) {

    const state = {
        logsPage: 0,
        isLastLog: false
    }

    const AdminLogs = {
        init: () => {
            modal.init();
        },
        initDatePickers: () => {

            jQuery('#cembrapay-logs-filter-date-from, #cembrapay-logs-filter-date-to').datepicker({
                dateFormat: 'yy-mm-dd',
                changeMonth: true,
                changeYear: true,
                showButtonPanel: true
            });

        },
        resetState: () => {
            state.logsPage  = 0;
            state.isLastLog = false;
        },
        filtersPanel: () => {

            const filterTypes = ['dateRange', 'customerName', 'orderId', 'requestType', 'relationship'];

            return `
                <div class="cembrapay-logs-filters-panel">
                    ${
                        filterTypes.map( filterType => {
                            switch(filterType) {
                                case 'dateRange':
                                    return `
                                    <div class="cembrapay-logs-filters-panel-item">
                                        <label>${ cembrapayLogs.strings.dateRange }</label>
                                        <label for="cembrapay-logs-filter-date-from">${ cembrapayLogs.strings.from }</label>
                                        <input type="text" id="cembrapay-logs-filter-date-from" name="cembrapay-logs-filter-date-from" value="${cembrapayLogs.lastMonth}" />
                                        <label for="cembrapay-logs-filter-date-to">${ cembrapayLogs.strings.to }</label>
                                        <input type="text" id="cembrapay-logs-filter-date-to" name="cembrapay-logs-filter-date-to" value="${cembrapayLogs.today}" />
                                    </div>
                                    `;
                                break;
                                case 'customerName':
                                    return `
                                    <div class="cembrapay-logs-filters-panel-item">
                                        <label>${ cembrapayLogs.strings.customerName }</label>
                                        <label for="cembrapay-logs-filter-customer-first-name">${ cembrapayLogs.strings.firstName }</label>
                                        <input type="text" id="cembrapay-logs-filter-customer-first-name" name="cembrapay-logs-filter-customer-first-name" />
                                        <label for="cembrapay-logs-filter-customer-last-name">${ cembrapayLogs.strings.lastName }</label>
                                        <input type="text" id="cembrapay-logs-filter-customer-last-name" name="cembrapay-logs-filter-customer-last-name" />
                                    </div>
                                    `;
                                break;
                                case 'orderId':
                                    return `
                                    <div class="cembrapay-logs-filters-panel-item">
                                        <label for="cembrapay-logs-filter-order-id">${ cembrapayLogs.strings.orderId }</label>
                                        <input type="number" id="cembrapay-logs-filter-order-id" name="cembrapay-logs-filter-order-id" />
                                    </div>
                                    `;
                                break;
                                case 'requestType':
                                    return `
                                    <div class="cembrapay-logs-filters-panel-item">
                                        <label for="cembrapay-logs-filter-request-type">${ cembrapayLogs.strings.requestType }</label>
                                        <select id="cembrapay-logs-filter-request-type" name="cembrapay-logs-filter-request-type">
                                            <option value="">${ cembrapayLogs.strings.all }</option>
                                            <option value="CHK">${ cembrapayLogs.strings.checkoutChk }</option>
                                            <option value="AUT">${ cembrapayLogs.strings.authorizationAut }</option>
                                            <option value="SET">${ cembrapayLogs.strings.settlementSet }</option>
                                            <option value="CAN">${ cembrapayLogs.strings.cancellationCan }</option>
                                            <option value="CST">${ cembrapayLogs.strings.statusCst }</option>
                                        </select>
                                    </div>
                                    `;
                                break;
                                case 'relationship':
                                    return `
                                    <div class="cembrapay-logs-filters-panel-item">
                                        <label for="cembrapay-logs-filter-relationship">${ cembrapayLogs.strings.relationship }</label>
                                        <select id="cembrapay-logs-filter-relationship" name="cembrapay-logs-filter-relationship">
                                            <option value="AND">AND</option>
                                            <option value="OR">OR</option>
                                        </select>
                                    </div>
                                    `;
                                break;
                            }
                        }).join('')
                    }
                    <div class="cembrapay-logs-filters-panel-item">
                        <button id="cembrapay-logs-filter-apply" class="button button-primary">${ cembrapayLogs.strings.applyFilters }</button>
                    </div>
                </div>
            `;
        },
        modal: {
            open: () => {

                modal.open();
                modal.title.html('');
                modal.content.css('height', '100%');
                jQuery('#cembrapay-modal .cembrapay-modal-content').css('max-width', '90%');
                state.logsPage = 0;
                AdminLogs.modal.data.loadLogs();

            },
            close: () => {

                modal.close();
                state.logsPage = 0;
                state.isLastLog = false;

            },
            data: {
                loadFilteredLogs: () => {

                    if( state.isLastLog ) {
                        return false;
                    }

                    jQuery('.cembrapay-logs-main').empty();
                    AdminLogs.modal.data.loadLogs();

                },
                loadLogs: field => {

                    if( state.isLastLog ) {
                        return false;
                    }

                    if( ! jQuery('.cembrapay-logs-container').length ) {

                        modal.content.html(`
                            <div class="cembrapay-logs-container">
                                ${AdminLogs.filtersPanel()}
                                <div class="cembrapay-logs-main">
                                    
                                </div>
                            </div>
                        `);

                    }

                    const logsMain = jQuery('.cembrapay-logs-main');

                    logsMain.append(preloaderCenter);

                    let filters = {
                        dateFrom: jQuery('#cembrapay-logs-filter-date-from').val(),
                        dateTo: jQuery('#cembrapay-logs-filter-date-to').val(),
                        customerFirstName: jQuery('#cembrapay-logs-filter-customer-first-name').val(),
                        customerLastName: jQuery('#cembrapay-logs-filter-customer-last-name').val(),
                        orderId: jQuery('#cembrapay-logs-filter-order-id').val(),
                        requestType: jQuery('#cembrapay-logs-filter-request-type').val(),
                        relationship: jQuery('#cembrapay-logs-filter-relationship').val()
                    };
                    
                    AdminLogs.initDatePickers();
                    
                    jQuery.ajax({
                        url: cembrapayLogs.ajaxUrl,
                        type: 'POST',
                        dataType: 'json',
                        data: {
                            action: 'get_logs',
                            security: cembrapayLogs.nonceGet,
                            filters: filters,
                            page: state.logsPage
                        },
                        success: function(response) {

                            jQuery('.spinner-main').remove();

                            if( response.success ) {

                                const logs = response.data.logs;

                                if( logs.length ) {

                                    let logsTable = jQuery('.cembrapay-log-items tbody');

                                    if( ! logsTable.length ) {

                                        logsMain.append(`
                                            <table class="cembrapay-log-items"cellpadding="0" cellspacing="0">
                                                <thead>
                                                <tr>
                                                    <th>ID</th>
                                                    <th>${ cembrapayLogs.strings.orderId }</th>
                                                    <th>${ cembrapayLogs.strings.firstName }</th>
                                                    <th>${ cembrapayLogs.strings.lastName }</th>
                                                    <th>${ cembrapayLogs.strings.requestType }</th>
                                                    <th>${ cembrapayLogs.strings.status }</th>
                                                    <th>${ cembrapayLogs.strings.date }</th>
                                                    <th>${ cembrapayLogs.strings.actions }</th>
                                                </tr>
                                                </thead>
                                                <tbody>
                                                </tbody>
                                            </table>
                                        `);

                                        logsTable = jQuery('.cembrapay-log-items tbody');

                                    }

                                    logsTable.append(`
                                        
                                        ${
                                            logs.map( log => {

                                                const request = log.request ? AdminLogs.parseRequest(log.req_type, log.request) : '';
                                                const response = log.response ? AdminLogs.parseResponse(log.req_type, log.response) : '';

                                                return `
                                                    <tr>
                                                        <td>${ log.id }</td>
                                                        <td>${ log.order_id }</td>
                                                        <td>${ log.first_name }</td>
                                                        <td>${ log.last_name }</td>
                                                        <td>${ log.req_type }</td>
                                                        <td>${ log.proc_status }</td>
                                                        <td>${ log.datetime }</td>
                                                        <td>
                                                            <span data-id="${ log.id }" title="${ cembrapayLogs.strings.openLog } ${ log.id }" class="open-log dashicons dashicons-visibility"></span>
                                                            <span data-id="${ log.id }" title="${ cembrapayLogs.strings.deleteLog } ${ log.id }" class="delete-log dashicons dashicons-trash"></span>
                                                        </td>
                                                    </tr>
                                                    <tr class="log-data" id="log-${ log.id }" style="display: none;">
                                                        <td colspan="8">
                                                            <div style="display: flex; gap: 10px; border: 1px dashed #ccc; padding: 5px;">
                                                                <div style="flex: 1; max-width: 50%; word-wrap: break-word;">
                                                                    <span><strong>${ cembrapayLogs.strings.request }</strong></span><br/><br/>
                                                                    ${ request }
                                                                    <div style="width: 100%;">
                                                                        <p><strong>Raw</strong> - <a class="expand-log" data-log-id="${ log.id }" data-log-type="request" style="cursor: pointer;">Expand</a></p>
                                                                        <div id="log-raw-request-${ log.id }" style="display: none;">
                                                                            ${ log.request }
                                                                        </div>
                                                                    </div>
                                                                </div>
                                                                <div style="flex: 1;  max-width: 50%; word-wrap: break-word;">
                                                                    <span><strong>${ cembrapayLogs.strings.response }</strong></span><br/><br/>
                                                                    ${ response }
                                                                     <div style="width: 100%;">
                                                                        <p><strong>Raw</strong> - <a class="expand-log" data-log-id="${ log.id }" data-log-type="response" style="cursor: pointer;">Expand</a></p>
                                                                        <div id="log-raw-response-${ log.id }" style="display: none;">
                                                                            ${ log.response }
                                                                        </div>
                                                                    </div>
                                                                </div>
                                                            </div>
                                                        </td>
                                                    </tr>
                                                `;
                                            }).join('')
                                        }
                                    `);

                                    state.logsPage++;

                                }

                            }

                            if( ! response.success ) {
                                state.isLastLog = true;
                                logsMain.append(`<p id="no-more-logs">${response.data.message}</p>`);
                                setTimeout(() => {
                                    jQuery('#no-more-logs').remove();
                                }, 5000);
                            }

                        },
                        error: function(xhr, status, error) {
                            logsMain.html(`<p>${error}</p>`);
                        }
                    });

                },
                deleteLog: log => {

                    if( ! confirm(`${ cembrapayLogs.strings.deleteLogConfirm } ID: ${log.data('id')}`) ) {
                        return false;
                    }
                    
                    const logId = log.data('id');

                    jQuery.ajax({
                        url: cembrapayLogs.ajaxUrl,
                        type: 'POST',
                        dataType: 'json',
                        data: {
                            action: 'delete_log',
                            security: cembrapayLogs.nonceGet,
                            logId: logId
                        },
                        success: function(response) {

                            if( response.success ) {
                                jQuery(`#log-${logId}`).remove();
                            }

                        },
                        error: function(xhr, status, error) {
                            console.log(xhr, status, error);
                        }
                    });

                },

                expandLog: log => {
                    
                    const logId = log.data('log-id');
                    const logType = log.data('log-type');
                    jQuery(`#log-raw-${logType}-${logId}`).slideToggle();
                     
                }

            },
            toggleLog: log => {

                jQuery('.log-data').hide();

                const logId = log.data('id');
                jQuery(`#log-${logId}`).slideToggle();

            },
            bottomReached: element => {
                
                const scrollTop = element.scrollTop();
                const scrollHeight = element.prop('scrollHeight');
                const clientHeight = element.innerHeight();
                
                if (scrollTop + clientHeight >= scrollHeight) {
                    AdminLogs.modal.data.loadLogs();
                }

            }

        },
        parseFields: (fields, request, strings = cembrapayLogs.strings) => {

            let html = '';
        
            for( let field of fields ) {
                switch( field.type ) {
                    case 'string':
                        const value = true === field.encoded ? atob( request[ field.name ] ) : request[ field.name ];
                        const label = strings[ field.name ] ? strings[ field.name ] : field.name;
                        if( value ) {
                            html += `<span><strong>${ label }</strong>: ${ value }</span><br/>`;
                        }
                    break;
                    case 'object':
                        html += `<span><strong>${ strings[ field.name ] }</strong></span><br/>`;
                        if( field.subfields && field.subfields.length && request[ field.name ] ) {
                            html += AdminLogs.parseFields(field.subfields, request[ field.name ]);
                        }
                    break;
                    case 'array':
                        if( request[ field.name ] ) {
                            for( let i = 0; i < request[ field.name ].length; i++ ) {
                                switch( typeof request[ field.name ][i] ) {
                                    case 'string':
                                        html += `<span><strong>${ field.name }</strong>: ${ request[ field.name ][i] }</span><br/>`;
                                    break;
                                    default:
                                        let objKeys = 'object' === typeof request[ field.name ][i] ? Object.keys( request[ field.name ][i] ) : request;
                                        for( let key in objKeys ) {
                                            key = objKeys[key];
                                            if( request[ field.name ][i][key] ) {
                                                const label = strings[ key ] ? strings[ key ] : key;
                                                html += `<span><strong>${ label }</strong>: ${ request[ field.name ][i][key] }</span><br/>`;
                                            }
                                        }
                                    break;
                                }
                            }
                        }
                    break;
                    case 'space':
                        html += `<br/>`;
                    break;
                }
            }

            return html;

        },
        parseRequest: ( reqType, request ) => {

            request = JSON.parse(request);

            const requestBody = request && request.args && request.args.body ? request.args.body : {};

            let html = '<p>';

            html += `<span><strong>URL</strong>: ${ request.url }</span><br/>`;

            switch( reqType ) {

                case 'CHK': case 'AUT':

                    const fieldsAutChkRequest = logsFields.chkAutRequest;
                    html += AdminLogs.parseFields(fieldsAutChkRequest, requestBody);

                break;
                case 'CFM':

                    const fieldsCfmRequest = logsFields.cfmRequest;
                    html += AdminLogs.parseFields(fieldsCfmRequest, requestBody);

                break;
                case 'CAN':

                    const fieldsCanRequest = logsFields.canRequest;
                    html += AdminLogs.parseFields(fieldsCanRequest, requestBody);

                break;
                case 'CST':

                    const fieldsCstRequest = logsFields.cstRequest;
                    html += AdminLogs.parseFields(fieldsCstRequest, requestBody);

                break;
                case 'SET':

                    const fieldsSetRequest = logsFields.setRequest;
                    html += AdminLogs.parseFields(fieldsSetRequest, requestBody);

                break;
                case 'CNT':
                
                    const fieldsCntRequest = logsFields.cntRequest;
                    html += AdminLogs.parseFields(fieldsCntRequest, requestBody);

                break;

            }

            html += '</p>';

            return html;

        },
        parseResponse: ( reqType, response ) => {

            response = JSON.parse(response);

            let html = ``;

            if( response && response.processingStatus ) {

                if( 'ERROR' === response.processingStatus ) {

                    if( response.errors && response.errors.length ) {
                        let idx = 1;
                        for( let error of response.errors ) {
                            html += `<p>`;
                            html += `<span><strong>${ cembrapayLogs.strings.error } ${ idx }</strong></span><br/>`;
                            if( error.processingErrorCode ) {
                                html += `<span><strong>${ cembrapayLogs.strings.errorCode }</strong>: ${ error.processingErrorCode }</span><br/>`;
                            }
                            if( error.processingErrorDescr ) {
                                html += `<span><strong>${ cembrapayLogs.strings.errorDescription }</strong>: ${ error.processingErrorDescr }</span><br/>`;
                            }
                            html += `<p>`;
                            idx++;
                        }
                    }

                }

                switch( reqType ) {

                    case 'CHK': case 'AUT':

                        const fieldsAutChkResponse = logsFields.chkAutResponse;
                        html += AdminLogs.parseFields(fieldsAutChkResponse, response);

                    break;
                    case 'CFM':
                        
                        const fieldsCfmResponse = logsFields.cfmResponse;
                        html += AdminLogs.parseFields(fieldsCfmResponse, response);

                    break;
                    case 'CAN':

                        const fieldsCanResponse = logsFields.canResponse;
                        html += AdminLogs.parseFields(fieldsCanResponse, response);

                    break;
                    case 'CST':

                        const fieldsCstResponse = logsFields.cstResponse;
                        html += AdminLogs.parseFields(fieldsCstResponse, response);

                    break;
                    case 'SET':

                        const fieldsSetResponse = logsFields.setResponse;
                        html += AdminLogs.parseFields(fieldsSetResponse, response);

                    break;
                    case 'CNT':

                        const fieldsCntResponse = logsFields.cntResponse;
                        html += AdminLogs.parseFields(fieldsCntResponse, response);

                    break;

                }

            }

            return html;

        }
        
    }

    jQuery(() => {

        AdminLogs.init();

        jQuery('body').on('click', '#woocommerce_cembrapay_logs_separator', function(evt) {
            evt.preventDefault();
            AdminLogs.modal.open();
        });

        jQuery('body').on('click', '#cembrapay-logs-filter-apply', function(evt) {
            evt.preventDefault();
            AdminLogs.resetState();
            AdminLogs.modal.data.loadFilteredLogs();
        });

        jQuery('body').on('click', '.open-log', function(evt) {
            evt.preventDefault();
            AdminLogs.modal.toggleLog(jQuery(this));
        });

        jQuery('body').on('click', '.delete-log', function(evt) {
            evt.preventDefault();
            AdminLogs.modal.data.deleteLog(jQuery(this));
        });

        jQuery('body').on('click', '.expand-log', function(evt) {
            evt.preventDefault();
            AdminLogs.modal.data.expandLog(jQuery(this));
        });

        jQuery('body').on('click', '.cembrapay-modal-content #close, #cembrapay-modal #bg', function(evt) {
            evt.preventDefault();
            AdminLogs.modal.close();
        });

    });

    document.addEventListener('scroll', function (event) {
        if( 'content' === event.target.id ) {
            AdminLogs.modal.bottomReached( jQuery(event.target) );
        }
    }, true);

})(jQuery);