<?php

namespace App\Modules\Wishlist;

use App\Models\User;
use App\Modules\Wishlist\Contracts\WishlistInterface;
use App\Modules\Wishlist\Models\Wishlist as WishlistModel;
use Daylight\Core\Models\Product;
use Illuminate\Session\SessionManager;
use Illuminate\Support\Collection;

class Wishlist implements WishlistInterface
{
    protected ?WishlistModel $instance = null;

    protected string $sessionKey = 'wishlist_session';

    public function __construct(
        protected SessionManager $sessionManager
    ) {
        //
    }

    public function exists(): bool
    {
        return $this->sessionManager->has($this->sessionKey) && $this->instance();
    }

    public function destroy(): void
    {
        $this->instance()->delete();

        $this->sessionManager->forget($this->sessionKey);
    }

    public function associate(User $user): void
    {
        if (! $user) {
            return;
        }

        $this->instance()->user()->associate($user);
        $this->instance()->save();
    }

    public function create(?User $user = null): WishlistModel
    {
        $instance = WishlistModel::make();

        if ($user) {
            $instance->user()->associate($user);
        }

        $instance->save();

        $this->sessionManager->put($this->sessionKey, $instance->uuid);

        return $instance;
    }

    public function add(Product $product): void
    {
        if ($this->getProduct($product)) {
            return;
        }

        $this->instance()->products()->syncWithoutDetaching([
            $product->id,
        ]);
    }

    public function getProduct(Product $product): ?Product
    {
        return $this->instance()->products()->find($product->id);
    }

    public function contents(): Collection
    {
        return $this->instance()->products;
    }

    public function getQuery()
    {
        return $this->instance()->products();
    }

    public function count(): int
    {
        return $this->contents()->count();
    }

    public function isEmpty(): bool
    {
        return $this->count() === 0;
    }

    public function remove(Product|int $product): void
    {
        $productId = $product instanceof Product ? $product->id : $product;

        $this->instance()->products()->detach($productId);
    }

    public function instance(): WishlistModel
    {
        if ($this->instance) {
            return $this->instance;
        }

        $existingInstance = WishlistModel::query()
            ->whereUuid($this->sessionManager->get($this->sessionKey))
            ->with([
                'products.translations' => function ($query) {
                    $query->where('locale', $this->sessionManager->pull('locale') ?? app()->getLocale());
                },
                'user.customer.customerGroups',
                'user.customer.defaultBillingAddress.country.taxRates',
                'user.customer.defaultBillingAddress.country.shippingZones',
            ])
            ->first();

        if (! $existingInstance) {
            return $this->instance = $this->create();
        }

        return $this->instance = $existingInstance;
    }
}
