<?php

use App\Models\Inventory\Inventory;
use Mtc\Core\Images\ImageUploader;
use Mtc\Shop\Brand;
use Mtc\Shop\CustomFieldSetField;
use Mtc\Shop\Item\Custom;
use Mtc\Shop\Item\CustomMultiple;
use Mtc\Shop\Item\Image as ItemImage;
use Mtc\Shop\Item\Size as ItemSize;
use Mtc\Shop\PlaceholderImage;
use Illuminate\Support\Facades\DB;

/**
 * Item.
 *
 * @author mtc.
 * @copyright 2013 mtc. http://www.mtcmedia.co.uk/
 *
 * @version 2013
 */
class Item
{
    public $id;
    public $name;
    public $code;
    public $epos_id;
    public $epos_code;
    public $description;
    public $basket_image;
    public $percentage_off;
    public $price = 0;
    public $price_exvat = 0;
    public $sale_price = 0;
    public $sale_price_exvat = 0;
    public $stock;
    public $heavy = 0;
    public $images;
    public $image_default;
    public $image_hover;
    public $image_basket;
    public $brand;
    public $brand_name;
    public $brand_image;
    public $nosizes = false;
    public $weight;
    public $google_category;
    public $categories = [];
    public $parent_categories;
    public $hidden = 0;
    public $deleted;
    public $sizes;
    public $size_strengths;
    public $c_rates;
    public $c_selected;
    public $c_symbol;
    public $url;
    public $vat_rate;
    public $vat_deductable;
    public $preorder = false;
    public $warnings = [];
    public $product_type = '';
    public $id_check_required;
    public $can_be_sold_separately = '';
    public $basket_quantity_locked = '';
    public $disable_assessment_forms = '';
    public $bundle_page_url = '';
    public $is_groupbuy_container = '';
    public $groupbuy_bundletype_id = null;
    public $form_id = '';
    public $created_at;
    public $updated_at;

    public $custom_field_set_id = 0;
    public $custom = array();
    /*
     * SEO
     */
    public $seo_title;
    public $seo_keywords;
    public $seo_description;

    public $magento_entity_id;
    public $search_name;
    public $search_description;
    public $sort_price;
    public $sex;
    public $times_purchased;
    public $num_sold;
    public $num_views;
    public $num_basket;
    public $seo_schema_cache;
    public $restriction_period_length;
    public $restriction_per_period;
    public $restriction_per_order;
    public $restriction_limit_once;
    public $subscription_is_allowed;
    public $subscription_can_be_paused;
    public $subscription_max_number_of_issues;
    public $view_image;
    public $view_price;
    public $from_price;
    public $image_zoom;
    public $main_category;
    public $image_basket_alt;
    public $free_delivery;

    /**
     * Constructor.
     * Set session if it is defined in session
     * Load item if ID is passed
     *
     * @param int $id Item ID to load
     */
    public function __construct($id = 0)
    {

        if (isset($_SESSION['currency']['currency'])) {
            $this->c_selected = $_SESSION['currency']['currency'];
        }
        if (!empty($id)) {
            $this->Get_Item($id);
        }
    }

