<?php

namespace App\Shopify;

use App\Models\Category;
use App\Models\Product;
use App\Models\User;
use RuntimeException;

/**
 * Service class serves integration dashboard for product related logic
 */
class ProductsService
{
    const PRODUCTS_PER_PAGE = 20;
    const SORT_BY_MAPPING = [
        'integrationId' => 'id',
        'sapId' => 'sap_matnr'
    ];

    public function __construct()
    {
        $shopifyStore = config('shopify-app.sync_store');
        $this->shop = User::where('name', $shopifyStore)->first();
        if (!$this->shop) {
            throw new RuntimeException('Shopify store not found! Perhaps not installed yet? - ' . $shopifyStore);
        }
        $this->api = $this->shop->api();
        $this->storeDomain = $shopifyStore;
        $this->langs = config('shopify-app.available_languages');
        $this->defaultLang = config('shopify-app.default_language');
    }

    public function listProducts(int $page = 1, string $sortBy = 'integrationId', int $sortDesc = 1, array $filters = [])
    {
        $productsQuery = Product::with(['brand', 'childProducts'])
            ->whereNull('parent_id')
            ->orderBy(self::SORT_BY_MAPPING[$sortBy], $sortDesc ? 'desc' : 'asc');

        if (!empty($filters['categoryIds'])) {
            $productsQuery->whereIn('category_id', $filters['categoryIds']);
        }

        if (!empty($filters['sapIds'])) {
            $sapIds = array_map(function ($sapId) {
                return str_pad($sapId, 18, '0', STR_PAD_LEFT);
            }, $filters['sapIds']);
            $productsQuery->whereIn('sap_matnr', $sapIds);
        }

        $totalCount = $productsQuery->count();

        $products = $productsQuery->offset(($page - 1) * self::PRODUCTS_PER_PAGE)
            ->limit(self::PRODUCTS_PER_PAGE)
            ->get();

        // $shopifyIds = $products->pluck('shopify_id', 'id')->all();

        $outList = [];
        foreach ($products as $product) {
            $productLang = $product->languages->findByLocale($this->defaultLang);
            $priceToSync = false;
            if ($product->is_parent) {
                foreach ($product->childProducts as $child) {
                    if ($child->price->to_sync) {
                        $priceToSync = true;
                        break;
                    }
                }
            } else {
                $priceToSync = $product->price->to_sync;
            }

            $outList[] = [
                'sapId' => ($product->sap_matnr * 1) . '',
                'integrationId' => $product->id,
                'shopifyId' => $product->shopify_id,
                'brand' => $product->brand ? $product->brand->sap_descr : '',
                'desc' => $productLang->sap_descr,
                'range' => $product->sap_range,
                'toSync' => $product->to_sync ? true : false,
                'priceToSync' => $priceToSync ? true : false,
                'adminUrl' => $product->shopify_id ? ('https://' . $this->storeDomain . '/admin/products/' . $product->shopify_id) : ''
            ];
        }

        return [
            'list' => $outList,
            'total' => $totalCount,
            'sortBy' => $sortBy,
            'sortDesc' => $sortDesc,
            'page' => $page
        ];
    }

    public function getCategories()
    {
        $categories = Category::with('languages')
            ->whereNotNull('parent_id')
            ->get();

        return $categories;
    }

    protected function getShopifyProductsByIds($shopifyIds)
    {
        $shopifyGids = [];
        foreach ($shopifyIds as $id => $shopifyId) {
            $shopifyGids[$id] = '"gid://shopify/Product/' . $shopifyId . '"';
        }

        $query = '
            query {
                nodes(ids: [' . implode(',', $shopifyGids) . ']) {
                    ...on Product {
                        id
                        title
                        status
                    }
                }
            }
        ';

        $response = $this->api->graph($query);

        if (($response['status'] !== 200 && $response['status'] !== 201) || $response['errors']) {
            $msg = "Unable to get products from shopify: " . json_encode($response['errors']);
            throw new RuntimeException($msg);
        }

        return $response['body']['data']['nodes'];
    }
}
