<?php

namespace App\Repositories\Core\User;

use Cart;
use Illuminate\Support\Facades\Auth;

class ShopCart
{
    public static function add($item, $update = false)
    {
        if (self::has($item['id'])) {
            if ($update) {
                self::remove($item['id']);
                self::get()->add($item);
            } else {
                self::get()->update($item['id'], ['quantity' => $item['quantity']]);
            }
        } else {
            self::get()->add($item);
        }

        return [
            'count' => self::count(),
            'quantity' => self::getTotalQuantity(),
            'total' => self::getTotal(),
            'added' => $item,
        ];
    }

    public static function getSummary()
    {
        return [
            'count' => self::count(),
            'quantity' => self::getTotalQuantity(),
            'total' => self::getTotal(),
        ];
    }

    public static function remove($id)
    {
        return self::get()->remove($id);
    }

    public static function clear()
    {
        Cart::clear();

        return self::get()->clear();
    }

    public static function has($id)
    {
        return array_key_exists($id, self::getContent()->toArray());
    }

    public static function keys()
    {
        return array_keys(self::getContent()->toArray());
    }

    public static function count()
    {
        return self::getContent()->count();
    }

    public static function getTotalQuantity()
    {
        return self::get()->getTotalQuantity();
    }

    public static function getTotal()
    {
        return self::fixDecimal(self::get()->getTotal());
    }

    public static function fixDecimal($number)
    {
        return number_format(round($number, 2), 2);
    }

    public static function getItemQuantity($id)
    {
        return self::getItem($id) ? (int) self::getItem($id)->quantity : 0;
    }

    public static function getItem($id)
    {
        return Cart::get($id);
    }

    public static function getContent()
    {
        return self::get()->getContent();
    }

    public static function migrateGuestCartToUser($userId = null)
    {
        $userId = self::resolveUserId($userId);

        if ($userId === null) {
            return;
        }

        $guestSessionKey = self::sessionKey();
        $guestItems = Cart::session($guestSessionKey)->getContent();

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

        $userSessionKey = self::sessionKey($userId);

        foreach ($guestItems as $item) {
            $existing = Cart::session($userSessionKey)->get($item->id);

            if ($existing) {
                Cart::session($userSessionKey)->update($item->id, [
                    'quantity' => [
                        'relative' => false,
                        'value' => $existing->quantity + $item->quantity,
                    ],
                ]);

                continue;
            }

            $itemData = [
                'id' => $item->id,
                'name' => $item->name,
                'price' => $item->price,
                'quantity' => $item->quantity,
                'attributes' => self::extractAttributes($item),
            ];

            if (isset($item->associatedModel)) {
                $itemData['associatedModel'] = $item->associatedModel;
            }

            $conditions = self::extractConditions($item);
            if (! empty($conditions)) {
                $itemData['conditions'] = $conditions;
            }

            Cart::session($userSessionKey)->add($itemData);
        }

        Cart::session($guestSessionKey)->clear();
        Cart::session($userSessionKey);
    }

    protected static function extractAttributes($item)
    {
        if (! isset($item->attributes)) {
            return [];
        }

        if (is_object($item->attributes) && method_exists($item->attributes, 'toArray')) {
            return $item->attributes->toArray();
        }

        return (array) $item->attributes;
    }

    protected static function extractConditions($item)
    {
        if (! isset($item->conditions)) {
            return [];
        }

        if (is_object($item->conditions) && method_exists($item->conditions, 'toArray')) {
            return $item->conditions->toArray();
        }

        return (array) $item->conditions;
    }

    protected static function resolveUserId($userId = null)
    {
        return $userId ?? Auth::guard('customer')->id();
    }

    protected static function sessionKey($userId = null)
    {
        $key = $userId ?? 'guest';

        return 'cart_'.sha1(static::class.$key);
    }

    protected static function session($userId = null)
    {
        return Cart::session(self::sessionKey($userId));
    }

    public static function get($userId = null)
    {
        return self::session(self::resolveUserId($userId));
    }
}
