<?php

namespace App\Repositories\Shop;

use App\Repositories\Core\User\ShopCart;

class Baskets
{
    public static function addBasket($offerId, $quantity = 1, $update = false)
    {
        if (ShopCart::has($offerId) && ! $quantity) {
            ShopCart::remove($offerId);
        }
        $data = $quantity ? self::getBasketData($offerId, $quantity) : false;

        return $data ? ShopCart::add($data, $update) : false;
    }

    public static function getBasketTotal($deliveryId = false, $deliveryTypeId = false)
    {
        $saleChannelId = Deliveries::getSaleChannelId($deliveryId);

        return self::getBasketSummary($saleChannelId, $deliveryTypeId);
    }

    public static function getBasketSummary($saleChannelId = false, $deliveryTypeId = false)
    {
        $total = 0;
        $totalTaxed = 0;
        $totalWeight = 0;
        $detail = [];
        $basket = ShopCart::getContent();
        $offers = Offers::getWithVariationByIds(self::getIds());

        foreach ($basket as $item) {
            $offer = $offers->where('id', $item->id)->first();
            $prices = Offers::getPrice($item->id, $item->quantity, $saleChannelId);
            $weight = $offer->weight * $item->quantity;
            $detail[] = self::getRowDetail($item, $offer, $prices, $weight);
            $total += $prices ? self::getTotal($item->quantity, $prices->price) : false;
            $totalTaxed += $prices ? self::getTotal($item->quantity, $prices->price_taxed) : false;
            $totalWeight += $weight;
        }
        $shipping = DeliveryTypeCalculations::getPriceByDeliveryType($deliveryTypeId, $totalWeight);

        return [
            'detail' => $detail,
            'total' => $total,
            'taxes' => $totalTaxed - $total,
            'total_taxed' => $totalTaxed,
            'shipping' => $shipping,
            'total_shipped' => $totalTaxed + $shipping,
            'count' => ShopCart::count(),
            'quantity' => ShopCart::getTotalQuantity(),
            'weight' => $totalWeight,
            'sale_channel' => SaleChannels::getArray($saleChannelId),
        ];
    }

    public static function getRowDetail($item, $offer, $prices, $weight)
    {
        return [
            'offer_id' => (int) $item->id,
            'name' => $offer->article->name.' ('.$offer->variation->name.')',
            'quantity' => (int) $item->quantity,
            'vat' => $prices ? (float) $prices->vat->value : false,
            'price' => $prices ? (float) $prices->price : false,
            'tax' => $prices ? $prices->price_taxed - $prices->price : false,
            'price_taxed' => $prices ? (float) $prices->price_taxed : false,
            'total' => $prices ? self::getTotal($item->quantity, $prices->price) : false,
            'total_tax' => $prices ? self::getTotal($item->quantity, $prices->price_taxed - $prices->price) : false,
            'total_taxed' => $prices ? self::getTotal($item->quantity, $prices->price_taxed) : false,
            'weight' => $weight,
        ];
    }

    public static function getWeight()
    {
        $basket = ShopCart::getContent();
        $offers = Offers::getWithVariationByIds(ShopCart::keys());
        $totalWeight = 0;
        foreach ($basket as $item) {
            $offer = $offers->where('id', $item->id)->first();
            $weight = $offer->weight * $item->quantity;
            $totalWeight += $weight;
        }

        return $totalWeight;
    }

    public static function getTotal($quantity, $price)
    {
        return $quantity * $price;
    }

    public static function getBasket($saleChannelId = false)
    {
        $saleChannelId = $saleChannelId ? $saleChannelId : SaleChannels::getDefaultID();
        $basket = ShopCart::getContent();
        $offers = Offers::getWithPricesByIds(self::getIds(), $saleChannelId);
        foreach ($basket as $item) {
            $offer = $offers->where('id', $item->id)->first();
            if (! $offer) {
                continue;
            }

            $priceValue = Offers::getPrice($item->id, $item->quantity, $saleChannelId);
            $unitPrice = $priceValue ? (float) $priceValue->price_taxed : (float) $item->price;

            $article_nature = strtolower($offer->article->article_nature->name);
            $data[$article_nature][] = [
                'id' => (int) $item->id,
                'name' => $item->name,
                'quantity' => (int) $item->quantity,
                'price' => $unitPrice,
                'variation' => $offer->variation->name,
                'image' => Articles::getPreviewSrc(ArticleImages::getFullImageByArticle($offer->article)),
                'latin' => $offer->article->product->specie->latin ?? false,
                'stock' => $offer->stock_current !== null ? (int) $offer->stock_current : null,
            ];
        }

        return $data ?? false;
    }

    public static function refreshPrices($saleChannelId = false)
    {
        $saleChannelId = $saleChannelId ? $saleChannelId : SaleChannels::getDefaultID();
        $basket = ShopCart::getContent();

        foreach ($basket as $item) {
            $priceValue = Offers::getPrice($item->id, $item->quantity, $saleChannelId);

            if (! $priceValue) {
                continue;
            }

            ShopCart::get()->update($item->id, [
                'price' => $priceValue->price_taxed,
            ]);
        }
    }

    public static function getBasketData($id, $quantity = 1)
    {
        $offer = Offers::get($id, ['article', 'variation']);

        if ($offer && $offer->stock_current !== null) {
            $quantity = min($quantity, max(0, (int) $offer->stock_current));
            if ($quantity <= 0) {
                return false;
            }
        }

        return [
            'id' => $id,
            'name' => self::getArticleName($offer),
            'price' => Offers::getPrice($id, $quantity)->price_taxed,
            'quantity' => $quantity,
            'attributes' => [],
        ];
    }

    public static function getArticleName(&$offer)
    {
        return $offer->article->name;
    }

    public static function getIds()
    {
        return ShopCart::keys();
    }
}
