<?php

namespace App\Livewire\Cart\Concerns;

use Daylight\Core\Models\Country;
use Daylight\Core\Models\OptionValue;
use Daylight\Core\Models\Variant;
use Daylight\Core\Modules\Cart\Cart;
use Daylight\Core\Modules\Cart\Contracts\CartInterface;
use Daylight\Core\Modules\Pricing\Facades\Pricing;
use Daylight\Core\Services\Countries;
use Illuminate\Support\Collection;
use Livewire\Attributes\On;

trait InteractsWithCart
{
    public array|Collection $variants = [];

    public array|Collection $cartItems = [];

    public array|Collection $dataLayerProducts = [];

    public function cart(): Cart
    {
        return app(CartInterface::class);
    }

    public function variantName(Variant $item): string
    {
        return $item->optionValues->map(function (OptionValue $optionValue) {
            return sprintf('%s: %s',
                $optionValue->option->name,
                $optionValue->name
            );
        })->join(' / ');
    }

    public function deleteItem($variantId)
    {
        $this->cart()->remove($variantId);

        $this->dispatch('cart-item-deleted');
        $this->dispatch('cart-updated');
    }

    public function updateQuantity($variantId, $quantity)
    {
        $this->cart()->changeQuantity($variantId, $quantity);
    }

    public function getBillingCountry(): Country
    {
        if (auth()->check() && auth()->user()->customer?->defaultBillingAddress) {
            return auth()->user()->customer->defaultBillingAddress->country;
        }

        return Countries::defaultCountry();
    }

    public function getShippingCountry(): Country
    {
        if (isset($this->form->shippingAddress['country_id'])) {
            return Countries::all()->firstWhere('id', $this->form->shippingAddress['country_id']);
        }

        return Countries::defaultCountry();
    }

    public function hasExemptedVat(): bool
    {
        return auth()->user()?->customer?->defaultBillingAddress?->hasExemptedVat() ?? false;
    }

    public function taxes(): Collection
    {
        if ($this->hasExemptedVat()) {
            return collect([
                [
                    'rate' => 0,
                    'amount' => 0,
                    'name' => __('VAT'),
                ],
            ]);
        }

        return $this->cartItems
            ->groupBy('tax_class_id')
            ->map(function ($variants, $class) {
                $taxRate = $this->getBillingCountry()->taxRates->where('tax_class_id', $class)->first();

                $subtotal = $variants->reduce(function ($carry, $variant) {
                    return intval($carry) + ($variant['price'] * $variant['quantity']);
                }, 0);

                $tax = $subtotal * ($taxRate->rate / 100);

                return [
                    'rate' => $taxRate->rate,
                    'amount' => $tax,
                    'name' => $taxRate->name,
                ];
            });
    }

    public function total(): float
    {
        return $this->subtotal() + $this->taxes()->sum('amount');
    }

    public function subtotal(): float
    {
        return $this->cartItems->sum(function ($item) {
            return $item['quantity'] * $item['price'];
        });
    }

    #[On('cart-updated')]
    public function loadCartItems(): void
    {
        $this->variants = $this->cart()->contents();

        $this->cartItems = $this->variants->map(function ($item) {
            return [
                'id' => $item->id,
                'image' => $item->getFirstMedia()->getUrl('thumbnail'),
                'name' => $item->product->name,
                'url' => translatedRoute('products.show', $item->product->slug),
                'variantName' => $this->variantName($item),
                'sku' => $item->sku,
                'price' => Pricing::for($item)->quantity($item->pivot->quantity)->get()->matched->price,
                'quantity' => $item->pivot->quantity,
                'tax_class_id' => $item->tax_class_id,
                'dataLayer' => $item->getDataLayerInformation($item->pivot->quantity),
            ];
        });

        $this->dataLayerProducts = $this->variants->map(function ($variant) {
            return $variant->getDataLayerInformation(
                $this->cartItems->firstWhere('sku', $variant->sku)['quantity']
            );
        });
    }

    public function mountInteractsWithCart(): void
    {
        $this->loadCartItems();
    }
}
