<?php

namespace App\Services\Shopify;

use App\Models\Catalog;
use App\Models\Company;
use App\Models\LicenseExtension;
use App\Models\LicenseExtensionProduct;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use RuntimeException;

/**
 * Service class that holds all license related Shopify related interaction and business logic
 */
class LicensesService extends BaseService
{
    // Amount of days after which a license extension product should be deleted if not used
    const LICENSE_EXTENSION_PRODUCT_TIMEOUT_DAYS = 60;

    /**
     * Creates a Shopify Product for a license extension
     *
     * @param Company $company
     * @param object $license
     * @param integer $duration
     * @return void
     */
    public function createLicenseExtensionProduct(Company $company, object $license, int $duration)
    {
        $extension = $license->extensions[$duration];
        $licenseExtension = LicenseExtension::where('nav_item_no', $extension['sku'])->first();
        $licenseNumber = str_replace(["\n", "\r"], ' - ', trim($license->License_Number));
        $productVersion = str_replace(["\n", "\r"], ' - ', trim($license->Product_and_Version));

        $shopifyProductInput = [
            'title' => 'NoldusCare Extension ' . $duration . ' year' . ($duration > 1 ? 's': ''),
            'vendor' => 'Noldus',
            'productType' => 'NC',
            'metafields' => [
                [
                    'key' => 'license_number',
                    'namespace' => $this->metaNamespace,
                    'type' => 'single_line_text_field',
                    'value' => $licenseNumber
                ],
                [
                    'key' => 'product_and_version',
                    'namespace' => $this->metaNamespace,
                    'type' => 'single_line_text_field',
                    'value' => $productVersion
                ],
                [
                    'key' => 'company_number',
                    'namespace' => $this->metaNamespace,
                    'type' => 'single_line_text_field',
                    'value' => $license->Related_Company_Number
                ],
                [
                    'key' => 'hfp',
                    'namespace' => $this->metaNamespace,
                    'type' => 'single_line_text_field',
                    'value' => '1'
                ]
            ],
            /*
            'variants' => [
                [
                    'options' => ['Default Title'],
                    'price' => $extension['price'],
                    'sku' => $extension['sku'],
                    'requiresShipping' => false
                ]
            ],
            'published' => true
            */
        ];

        $query = '
            mutation productCreate($input: ProductCreateInput!) {
                productCreate(product: $input) {
                    product {
                        id
                        variants(first:1) {
                            edges {
                                node {
                                    id
                                }
                            }
                        }
                    }
                    userErrors {
                        field
                        message
                    }
                }
            }
        ';

        $response = $this->api->graph($query, [
            'input' => $shopifyProductInput
        ]);

        if (!$this->_checkResponse($response, 'productCreate')) {
            return false;
        }

        $responseProduct = $response['body']['data']['productCreate']['product'];
        $responseVariant = $responseProduct['variants']['edges'][0]['node'];

        $query = '
            mutation productVariantsBulkUpdate($productId: ID!, $variants: [ProductVariantsBulkInput!]!) {
                productVariantsBulkUpdate(productId: $productId, variants: $variants) {
                    productVariants {
                        id
                        title
                        inventoryItem {
                            id
                        }
                        translations: metafield(namespace: "eae", key: "translations") {
                            id
                        }
                    }
                    userErrors {
                        field
                        message
                    }
                }
            }
        ';
        $response = $this->api->graph($query, [
            'productId' => $responseProduct['id'],
            'variants' => [
                [
                    'id' => $responseVariant['id'],
                    'price' => $extension['price'],
                    'inventoryItem' => [
                        'requiresShipping' => false,
                        'sku' => $extension['sku']
                    ]
                ]
            ]
        ]);
        if (!$this->_checkResponse($response, 'productVariantsBulkUpdate')) {
            return false;
        }

        $this->publishToOnlineStore($responseProduct['id']);

        $genericCatalog = Catalog::where('item_discount_group', '*')
            ->where('customer_discount_group', '*')
            ->first();

        if (!$company->exclusive_catalog_gid) {
            if (!$this->createCompanyCatalog($company)) {
                throw new RuntimeException('Unable to create company exlusive catalog');
            }
        }

        $this->_updatePublication($company->exclusive_publication_gid, [$responseProduct['id']]);
        $this->_updatePublication($genericCatalog->publication_gid, [], [$responseProduct['id']]);

        $licenseExtensionProduct = new LicenseExtensionProduct();
        $licenseExtensionProduct->company_id = $company->id;
        $licenseExtensionProduct->license_extension_id = $licenseExtension->id;
        $licenseExtensionProduct->product_gid = $responseProduct['id'];
        $licenseExtensionProduct->variant_gid = $responseVariant['id'];
        $licenseExtensionProduct->license_number = $licenseNumber;
        $licenseExtensionProduct->product = $productVersion;
        $licenseExtensionProduct->status = LicenseExtensionProduct::STATUS_PENDING;
        $licenseExtensionProduct->nvar = $license->nvar;
        $licenseExtensionProduct->save();

        $this->createProductImage($licenseExtensionProduct->product_gid, url('/noldus.png'));



        $idParts = explode('/', $responseProduct['id']);
        $varIdParts = explode('/', $responseVariant['id']);
        return [
            'productGid' => array_pop($idParts),
            'variantGid' => array_pop($varIdParts),
            'variantFullGid' => $responseVariant['id'],
            'licenseNumber' => $licenseNumber,
            'licenseProduct' => $productVersion
        ];
    }