    /**
     * Item::Get_Item().
     *
     * @param int $id Item ID
     * @param bool $only_basics Can we load only basics to ensure that we don't execute irrelevant queries
     * @return bool whether the item was found and loaded
     */
    public function Get_Item($id, $only_basics = false)
    {
        if (!$item = \Mtc\Shop\Item::query()->find($id)) {
            return false;
        }

        $data = $item->toArray();

        $this->id = $data['id'];
        $this->name = $data['name'];
        $this->description = $data['description'];
        $this->price = $data['price'];
        $this->price_exvat = $data['price_exvat'];
        $this->sale_price = $data['sale_price'];
        $this->sale_price_exvat = $data['sale_price_exvat'];

        if ($this->price == $this->sale_price) {
            $this->sale_price = 0;
        }

        $this->percentage_off = 0;

        if ($this->sale_price > 0 && $this->price > 0) {
            $this->percentage_off = floor((($this->price - $this->sale_price) / $this->price) * 100);
        }

        $this->code = $this->epos_id = $this->epos_code = $data['epos_code'];
        $this->weight = $data['weight'];
        $this->heavy = $data['heavy'];
        $this->vat_rate = $data['vat_rate'];
        $this->vat_deductable = $data['vat_deductable'];

        $this->seo_schema_cache = $data['seo_schema_cache'];
        $this->seo_title = $data['seo_title'];
        $this->seo_keywords = $data['seo_keywords'];
        $this->seo_description = $data['seo_description'];

        $this->hidden = $data['hidden'];
        $this->deleted = $data['deleted'];
        $this->stock = $data['stock'];
        $this->product_type = $data['product_type'];
        $this->id_check_required = $data['id_check_required'];
        $this->can_be_sold_separately = $data['can_be_sold_separately'];
        $this->basket_quantity_locked = $data['basket_quantity_locked'];
        $this->disable_assessment_forms = $data['disable_assessment_forms'];
        $this->bundle_page_url = $data['bundle_page_url'];
        $this->is_groupbuy_container = $data['is_groupbuy_container'];
        $this->groupbuy_bundletype_id = $data['groupbuy_bundletype_id'] ?: null;
        $this->custom_field_set_id = $data['custom_field_set_id'];
        $this->warnings = \Mtc\Shop\Item::getWarnings($id);
        $this->form_id = $data['form_id'];
        $this->restriction_period_length = $data['restriction_period_length'];
        $this->restriction_per_period = $data['restriction_per_period'];
        $this->restriction_per_order = $data['restriction_per_order'];
        $this->restriction_limit_once = $data['restriction_limit_once'];
        $this->subscription_is_allowed = $data['subscription_is_allowed'];
        $this->subscription_can_be_paused = $data['subscription_can_be_paused'];
        $this->subscription_max_number_of_issues = $data['subscription_max_number_of_issues'];
        $this->created_at = $data['created_at'];
        $this->updated_at = $data['updated_at'];

        $this->Get_Images();
        $this->getCustom();
        $this->Generate_URL('');

        // Pages like Browse don't need everything, just the basics + images and url
        if ($only_basics) {
            return true;
        }

        $this->Get_Brand();
        $this->getCategories();
        $this->Get_Sizes();

        //Use lowest price from sizes
        if (!empty($this->sizes)) {

            //Reset array keys
            $sizes = array_values($this->sizes);

            if (!empty($sizes[0]['display_price'])) {
                $this->price = $sizes[0]['display_price'];
            }
        }

        $this->get_basket_image();

        return true;
    }

    /**
     * Item::Insert_Item().
     *
     * @return
     */
    public function Insert_Item()
    {
        $sort_price = $this->price;
        if ($this->sale_price > 0 && $this->sale_price < $this->price) {
            $sort_price = $this->sale_price;
        }

        $search_description = '';
        if (preg_match('#<div class="wysiwyg"></div>#', $this->description)) {
            $this->description = '';
        }
        if ($this->description != '') {
            $search_description = implode(' ', PorterStemmer::multi_stem(strip_tags($this->description)));
        }

        $search_name = '';
        if ($this->name != '') {
            $search_name = implode(' ', PorterStemmer::multi_stem($this->name));
        }

        $params = array(
            'basket_quantity_locked' => $this->basket_quantity_locked,
            'disable_assessment_forms' => $this->disable_assessment_forms,
            'bundle_page_url' => $this->bundle_page_url,
            'can_be_sold_separately' => $this->can_be_sold_separately,
            'custom_field_set_id' => $this->custom_field_set_id,
            'description' => $this->description,
            'epos_code' => $this->epos_code,
            'female' => empty($this->female) ? 0 : $this->female,
            'form_id' => $this->form_id,
            'groupbuy_bundletype_id' => $this->groupbuy_bundletype_id ?: null,
            'heavy' => empty($this->heavy) ? 0 : $this->heavy,
            'is_groupbuy_container' => $this->is_groupbuy_container,
            'name' => $this->name,
            'price' => $this->price ?? 0,
            'price_exvat' => $this->price_exvat ?? 0,
            'product_type' => $this->product_type,
            'id_check_required' => $this->id_check_required,
            'restriction_limit_once' => $this->restriction_limit_once,
            'restriction_per_order' => $this->restriction_per_order,
            'restriction_per_period' => $this->restriction_per_period,
            'restriction_period_length' => $this->restriction_period_length,
            'sale_price' => empty($this->sale_price) ? 0 : $this->sale_price,
            'sale_price_exvat' => empty($this->sale_price_exvat) ? 0 : $this->sale_price_exvat,
            'search_description' => $search_description,
            'search_name' => $search_name,
            'seo_description' => $this->seo_description ?? '',
            'seo_keywords' => $this->seo_keywords ?? '',
            'seo_title' => $this->seo_title ?? '',
            'sort_price' => $sort_price ?? 0,
            'vat_deductable' => empty($this->vat_deductable) ? 0 : $this->vat_deductable,
            'vat_rate' => empty($this->vat_rate) ? 0 : $this->vat_rate,
            'weight' => $this->weight,
        );

        $item = Mtc\Shop\Item::create($params);

        $this->id = $item->id;
    }

