system.directive('fulfillmerchize', function () {
    return {
        controller: function ($scope, $http, Upload, $q) {
            this.__proto__ = new BaseFulfillController($scope, $http);
            $scope.merchizeCurrentOrder = {};
            $scope.merchizeStates = {
                products: []
            };
            $scope.profiles = {};
            
            let productTemplateIds = [];


            $scope.merchize_openFulfillForm = async function (orderOrCard) 
            {
                let order = angular.copy(orderOrCard);

                if (typeof orderOrCard.order_id != 'undefined') 
                {
                    $scope.loadingOrderInfo = true; 
                    order = await $scope.loadOrderInfo(orderOrCard.order_id, orderOrCard.locale_code);
                    $scope.loadingOrderInfo = false;

                    $scope.fulFillLocale = orderOrCard.locale_code;

                    safeApply();

                    if (!order) return toastr.error('Error! Cannot find order infomation...');

                } else {
                    if (typeof order.location != 'undefined' && order.location !== '') {
                        $scope.fulFillLocale = angular.copy(order.location);
                    } else {
                        $scope.fulFillLocale = null;
                    }
                }

                if (!$scope.merchizeStates.initialized) {
                    await initializeMerchize();
                    $scope.merchizeStates.initialized = true;
                }

                $scope.merchizeCurrentOrder = angular.copy(order);
                $scope.getSuggestsPrinting($scope.merchizeCurrentOrder.code);
                if ($scope.merchizeCurrentOrder.attributes.customer_info) {
                    $scope.merchizeCurrentOrder.customer.phone = $scope.merchizeCurrentOrder.attributes.customer_info.phone;
                    $scope.merchizeCurrentOrder.customer.full_name = $scope.merchizeCurrentOrder.attributes.customer_info.full_name;
                }
                
                if ($scope.merchizeCurrentOrder.shipping_type != 'express') {
                    $scope.merchizeCurrentOrder.shipping_type = 'standard';
                }

                if ($scope.merchizeCurrentOrder.customer) {

                    if (typeof $scope.merchizeCurrentOrder.attributes.gift_info != 'undefined' && $scope.merchizeCurrentOrder.attributes.gift_info.name) {
                        $scope.merchizeCurrentOrder.customer.full_name = $scope.merchizeCurrentOrder.attributes.gift_info.name;
                        if ($scope.merchizeCurrentOrder.attributes.gift_info.phone) {
                            $scope.merchizeCurrentOrder.customer.phone = $scope.merchizeCurrentOrder.attributes.gift_info.phone;
                        }
                    }

                    $scope.merchizeCurrentOrder.customer.full_name = $scope.capitalizeFirstLetter($scope.merchizeCurrentOrder.customer.full_name);
                    if (window.user_email) {
                        $scope.merchizeCurrentOrder.customer.email = window.user_email;
                    }
                }

                // init attr
                for (let i = 0; i < $scope.merchizeCurrentOrder.items.length; i++) {
                    const element = $scope.merchizeCurrentOrder.items[i];
                    element.merchizeData = {
                        artworks: {
                            front: {},
                            back: {},
                            sleeve: {},
                            hood: {},
                        },
                        variants: {},
                        size: null,
                        color: null,
                        mc_product_id: null,
                        states: {}
                    };
                }

                for (let i = 0; i < $scope.merchizeCurrentOrder.items.length; i++) {
                    $scope.getCustomConfigs($scope.merchizeCurrentOrder.items[i]);
                }

                fetchProfiles();

                $scope.checkEstimateCosts($scope.merchizeCurrentOrder, toastr);

                safeApply();

                $('#modalFulfillMerchize').modal({
                    modal: true,
                    persist: true,
                    position: [30, 0],
                    autoPosition: true
                });
            }

            $scope.merchize_changeProduct = (item) => {
                getMerchizeVariants(item.merchizeData.mc_product_id, item)
            }

            $scope.merchize_changeSize = (item) => {
                // nothing to do
            }

            $scope.merchize_changeColor = (item) => {
                loadColorCode(item);
            }

            $scope.merchize_getColorCode = function(item) {
                if (item.merchizeData.colorCode) {
                    return item.merchizeData.colorCode.hex;
                }
                return '#fff';
            }

            $scope.merchize_uploadImages = async function (files, item, designFile) {
                let supportedFilesType = ['image/png', 'image/jpg', 'image/jpeg', 'image/gif'];
                let supportedFilesExtensions = ['jpg', 'jpeg', 'png', 'gif'];

                item.merchizeData.states.uploading = true;

                if (files) {
                    try {

                        let imagesUploaded = [];
                        let imageFile = null;
                        if (files && files.length) {
                            imageFile = files[0];

                            let fileExtension = imageFile.name.split('.').pop();
                            fileExtension = fileExtension.toLowerCase();
                            if (
                                supportedFilesExtensions.includes(fileExtension) &&
                                supportedFilesType.includes(imageFile.type)
                            ) {
                                imagesUploaded = await $scope.gelato_uploads(files);
                            } else {
                                toastr.error('Error! format supported: jpg, jpeg, png, gif');
                            }
                        }

                        if (imagesUploaded.length) {
                            $scope.$applyAsync(function () {
                                let imageUrl = imagesUploaded.pop();
                                if (imageUrl) {
                                    designFile.extension = imageFile.name.split('.').pop();
                                    designFile.url = imageUrl;
                                }
                                item.merchizeData.states.uploading = false;
                            });
                        }

                    } catch (error) {
                        console.log(error);
                        toastr.error('Error upload images!');
                    }
                }
            };

            $scope.merchize_uploads = function (files) 
            {
                if (typeof googleCloudStorageBucket != 'undefined') {
                    baseFileManagerUrl = googleCloudStorageBucket;
                }
                return new Promise(function (resolve, reject) {
                    Upload.upload({
                        url: baseFileManagerUrl + '/upload',
                        data: { upload: files, type: 'design' }
                    }).then(function (resp) {
                        if (resp.data.status === 'successful') {
                            let upload = resp.data.upload;
                            resolve(upload);
                        } else {
                            reject(0);
                        }
                    }, function (resp) {
                        reject(0);
                    }, function (evt) {
                        $scope.progressPercentage = 100.0 * evt.loaded / evt.total;
                    });
                });
            };

            $scope.merchize_chooseDesign = function (design, designFile, item) {
                if (!design.is_design_comfirm) {
                    toastr.error('Design is not confirmed');
                    return;
                }
                if (designFile.url !== design.url) {
                    designFile.url = design.url;
                    designFile.extension = design.url.split('.').pop();
                    $scope.merchize_changeDesignUrl(designFile);
                    safeApply();
                }
            }

            $scope.merchize_changeDesignUrl = function (designFile)
            {
                designFile.extension = designFile.url.split('.').pop();
                designFile.designPositions = {};

                safeApply();
            }

            $scope.orderMerchize = () => 
            {
                safeApply();

                const printervalOrder = angular.copy($scope.merchizeCurrentOrder);
            
                if (merchize_validateItem(printervalOrder.items).validated) 
                {
                    const merchizeOrderBody = buildFulfillOrderBody(printervalOrder);

                    const param = {
                        title: 'Create Order',
                        customText: 'Post order to Merchize!',
                        confirmButtonText: 'Ok',
                        cancelButtonText: 'Back'
                    };

                    swal({
                        title: param.title,
                        html: param.customText,
                        type: "warning",
                        showConfirmButton: true,
                        showCancelButton: true,
                        confirmButtonText: param.confirmButtonText,
                        cancelButtonText: param.cancelButtonText
                    }).then(async function (isConfirm) 
                    {
                        if (isConfirm.value) {
                        
                            loadingButton('#btnPostMerchizeOrder');

                            await postProfiles(printervalOrder);
                            postToMerchize(printervalOrder, merchizeOrderBody);

                        } else {
                            console.log(merchizeOrderBody);
                        }

                    });

                } else  { // show error validate
                    document.getElementById("errorModalMerchize").style.display = "block";
                }
            }

            const postProfiles = (order) => 
            {
                const profiles = buildProfiles(order);

                const errMessage = 'Error save profile. Please contact technical team.';
                const promisePostProfile = new Promise(function (resolve, reject) {
                    const requestObj = $scope.buildLocaleData('/print-suppliers/profile', profiles, $scope.fulFillLocale);
                    $http.post(requestObj.url, requestObj.params).then(function(response) {
                        if (response.data.status === "successful") {
                            resolve(response.data.data);
                        } else {
                            toastr.error(errMessage);
                            reject();
                        }
                    });
                });

                const promises = [promisePostProfile];

                return Promise.all(promises);
            }

            const buildProfiles = (order) =>
            {
                const profiles = [];
                for (let i = 0; i < order.items.length; i++) 
                {
                    const item = order.items[i];
                    const options = {
                        mc_product_id: item.merchizeData.mc_product_id,
                        color: item.merchizeData.color,
                        size: item.merchizeData.size,
                        artworks: item.merchizeData.artworks,
                    }

                    profiles.push({
                        product_id: item.product_id,
                        is_template_product: isTemplateProduct(item.product_id),
                        product_sku_id: item.product_sku_id,
                        order_id: item.id,
                        order_item_id: item.id,
                        options,
                        type: 'merchize'
                    });
                }
                return profiles;
            }

            const buildFulfillOrderBody = (currentOrder) => 
            {
                const fullName = currentOrder.customer.full_name;
                const partsName = fullName.split(' ');
                const lengthName = partsName.length;

                const lastName = partsName.pop();
                let firstName = partsName.join(' ');

                if (lengthName < 2) {
                    firstName = lastName;
                }

                let region = ' ';
                if(currentOrder.state_name){
                    region = currentOrder.state_name;
                }

                let city = ' ';
                if (currentOrder.city_name) {
                    city = currentOrder.city_name;
                }

                let orderReferenceId = "API";
                if (printerval_locate && printerval_locate !== '') {
                    orderReferenceId += "_" + printerval_locate.toUpperCase();
                }
                orderReferenceId += "_" + currentOrder.code;

                const lineItems = buildLineItems(currentOrder.items);

                const orderBody = {
                    order_id: orderReferenceId,
                    identifier: 'fulfillment_tool',
                    shipping_info: {
                        full_name: firstName + ' ' + lastName,
                        address_1: currentOrder.delivery_address,
                        address_2: currentOrder.optional_address,
                        city,
                        state: region,
                        postcode: currentOrder.zip_code,
                        country: currentOrder.country.iso,
                        email: currentOrder.customer.email,
                        phone: currentOrder.customer.phone,
                    },
                    items: lineItems,
                };

                return orderBody;
            }

            const buildLineItems = (items) => 
            {
                const lineItems = [];

                for (let i = 0; i < items.length; i++) 
                {
                    const item = items[i];
                    const artworks = item.merchizeData.artworks;
                    const lineItem = {
                        name: item.name,
                        product_id: item.id,
                        sku: item.product_sku_id,
                        quantity: item.quantity,
                        price: 0,
                        currency: 'USD',
                        image: item.image_url,
                        design_front: '',
                        design_back: '',
                        design_sleeve: '',
                        design_hood: '',
                        attributes: buildMcProductAttributes(item.merchizeData),
                    };

                    for (const key in artworks) {
                        if (Object.hasOwnProperty.call(artworks, key)) 
                        {
                            const artwork = artworks[key];
                            if (artwork.url) 
                            {
                                lineItem['design_' + key] = artwork.url;
                            }
                        }
                    }

                    lineItems.push(lineItem);
                }

                return lineItems;
            }

            const buildMcProductAttributes = (merchizeData) => {
                const attributes = [];
                const mcProduct = $scope.merchizeStates.products.find((product) => {
                    return product.id == merchizeData.mc_product_id;
                });

                attributes.push({
                    "name": "product",
                    "option": mcProduct.product_title
                });

                if (merchizeData.color) {
                    attributes.push({
                        "name": "Color",
                        "option": merchizeData.color
                    });
                }

                if (merchizeData.size) {
                    attributes.push({
                        "name": "Size",
                        "option": merchizeData.size
                    });
                }

                return attributes;
            }

            const merchize_validateItem = (items) => 
            {
                let validated = true;
                let messages = {};

                for (let i = 0; i < items.length; i++) {
                    const itemData = items[i];
                    messages[itemData.product_sku_id] = [];

                    const variants = itemData.merchizeData.variants;
                    if (Object.keys(variants).length) {
                        
                        const keys = Object.keys(variants);
                        for (let j = 0; j < keys.length; j++) {

                            let k = null;
                            if (keys[j] == 'colors') k = 'color';
                            if (keys[j] == 'sizes') k = 'size';

                            if (!itemData.merchizeData[k]) {
                                validated = false;
                                messages[itemData.product_sku_id].push(itemData.name + ' || Missing product attributes.');
                                break;
                            }

                        }

                    } else {
                        validated = false;
                        messages[itemData.product_sku_id].push(itemData.name + ' || Missing product.');
                    }

                    const artworks = itemData.merchizeData.artworks;
                    if (!artworks.back.url && !artworks.front.url) {
                        validated = false;
                        messages[itemData.product_sku_id].push(itemData.name + ' || Missing Design.');
                    }

                }

                $scope.merchizeStates.messages = messages;

                return {
                    validated,
                    messages
                };
            }

            const postToMerchize = (printervalOrder, merchizeOrderData) => 
            {
                toastr.options.positionClass = "toast-bottom-left";
                
                const requestObj = $scope.buildLocaleData('/print-suppliers/merchize/fulfill-order', {
                    order_id: printervalOrder.id,
                    merchize_order_data: merchizeOrderData
                }, $scope.fulFillLocale);

                $http.post(requestObj.url, requestObj.params).then(function (response)
                {
                    if (response.data.data._id) {
                        toastr.success('Successfully');
                        $('#modalFulfillMerchize').modal('hide');
                    } else {
                        toastr.error('Has an Error! Please contact technical team.  | ' + JSON.stringify(response.data));
                    }

                    const mapItemPrintProvider = {};
                    for (let index = 0; index < printervalOrder.items.length; index++) {
                        const item = printervalOrder.items[index];
                        mapItemPrintProvider[item.id] = 'MERCHIZE';
                    }

                    afterFulfillAction(merchizeOrderData, {mapItemPrintProvider});

                    stopLoadingButton('#btnPostMerchizeOrder');
                    
                }).catch(function(error) {
                    toastr.error('Has an Error! Please contact technical team. | ' + JSON.stringify(error));
                    toastr.warning($scope.getFailFulfillMessage('merchize'));
                    $('#modalFulfillPrintLogistic').modal('hide');
                    stopLoadingButton('#btnPostMerchizeOrder');
                });
            }

            const initializeMerchize = async function () {
                return new Promise((resolve) => {
                    Promise.all([getMerchizeProducts()]).then(() => {
                        resolve();
                    });
                });
            }
            
            const getMerchizeVariants = (mcProductId, item) => {

                const requestObj = $scope.buildLocaleData('/print-suppliers/merchize/variants', {
                    product_id: mcProductId
                }, $scope.fulFillLocale);

                return $http.get(requestObj.url, {
                    params: requestObj.params
                }).then((response) => {
                    if (response.data) {
                        item.merchizeData.variants = response.data;
                    }
                });
            }

            const getMerchizeProducts = () => {

                const requestObj = $scope.buildLocaleData('/print-suppliers/merchize/products', {}, $scope.fulFillLocale);

                return $http.get(requestObj.url, {
                    params: requestObj.params
                }).then((response) => {
                    if (response.data) {
                        $scope.merchizeStates.products = response.data;
                    }
                });
            }

            const afterFulfillAction = (fulfillOrderPayload, additionalData = {}) => 
            {
                logMerchizeFulFill(fulfillOrderPayload);

                const orderMeta = {
                    order_id: $scope.merchizeCurrentOrder.id,
                };

                if (additionalData && typeof additionalData.mapItemPrintProvider) {
                    orderMeta.print_provider = additionalData.mapItemPrintProvider;
                }

                requestObj = $scope.buildLocaleData('/print-suppliers/fulfill/attach-order-meta', orderMeta, $scope.fulFillLocale);
                
                return $http.post(requestObj.url, requestObj.params);
            }

            const logMerchizeFulFill = function(merchizeOrder, isLogData = false) 
            {
                let logData;

                if (!isLogData) {
                    logData = {
                        actor_email: user_email,
                        event_type: 'MERCHIZE-FULFILLMENT',
                        target_id: $scope.merchizeCurrentOrder.id,
                        data: merchizeOrder
                    };
                } else {
                    logData = merchizeOrder;
                }

                const requestObj = $scope.buildLocaleData('/print-suppliers/fulfill/log', logData, $scope.fulFillLocale);
                
                $http.post(requestObj.url, requestObj.params).then(() => {});

            }

            const loadingButton = function (selector, text = 'Processing...') {
                $(selector).attr('dt-text', $(selector).text());
                $(selector).text(text);
                $(selector).attr("disabled", true);
            }

            const stopLoadingButton = function (selector) {
                $(selector).html($(selector).attr('dt-text'));
                $(selector).attr("disabled", false);
            }

            const loadColorCode = function(item)
            {
                const requestObj = $scope.buildLocaleData('/print-suppliers/printify/find-color', {
                    name: item.merchizeData.color
                }, $scope.fulFillLocale);
                    
                $http.get(requestObj.url, {
                    params: requestObj.params
                }).then((response) => {
                    if (response.data.result) {
                        item.merchizeData.colorCode = response.data.result;
                    }
                });
            }

            const fetchProfiles = () =>
            {
                $scope.getDesignJobOrder($scope.merchizeCurrentOrder);

                const requestObj = $scope.buildLocaleData('/print-suppliers/get-profile', {
                    type: 'merchize',
                    order_items: $scope.merchizeCurrentOrder.items
                }, $scope.fulFillLocale);

                $http.post(requestObj.url, requestObj.params).then(function(response) {
                    if (response.data.status === 'successful') {
                        $scope.profiles = {
                            profiles: response.data.profiles,
                            designs: response.data.designs
                        };
                        productTemplateIds = response.data.product_template_ids;
                        applyProfiles();
                    }
                }, function(error) {
                    toastr.error('Error load profiles!');
                });
            }

            const applyProfiles = async () => 
            {
                $scope.merchizeCurrentOrder.items.forEach(async printOrderItem => {

                    let profile = null;
                    let designs;

                    if (!printOrderItem.merchizeData.profile) {
                        printOrderItem.merchizeData.profile = {};
                    }

                    if (isTemplateProduct(printOrderItem.product_id)) {
                        profile = $scope.profiles.profiles.find(function (item) {
                            return parseInt(item.product_id) === parseInt(printOrderItem.product_id) && item.is_template_product;
                        });
                        designs = $scope.findDesign(printOrderItem, true, $scope.profiles.designs);
                    } else {
                        profile = $scope.profiles.profiles.find(function (item) {
                            return parseInt(item.product_sku_id) === parseInt(printOrderItem.product_sku_id) && !item.is_template_product;
                        });
                        designs =  $scope.findDesign(printOrderItem, false, $scope.profiles.designs);
                    }

                    printOrderItem.merchizeData.patternDesigns = [];
                    if(designs && designs.length) {
                        printOrderItem.merchizeData.patternDesigns = designs;

                        setTimeout(() => {
                            $('[data-magnify=gallery]').magnify({
                                zIndex: 10000
                            });
                        }, 500);
                        
                    }

                    if(profile) 
                    {
                        const profileOptions = profile.options;

                        if (typeof profileOptions.artworks != 'undefined') {
                            if (profileOptions.artworks.front.url) {
                                printOrderItem.merchizeData.artworks.front = angular.copy(profileOptions.artworks.front);
                            }
                            if (profileOptions.artworks.back.url) {
                                printOrderItem.merchizeData.artworks.back = angular.copy(profileOptions.artworks.back);
                            }
                        }

                        const mcProduct = $scope.merchizeStates.products.find((product) => {
                            return product.id == profileOptions.mc_product_id;
                        });

                        printOrderItem.merchizeData.mc_product_id = mcProduct.id.toString();
                        $scope.merchize_changeProduct(printOrderItem);

                        if (profileOptions.size) {
                            printOrderItem.merchizeData.size = profileOptions.size;
                            $scope.merchize_changeSize(printOrderItem);
                        }
                        if (profileOptions.color) {
                            printOrderItem.merchizeData.color = profileOptions.color;
                            $scope.merchize_changeColor(printOrderItem);
                        } 
                    }

                });
            }

            const isTemplateProduct = (productId) => {
                return productTemplateIds.includes(productId);
            }

            const safeApply = () => {
                if ($scope.$root.$$phase !== '$apply' && $scope.$root.$$phase !== '$digest') {
                    $scope.$apply();
                }
            }

        }
    }
});