<?php

namespace Modules\FlashSale\Entities;

use Modules\Support\Money;
use Modules\Admin\Ui\AdminTable;
use Modules\Support\Eloquent\Model;
use Modules\Product\Entities\Product;
use Modules\Support\Eloquent\Translatable;

class FlashSale extends Model
{
    use Translatable;

    /**
     * Active flash sale.
     *
     * @var self
     */
    private static $active;
    /**
     * The attributes that are translatable.
     *
     * @var array
     */
    public $translatedAttributes = ['campaign_name'];
    /**
     * The relations to eager load on every query.
     *
     * @var array
     */
    protected $with = ['translations'];
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = ['id'];


    /**
     * Set an active flash sale campaign.
     *
     * @param int $id
     *
     * @return void
     */
    public static function activeCampaign($id)
    {
        self::$active = function () use ($id) {
            return once(function () use ($id) {
                return self::withEligibleProducts()->where('id', $id)->firstOrNew([]);
            });
        };
    }


    public static function contains(Product $product)
    {
        return self::active()->products->contains($product);
    }


    /**
     * Get the active flash sale.
     *
     * @param int $id
     *
     * @return self
     */
    public static function active()
    {
        if (is_callable(self::$active)) {
            return call_user_func(self::$active);
        }

        return new self;
    }


    public static function remainingQty(Product $product)
    {
        $flashSaleProduct = self::pivot($product);

        return $flashSaleProduct->qty - $flashSaleProduct->sold;
    }


    public static function pivot(Product $product)
    {
        return self::active()->products->find($product)->pivot;
    }


    /**
     * Perform any actions required after the model boots.
     *
     * @return void
     */
    protected static function booted()
    {
        static::saved(function ($flashSale) {
            if (!empty(request()->has('products'))) {
                $flashSale->saveProducts(request('products'));
            }
        });
    }


    public function saveProducts($products)
    {
        $this->products()->sync(
            $this->buildProductPivots($products)
        );
    }


    public function products()
    {
        return $this->belongsToMany(Product::class, 'flash_sale_products')
            ->using(FlashSaleProduct::class)
            ->withPivot(['id', 'end_date', 'price', 'qty'])
            ->orderBy('position');
    }


    public function scopeWithEligibleProducts($query)
    {
        $query->with(['products' => function ($query) {
            $query->forCard()->wherePivot('end_date', '<>', null);
        }]);
    }


    public function getPriceAttribute($price)
    {
        return Money::inDefaultCurrency($price);
    }


    public function table()
    {
        return new AdminTable($this->query());
    }


    private function buildProductPivots($products)
    {
        return collect($products)->values()->mapWithKeys(function ($attributes, $index) {
            return [$attributes['product_id'] => [
                'end_date' => $attributes['end_date'],
                'price' => $attributes['price'],
                'qty' => $attributes['qty'],
                'position' => $index,
            ]];
        });
    }
}