    /**
     * Item::Update_Item().
     *
     * @return
     */
    public function Update_Item()
    {
        $search_name = implode(' ', PorterStemmer::multi_stem($this->name));
        $search_description = '';
        if (!empty($this->description) && PorterStemmer::multi_stem(strip_tags($this->description)) !== false) {
            $search_description = implode(' ', PorterStemmer::multi_stem(strip_tags($this->description)));
        }

        $params = array(
            'name' => $this->name,
            'search_name' => $search_name,
            'description' => $this->description,
            'search_description' => $search_description,
            'price' => $this->price,
            'price_exvat' => $this->price_exvat,
            'sale_price' => $this->sale_price,
            'sale_price_exvat' => $this->sale_price_exvat,
            'heavy' => empty($this->heavy) ? 0 : $this->heavy,
            'epos_code' => $this->epos_code,
            'vat_rate' => empty($this->vat_rate) ? 0 : $this->vat_rate,
            'vat_deductable' => empty($this->vat_deductable) ? 0 : $this->vat_deductable,
            'weight' => $this->weight,
            'seo_title' => $this->seo_title,
            'seo_keywords' => $this->seo_keywords,
            'seo_description' => $this->seo_description,
            'custom_field_set_id' => $this->custom_field_set_id,
            'product_type' => $this->product_type,
            'id_check_required' => $this->id_check_required,
            'can_be_sold_separately' => $this->can_be_sold_separately ?? '0',
            'basket_quantity_locked' => $this->basket_quantity_locked ?? '0',
            'disable_assessment_forms' => $this->disable_assessment_forms ?? '0',
            'bundle_page_url' => $this->bundle_page_url,
            'is_groupbuy_container' => $this->is_groupbuy_container ?? '0',
            'groupbuy_bundletype_id' => $this->groupbuy_bundletype_id ?: null,
            'form_id' => $this->form_id,
            'restriction_period_length' => $this->restriction_period_length,
            'restriction_per_period' => $this->restriction_per_period,
            'restriction_per_order' => $this->restriction_per_order,
            'restriction_limit_once' => $this->restriction_limit_once,
        );

        Mtc\Shop\Item::query()
            ->where('id', $this->id)
            ->update($params);

        \Mtc\Shop\Item::updateSortPrice($this->id);
    }

    /**
     * Item::Update_Hidden().
     *
     * @return void
     */
    public function Update_Hidden(): void
    {
        \Mtc\Shop\Item::query()
            ->where('id', $this->id)
            ->update([
                'hidden' => $this->hidden,
            ]);
    }
    /*
      Update Stock
     */

    /**
     * @return void
     */
    public function Update_Stock(): void
    {
        \Mtc\Shop\Item::query()
            ->where('id', $this->id)
            ->update([
                'stock' => $this->stock,
            ]);
    }

    /**
     * Deducts Stock
     *
     * @param $amount
     * @return void
     */
    public function Deduct_Stock($amount): void
    {
        if (config('ecom.stock.advanced')) {
            Inventory::deductQuantity([$this->epos_code, 'product'], (int) $amount);
            return;
        }

        $this->stock = $this->stock - (int) $amount;
        $this->Update_Stock();
    }

