<?php

namespace Modules\PrintSuppliers\Controllers;

use Exception;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Modules\PrintSuppliers\Models\OrderItem;
use Modules\PrintSuppliers\Traits\ProductFulfill;
use Illuminate\Http\Request;
use Intervention\Image\ImageManagerStatic as Image;
use Google\Cloud\Storage\StorageClient;

class Controller extends BaseController
{
    use AuthorizesRequests, DispatchesJobs, ValidatesRequests, ProductFulfill;

    const STATUS_SUCCESSFUL = 'successful';
    const STATUS_FAIL = 'fail';

    protected function triggerAsyncRequest($url, $params = "", $method = "get") {
        $channel = curl_init();
        if ($method == "get" || $method == "GET") {
            curl_setopt($channel, CURLOPT_URL, $url . "?" . $params);
        } else if ($method == "post" || $method == "POST") {
            curl_setopt($channel, CURLOPT_URL, $url);
            curl_setopt($channel, CURLOPT_POST, true);
            curl_setopt($channel, CURLOPT_POSTFIELDS, json_encode($params));
            curl_setopt($channel, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
        }
        curl_setopt($channel, CURLOPT_NOSIGNAL, 1);
        curl_setopt($channel, CURLOPT_TIMEOUT_MS, 600);
        curl_setopt($channel, CURLOPT_RETURNTRANSFER, 1);
        curl_exec($channel);
        curl_close($channel);
    }

    protected function triggerSyncRequest($url, $method = 'GET', $params = [], $headers = []) {
        $ch = curl_init();
        $timeout = 200;
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        if ($headers) {
            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        }
        if ($method != 'GET') {
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($params));
        }
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);

        curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
        $data = curl_exec($ch);
        curl_close($ch);
        return json_decode($data, true);
    }

    protected function multiCurl($urls = [], $method = "GET", $params = [], $headers = [])
    {
        ini_set('MAX_EXECUTION_TIME', 300);
        $listChannel = array();
        $mh = curl_multi_init();
        foreach ($urls as $url) {
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
            if (!empty($params)) {
                curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($params));
                curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type:application/json'));
            }
            if ($headers) {
                curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
            }
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
            curl_setopt($ch, CURLOPT_MAXREDIRS, 3);
            curl_setopt($ch, CURLOPT_POSTREDIR, 1);
            curl_setopt($ch, CURLOPT_TIMEOUT, 600);
            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 600);
            curl_multi_add_handle($mh, $ch);
            $listChannel[$url] = $ch;
        }
        $index = null;
        $result = [];
        do {
            curl_multi_exec($mh, $index);
        } while ($index > 0);

        foreach ($listChannel as $url => $ch) {
            $result[$url] = curl_multi_getcontent($ch);
            curl_multi_remove_handle($mh, $ch);
        }
        curl_multi_close($mh);
        return $result;
    }

    /**
     * Return config connect to api suppliers
     * @return array
     * */
    protected function getSupplierConfigs()
    {
        $dataConfigs = \Config::get('print-suppliers::connection');
        $configs = [];
        foreach ($dataConfigs as $key => $value) {
            switch ($key) {
                case 'printify': $configs['printify'] = loadPrintifyConfigs($value); break;
                case 'gelato': $configs['gelato'] = loadGelatoConfigs($value); break;
                case 'merchize': $configs['merchize'] = loadMerchizeConfigs($value); break;
                case 'printlogistic': $configs['printlogistic'] = loadPrintLogisticConfigs($value); break;
                case 'proluxury': $configs['proluxury'] = loadProLuxuryConfigs($value); break;
                case 'teezily': $configs['teezily'] = loadTeezilyConfigs($value); break;
            }
        }

        return $configs;
    }

    protected function getCredential($shopId = null, $supplier = 'printify')
    {
        $supplierConfigs = $this->getSupplierConfigs();
        $apiToken = null;

        switch ($supplier)
        {
            case 'printify' :
                if (isset($supplierConfigs['printify'])) {

                    $account = array_filter($supplierConfigs['printify'], function($_acc) use ($shopId) {
                        if ($shopId) {
                            return $_acc['shop_id'] == $shopId;
                        } else {
                            return $_acc['default'];
                        }
                    });

                    if (count($account)) {
                        $account = end($account);
                    }

                    $shopId = $account['shop_id'];
                    $apiToken = $account['api_token'];
                }
                break;

            case 'merchize':
                if (isset($supplierConfigs['merchize'])) {
                    $apiToken = $supplierConfigs['merchize']['api_token'];
                }
                break;
            case 'printlogistic':
                if (isset($supplierConfigs['printlogistic'])) {
                    $apiToken = $supplierConfigs['printlogistic']['api_token'];
                }
                break;
            case 'proluxury':
                if (isset($supplierConfigs['proluxury'])) {
                    $apiToken = $supplierConfigs['proluxury']['api_token'];
                }
                break;
            case 'teezily':
                if (isset($supplierConfigs['teezily'])) {
                    $apiToken = $supplierConfigs['teezily']['api_token'];
                }
                break;
        }

        return [$shopId, $apiToken];
    }

    /**
     * Return order detail by order id
     * @param $orderId
     * @return null|mixed
     */
    protected function findOrderDetail($orderId)
    {
        $getOrderEndpoint = '/order?embeds=shipment,warehouse,shippingInfoCompleted&metric=first&service_token=megaads@123';
        $responseOrder = $this->triggerSyncRequest(Config::get('sa.api_url') . $getOrderEndpoint . '&filters=id=' . $orderId, 'GET');
        if (isset($responseOrder['status']) && $responseOrder['status'] === 'successful' && isset($responseOrder['result']) && count($responseOrder['result'])) {
            return $responseOrder['result'];
        }
        return null;
    }

    /**
     * find profile by skuId
     * @param $skuId
     * @return null|mixed
     */
    protected function findProfile($skuId, $type = 'printify')
    {
        $currentLocale = env('APP_LOCALE');
        $baseUrl = \URL::to('/');
        $getProfileEndpoint = '/print-suppliers/profile';

        if ($currentLocale) {
            $baseUrl .= '/' . $currentLocale;
        }

        $response = $this->triggerSyncRequest($baseUrl . $getProfileEndpoint . '?skuIds=' . $skuId . '&type=' . $type, 'GET');
        if (isset($response['status']) && $response['status'] === 'successful' && isset($response['data']) && count($response['data'])) {
            return end($response['data']);
        }

        return null;
    }

    protected function updateResourceItemId($mapOrderItemResourceId)
    {
        foreach($mapOrderItemResourceId as $orderItemId => $resourceId) {
            $orderItem = OrderItem::query()->where('id', $orderItemId)->first();
            if ($orderItem) {
                $orderItem->resource_item_id = $resourceId;
                $orderItem->save();
            }
        }
    }

    protected function getActiveMarkets()
    {
        $markets = \Config::get('localization::module.locales');

        foreach ($markets as $k => $market) {
            if ($market['enable'] != true || $k == 'central') {
                unset($markets[$k]);
            };
        }

        return $markets;
    }

    protected function getFulfillDesignV2($productSkuId, $resolution, $productId = null, $anchor = null, $printArea = null) {
        $url = "https://printerval.com/service/pod/design/resolution?product_sku_id=$productSkuId&product_id=$productId&resolution=$resolution&position=$printArea";
        if (\Illuminate\Support\Facades\Input::get('email') == 'quynhnga9xnguyen@gmail.com') {
            $url = "https://printerval.com/service/pod/v2/design/resolution?product_sku_id=$productSkuId&product_id=$productId&resolution=$resolution&position=$printArea";
        }
        $response = $this->triggerSyncRequest($url);
        $result = $response;
        if($result['status'] == 'successful' && $result['result']['image_url']) {
            return $result['result']['image_url'];
        } else {
            \Log::error($url);
            throw new Exception("Design not found", 1);
        }
        
    }

    protected function getFulfillDesign($productSkuId, $resolution, $productId = null, $anchor = null, $printArea = null) {
        $design = null;

        if (class_exists('\Modules\Pod\Controllers\DesignController') && method_exists('\Modules\Pod\Controllers\DesignController','getDesignByResolution')) {
            $designJobController = new \Modules\Pod\Controllers\DesignController;
            $res = $designJobController->getDesignByResolution($productSkuId, $resolution, $productId, true, $anchor, $printArea);
            $design = $res['result'];
        }

        return $design;
    }

    public function showResizeTool () {
        return view('print-suppliers::home.resize-design');
    }

    public function showAutoMockupTool () {
        return view('print-suppliers::home.auto-mockup');
    }

    public function resizeDesign (Request $request) {
        $params = $request->all();
        $url = $params['url'];
        $width = $params['width'];
        if ($request->has('isDoubleSides') && $request->input('isDoubleSides') == 'true') {
            $odd = false;
            if ($width % 2) {
                $odd = true;
                $width = $width - 1;
            }
            $width = $width / 2;
        }
        $height = $params['height'];
        $anchor = $params['anchor'];
        $percent = $params['percent'];
        $filename = ($anchor . '_' . $width . 'x' . $height . '_' . time() . '_' . str_slug(basename($url)));
        if (strpos($filename, '.png') === false) {
            $filename .= ".png";
        }
        $image = Image::make($url);
        $image->resize($width * $percent / 100, $height * $percent/ 100, function ($constraint) {
            $constraint->aspectRatio();
        });
        if ($request->has('trim') && $request->input('trim') == 'true') {
            $image->trim();
        }
        $image->resizeCanvas($width, $height, $anchor);

        if ($request->has('bgColor') && $request->input('bgColor')) {
            $tmpImage = Image::canvas($width, $height, $request->input('bgColor'));
            $tmpImage->insert($image, 'center');
            $image = $tmpImage;
        }

        if ($request->has('isDoubleSides') && $request->input('isDoubleSides') == 'true') {
            if ($odd) {
                $width = $width * 2 + 1;
            } else {
                $width = $width * 2;
            }
        }

        $tmpImage = Image::canvas($width, $height, $request->input('bgColor'));
        $offset = round($width * $request->input('offset') / 100);
        $yoffset = round($width * $request->input('yoffset') / 100);
        $tmpImage->insert($image, 'top-left', $offset, $yoffset);
        if ($request->has('isDoubleSides') && $request->input('isDoubleSides')) {
            $tmpImage->insert($image, 'top-right', $offset, $yoffset);
        }
        $image = $tmpImage;

        $image =  ((string)($image->encode('png')));
        $gcp = new \App\Http\Controllers\GoogleCloudStorageController;
        return $gcp->uploadStream($image, $filename);
    }

    public function getPrintLocations($orderItem)
    {
        $printAreas = [];
        $itemConfigs = json_decode($orderItem['configurations'], true);
        if (isset($itemConfigs['print_location']) && $itemConfigs['print_location']) {
            $printAreas[] = $itemConfigs['print_location'];
        } else if (isset($itemConfigs['is_print_back']) && $itemConfigs['is_print_back']) {
            $printAreas[] = 'back';
        } else {
            $printAreas[] = 'front';
        }

        $isDoubleSided = DB::table('product_meta')
            ->where('product_id', $orderItem['product_id'])
            ->where('key', 'double_sided')
            ->where('value', '1')
            ->count();

        if ($isDoubleSided) {
            $printAreas = ['front', 'back'];
        }

        return $printAreas;
    }

    public function simulateGetFulfillDesign(Request $request) {

        $inputs = $request->all();

        try {
            $designJobController = new \Modules\Pod\Controllers\DesignController;
            $result = $designJobController->getDesignByResolution(...array_values($inputs));
        } catch (Exception $e) {
            $result = $e->getMessage();
        }

        return [
            'inputs' => $inputs,
            'result' => $result,
        ];

    }

    public function updateTool() {
        return view('print-suppliers::home.update-tool');
    }
}