    /**
     * Creates a company specific catalog
     *
     * @param Catalog $catalog
     * @return bool
     */
    public function createCompanyCatalog(Company $company, int $discount = 0)
    {
        $input = [
            'title' => 'NC-EXCLUSIVE: ' . $company->name,
            'status' => 'ACTIVE'
        ];

        $publicationData = $this->_createPublication(false);
        if (!$publicationData) {
            return false;
        }
        $input['publicationId'] = $publicationData['id'];

        $priceListData = $this->_createPriceList($company->name, $discount);
        if (!$priceListData) {
            return false;
        }
        $input['priceListId'] = $priceListData['id'];

        $query = '
            mutation catalogCreate($input: CatalogCreateInput!) {
                catalogCreate(input: $input) {
                    catalog {
                        id
                        publication {
                            id
                        }
                        priceList {
                            id
                        }
                    }
                    userErrors {
                        field
                        message
                    }
                }
            }
        ';

        $locationGids = $company->locations->pluck('shopify_gid');

        $input['context'] = [
            'companyLocationIds' => $locationGids,
        ];


        $response = $this->api->graph($query, [
            'input' => $input
        ]);

        if (!$this->_checkResponse($response, 'catalogCreate')) {
            return false;
        }

        $catalogResponse = $response['body']['data']['catalogCreate']['catalog'];
        $company->exclusive_catalog_gid = $catalogResponse['id'];
        $company->exclusive_publication_gid = !empty($catalogResponse['publication']['id']) ? $catalogResponse['publication']['id'] : null;
        $company->exclusive_price_list_gid = !empty($catalogResponse['priceList']['id']) ? $catalogResponse['priceList']['id'] : null;

        $company->save();
        return true;
    }

    /**
     * Adds an image to a product in Shopify
     *
     * @param string $productGid
     * @param string $imageUrl
     * @return void
     */
    public function createProductImage(string $productGid, string $imageUrl)
    {
        $query = '
            mutation productCreateMedia($media: [CreateMediaInput!]!, $productId: ID!) {
                productCreateMedia(media: $media, productId: $productId) {
                    mediaUserErrors {
                        field
                        message
                    }
                }
            }
        ';

        $response = $this->api->graph($query, [
            'media' => [
                'alt' => 'Noldus',
                'mediaContentType' => 'IMAGE',
                'originalSource' => $imageUrl
            ],
            'productId' => $productGid
        ]);

        if (!$this->_checkResponse($response, 'productCreateMedia', 'mediaUserErrors')) {
            return false;
        }
    }

    /**
     * Checks all expired not used license extensions and deletes related product in Shopify
     *
     * @return void
     */
    public function cleanLicenseProducts()
    {
        $expireDate = Carbon::now()->subDays(self::LICENSE_EXTENSION_PRODUCT_TIMEOUT_DAYS);
        $licenseProducts = LicenseExtensionProduct::where('status', LicenseExtensionProduct::STATUS_PENDING)
            ->where('created_at', '<', $expireDate)
            ->get();

        Log::info('[License Extension Products Cleaning] Found: ' . $licenseProducts->count() . ' expired');

        foreach ($licenseProducts as $licenseProduct) {
            if ($this->_deleteProduct($licenseProduct->product_gid)) {
                $licenseProduct->status = LicenseExtensionProduct::STATUS_EXPIRED;
                $licenseProduct->save();
            }
        }
    }

    /**
     * Deletes shopify product by GID
     *
     * @param string $productGid
     * @return bool
     */
    protected function _deleteProduct(string $productGid)
    {
        $query = '
            mutation productDelete($input: ProductDeleteInput!) {
                productDelete(input: $input) {
                    deletedProductId
                    userErrors {
                        field
                        message
                    }
                }
            }
        ';

        $response = $this->api->graph($query, [
            'input' => [
                'id' => $productGid
            ]
        ]);

        if (!$this->_checkResponse($response, 'productDelete')) {
            Log::warning('Error Deleting shopify product: ' . $productGid);
            return false;
        }
        Log::info('Deleted shopify product: ' . $productGid);
        return true;
    }
}