    /**
     * Reduce Item size stock after purchase
     * @param int $amount the amount by which to decrease of the size
     * @param int $item_id item ID for which to do the deduction
     * @param string $size size for which to do the deduction
     */
    public function Deduct_Size_Stock($amount, $item_id, $size): void
    {
        if (config('ecom.stock.advanced')) {
            DB::transaction(function () use ($amount, $item_id, $size) {

                $sku = ItemSize::ofItem($item_id)
                    ->where('size', $size)
                    ->first()->PLU ?? NULL;

                if ($sku) {
                    Inventory::deductQuantity([$sku, 'variant'], (int) $amount);
                }
            });
            return;
        }

        ItemSize::ofItem($item_id)
            ->where('size', $size)
            ->decrement('stock', $amount);

    }

    /*
      Get the images for this item
     */

    /**
     * Item::Get_Images().
     *
     */
    public function Get_Images()
    {
        $this->image_zoom = 0;
        require SITE_PATH . '/shop/includes/image_folders.php';

        $this->images = ItemImage::ofItem($this->id)
            ->orderBy('order', 'ASC')
            ->get()
            ->toArray();

        if (!empty($this->images)) {
            foreach ($this->images as $key => $image) {
                $file_name = '/' . $image_folders['product_folders']['large']['path'] . '/' . $image['name'];
                if (!file_exists(SITE_PATH . $file_name)) {
                    unset($this->images[$key]);
                    continue;
                }

                if (!empty($image['default'])) {
                    $this->image_default = $key;
                }

                if (!empty($image['zoom'])) {
                    $this->image_zoom = $key;
                }
            }
        }
    }

    /**
     * Get the brand for this item
     *
     * @return void
     */
    public function Get_Brand(): void
    {
        $brand = \Mtc\Shop\Item::query()
            ->where('id', $this->id)
            ->first()
            ->brands
            ->first();

        if (!empty($brand)) {
            $this->brand = $brand->id;
            $this->brand_name = $brand->name;
            $this->brand_image = $brand->image;
        }
    }

    /**
     * Attach brand
     *
     * @return void
     */
    public function Insert_Brand(): void
    {
        if ($brand = Brand::query()->find($this->brand)) {
            \Mtc\Shop\Item::query()
                ->find($this->id)
                ->brands()
                ->attach($brand);
        }
    }

    /**
     * Item::Update_Brand().
     *
     * @return void
     */
    public function Update_Brand(): void
    {
        $this->eloquent()->brands()->sync([$this->brand]);
    }

    /**
     * Gets item categories
     *
     * @return void
     */
    public function getCategories(): void
    {
        $categories = $this->eloquent()
            ->categories()
            ->select([
                'categories.id as cat_id',
                'categories.id',
                'categories.name',
                'categories.is_online_doctor',
            ])
            ->get();

        $this->categories = $categories->keyBy('id')->toArray();
    }

    /**
     * Item::Update_Categories().
     *
     * @return void
     */
    public function Update_Categories(): void
    {
        $this->eloquent()
            ->categories()
            ->sync($this->categories);

        // For any new additions, make sure that the new item is added as the last in order
        DB::table('items_categories')
            ->where('item_id', $this->id)
            ->where('order', 0)
            ->update([
                'order' => DB::raw('id'),
            ]);
    }

    /*
      Generate the URL to the Item;
     */

    /**
     * Item::Generate_URL().
     *
     * @return
     */
    public function Generate_URL($image = '', $color = 0)
    {
        //Standard Address
        $catname = null;
        if ($this->categories) {
            $catname = clean_value(Category_Name(reset($this->categories)['cat_id']));
        }
        $brandname = clean_value($this->brand_name);

        $text = '';
        if (!empty($brandname)) {
            $text = $brandname . '/';
        } elseif (!empty($catname)) {
            $text = clean_value($catname) . '/';
        }

        //use === to avoid 0 == ''
        if ($image === '') {
            $image = $this->image_default;
        }

        if (empty($this->brand)) {
            $this->brand = 0;
        }

        if (!empty($this->custom['slug'])) {
            $this->url = '/medications/' . $this->custom['slug'];
            return $this->url;

        }

        $this->url = '/item/' . $this->id . '/' . $text . clean_value(str_replace(' ', '-', trim($this->name))) . '.html';

        if ($image != $this->image_default) {
            $this->url .= '?image=' . $image;
        }
        $this->url = preg_replace("/-{2,}/", '-', $this->url);
        // Remove trailing hyphen when there is no file extension specified
        $this->url = preg_replace("/-+$/", '-', $this->url);
        // Remove trailing hyphen when file extension specified
        $this->url = str_replace("-.html", ".html", $this->url);

        return $this->url;
    }

    /**
     * Get the sizes for this item
     * If no sizes exist add a default "One size" entry
     */
    public function Get_Sizes()
    {
        $this->sizes = ItemSize::ofItem($this)
            ->selectBasics()
            ->get()
            ->map(function ($size) {
                $size->display_price = $size->sale_price > 0 ? $size->sale_price : $size->price;
                return $size;
            })
            ->sortBy('display_price')
            ->toArray();

        if (empty($this->sizes)) {
            $this->sizes = [
                [
                    'id' => 0,
                    'stock' => $this->stock,
                    'size' => 'One Size',
                    'price' => $this->price,
                    'sale_price' => 0,

                ]
            ];
            $this->nosizes = true;
        } else {
            $this->size_strengths = [];
            foreach ($this->sizes as $size) {
                if (!empty($size['hide'])) {
                    continue;
                }
                $this->size_strengths[$size['strength']][] = $size;
            }
        }
    }


    /**
     * Item::get_basket_image().
     *
     * @return item basket image url
     */
    public function get_basket_image()
    {
        //needed for declaration of $image_folders['product_folders']
        require SITE_PATH . '/shop/includes/image_folders.php';

        //cropped thumbs url path
        $image_url = '/' . $image_folders['product_folders']['thumbs']['path'] . '/';

        //image location path on server
        $image_path = SITE_PATH . '/' . $image_folders['product_folders']['thumbs']['path'] . '/';

        $placeholder_images = PlaceholderImage::getPackedData();

        //if item image is set and exists
        if (isset($this->image_default) && !empty($this->images[$this->image_default]['name'])) {

            $image_path .= $this->images[$this->image_default]['name'];

            if (is_file($image_path) === true) {
                $this->image_basket = $image_url . $this->images[$this->image_default]['name'];
                $this->image_basket_alt = $image_url . $this->images[$this->image_default]['alt'];
            }
            //else if item placeholder image exists
        } elseif (!empty($placeholder_images['item_small']['value'])) {
            $this->image_basket = $image_url . $placeholder_images['item_small']['value'];
            $this->image_basket_alt = $this->name;

            //else no item basket image
        } else {
            $this->image_basket = '';
        }

        return $this->image_basket;
    }

    /**
     * Gets the custom fields for this item.
     */
    public function getCustom(): void
    {
        $this->custom = Custom::query()
            ->where('item_id', $this->id)
            ->firstOrNew()
            ->toArray();

        $customMultiple = CustomMultiple::query()->where('item_id', $this->id)->get();

        foreach ($customMultiple as $multiple) {
            if (!is_array($this->custom[$multiple->field])) {
                $this->custom[$multiple->field] = [];
            }
            $this->custom[$multiple->field][] = $multiple->value;
        }
    }

    /**
     * Saves to the database the custom fields for this item.
     */
    public function saveCustom()
    {

        //Get the fields used by this set. non multiple fields only.
        $database_fields = CustomFieldsHelper::getSetDatabaseFields($this->custom_field_set_id, 'item', 0);

        if (!empty($this->custom['slug']) && !in_array('slug', $database_fields)) {
            $database_fields[] = 'slug';
        }

        if (sizeof($database_fields) > 0) {
            $values = [];
            foreach ($database_fields as $field) {
                $values[$field] = $this->custom[$field] ?? null;
            }

            Custom::query()
                ->updateOrCreate(
                    [
                        'item_id' => $this->id
                    ],
                    $values
                );
        }

        /*
         * Get All the fields that support multiple values/
         */
        $database_fields_multiple = CustomFieldsHelper::getSetDatabaseFields($this->custom_field_set_id, 'item', 1);

        /*
         * Update the values.
         */

        CustomMultiple::query()
            ->where('item_id', $this->id)
            ->delete();

        foreach ($database_fields_multiple as $field) {

            $this->custom[$field] = array_unique(array_filter($this->custom[$field]));

            if (sizeof($this->custom[$field]) > 0) {

                foreach ($this->custom[$field] as $value) {
                    if (empty($value)) {
                        continue;
                    }

                    CustomMultiple::query()
                        ->create([
                            'item_id' => $this->id,
                            'field' => $field,
                            'value' => $value
                        ]);
                }
            }
        }

    }

    /**
     * Increase the added to basket on items by one
     *
     * @return void
     */
    public function incrementNumBasket()
    {
        \Mtc\Shop\Item::query()
            ->where('id', $this->id)
            ->increment('num_basket');
    }

    /**
     * Item::getRedirectURL()
     *
     * Figures out where to redirect to, e.g. when item not available
     *
     * @return string url
     */
    public function getRedirectURL(string $reason = '-')
    {
        if (!empty($this->categories)) {
            //strip categories that do not contain any available items
            $filter = new ProductFilter();
            if (BRANDS_ENABLED) {
                $filter->selections['brands'] = [$this->brand];
            }
            $filter->getResults('cat');
            $valid_categories = array_intersect_key($this->categories, $filter->results['cats']);
            if (empty($valid_categories)) {
                //if there is no category/brand alternative, try any brand
                $filter->selections['brands'] = [];
                $filter->getResults('cat');
                $valid_categories = array_intersect_key($this->categories, $filter->results['cats']);
                return browse_url(reset($valid_categories)['cat_id']) . "?inaccessible_item_id={$this->id}&r=a&e={$reason}";
            } else {
                //brand/category alternatives available
                return browse_url(reset($valid_categories)['cat_id'], $this->brand) . "?inaccessible_item_id={$this->id}&r=b&e={$reason}";
            }
        }
        return "/browse/?inaccessible_item_id={$this->id}&r=c&e={$reason}";
    }

    /**
     * Deletes an item by setting a flag in the item table that should stop it from showing up on the site.
     *
     * Also removes images and deletes references to the item that might make it show up accidentally, such as featured
     * items.
     *
     * @author Lukas Giegerich <lukas.giegerich@mtcmedia.co.uk>
     *
     * @param int $id
     *
     * @return boolean
     */
    public function delete()
    {

        if ($this->id <= 0) {
            return false;
        }

        $this->eloquent()
            ->update([
                'deleted' => 1,
            ]);

        //hook that can be used for deleting product from featured products
        // as well if FeaturedProducts plugin installed
        HooksAdapter::do_action(__CLASS__ . '/' . __FUNCTION__, $this->id);

        //delete images
        $images = ItemImage::ofItem($this->id)->get();

        //needed for declaration of $image_folders['product_folders']
        require SITE_PATH . '/shop/includes/image_folders.php';

        foreach ($images as $delete_image) {
            foreach ($image_folders['product_folders'] as $folder) {
                $image_path = SITE_PATH . '/' . $folder['path'] . '/' . $delete_image->name;

                if (file_exists($image_path)) {
                    @unlink($image_path);
                }
            }
            $delete_image->delete();
        }

        return true;
    }


    /**
     * Saves custom fields images.
     *
     * @author Davis Lasis <davis.lasis@mtcmedia.co.uk>
     * @param int $set_id
     * @param string $type
     * @param $folders
     * @return void
     */
    public function saveCustomImages($set_id, $type, $folders): void
    {
        $fields = CustomFieldSetField::query()
            ->where('set_id', $set_id)
            ->when($type == 'item', function ($query) {
                $query->where('items', 1);
            })
            ->when($type == 'variations', function ($query) {
                $query->where('variations', 1);
            })
            ->get();

        if ($fields->count() == 0) {
            return;
        }

        foreach ($fields as $field) {
            $data = $field->toArray();
            $custom_field_data = CustomFieldsHelper::getCustomFieldData($data['custom_field_id']);

            if ($custom_field_data['type'] == 'image_upload') {
                if (!empty($_FILES['custom']['name'][$custom_field_data['database_field']])) {
                    $uploader = ImageUploader::newInstance($folders);
                    $file = $uploader->file('custom');
                    $filedata = $uploader->uploadImage($file[$custom_field_data['database_field']]);
                    $filename = $filedata['name'];
                    $this->custom[$custom_field_data['database_field']] = $filename;
                    $update_field = array($custom_field_data['database_field'] => $filename);
                }
            }
        }

        if (!empty($update_field)) {
            Custom::query()
                ->updateOrCreate([
                    'item_id' => $this->id,
                ], $update_field);
        }
    }

    /**
     * Return an Eloquent model of this item.
     * @return \Mtc\Shop\Item
     */
    public function eloquent()
    {
        return \Mtc\Shop\Item::query()
            ->find($this->id);
    }

    public function loadItemSmall($item_id)
    {

        $item_data = \Mtc\Shop\Item::query()
            ->with(['custom', 'images', 'sizes'])
            ->find($item_id);

        $this->images = $item_data->images->toArray();

        if (!empty($this->images)) {
            foreach ($this->images as $key => $image) {
                if (!empty($image['default'])) {
                    $this->image_default = $key;
                }
            }
        }
        $this->custom = (Array) $item_data->custom;
        $this->sizes = $item_data->sizes
            ->map(function ($size) {
                $size->display_price = $size->sale_price > 0 ? $size->sale_price : $size->price;
                return $size;
            })
            ->sortBy('display_price')
            ->toArray();

        if (empty($this->sizes)) {
            $this->sizes = [
                [
                    'id' => 0,
                    'stock' => $this->stock,
                    'size' => 'One Size',
                    'price' => $this->price,

                ]
            ];
            $this->nosizes = true;
        } else {
            $this->size_strengths = [];
            foreach ($this->sizes as $size) {
                if (!empty($size['hide'])) {
                    continue;
                }
                $this->size_strengths[$size['strength']][] = $size;
            }
        }

        $sizes = $item_data->sizes();
        $item_data = $item_data->toArray();
        foreach ($item_data as $key => $value) {
            $this->{$key} = $value;
        }

        $this->code = $this->epos_id = $this->epos_code = ($data['epos_code'] ?? null);


        if ($sizes->count() > 0) {
            foreach ($sizes->get() as $size) {
                // If sale price set, use that
                if ($size->sale_price > 0) {
                    $size_price = $size->sale_price;
                } else {
                    $size_price = $size->price;
                }

                // If the new price is lower, set that as item From price
                if (empty($min_price) || ($size_price < $min_price && $size_price > 0)) {
                    $min_price = $size_price;
                    if ($size->sale_price > 0) {
                        // If we have a sale price, set the Item sale price and Percentage off
                        $this->sale_price = $size->sale_price;
                    } else {
                        $this->sale_price = 0;
                    }
                }
            }

        } else {
            if ($this->price == $this->sale_price) {
                $this->sale_price = 0;
            }
        }

        $this->percentage_off = 0;

        if ($this->sale_price > 0 && $this->price > 0) {
            $this->percentage_off = floor((($this->price - $this->sale_price) / $this->price) * 100);
        }


        $this->Generate_URL('');


        $price = $this->price;
        $this->view_image = $image ?? null;
        $this->view_price = $price;

    }


    public function isInStock()
    {
        $is_in_stock = false;

        if ($this->eloquent()) {
            $is_in_stock = $this->eloquent()->isInStock();
        }

        return $is_in_stock;
    }


    public function findAssessmentForm()
    {
        $af = null;

        if ($this->eloquent()) {
            $af = $this->eloquent()->findAssessmentForm();
        }

        return $af;
    }


    public function getMainCategory()
    {
        $cat = null;

        if ($this->eloquent()) {
            $cat = $this->eloquent()->getMainCategory();
        }

        return $cat;
    }

    public function getAllCategoryIDs()
    {
        $ids = [];

        if ($this->eloquent()) {
            $ids = $this->eloquent()->getAllCategoryIDs();
        }

        return $ids;
    }


    public function isHidden()
    {
        $is_hidden = false;

        if ($this->eloquent()) {
            $is_hidden = $this->eloquent()->isHidden();
        }

        return $is_hidden;
    }

}
