<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Support\Facades\Cache;
use Morilog\Jalali\Jalalian;

class ConsignmentItem extends Model
{
    use HasFactory;

    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'id',
        'consignment_id',
        'store_id',
        'inventory_id',
        'product_id',
        'storage_id',

        'title',
        'props',
        'options',
        'affiliate',
        'count',
        'price',
        'discount',
        'shop_share',
        'seller_share',
        'affiliate_share',

        'reason',
        'status',

        'updated_at',

        'safe',
    ];

    protected $casts = [
        'consignment_id' => 'integer',
        'store_id' => 'integer',
        'inventory_id' => 'integer',
        'product_id' => 'integer',
        'storage_id' => 'integer',
        'count' => 'integer',
        'price' => 'integer',
        'discount' => 'integer',
        'shop_share' => 'integer',
        'seller_share' => 'integer',
        'affiliate_share' => 'integer',
    ];

    /**
     * additional data
     */
    protected $appends = [
        'get_props',
        'get_options',
        'get_formatted_price',
        'get_formatted_discount',
        'get_full_count_price',
        'get_full_count_discount',
        'get_full_count_weight',
        'get_full_count_weight_kg',

        'get_shares',

        'jalali_created_at',
        'jalali_updated_at',
    ];

    public function getGetPropsAttribute()
    {
        return unserialize($this->props);
    }

    public function getGetOptionsAttribute()
    {
        $options = $this->options;
        if ($options === null || $options === '') {
            return [];
        }

        $decoded = json_decode($options, true);
        return $decoded === null ? [] : $decoded;
    }

    public function getGetFormattedPriceAttribute()
    {
        return number_format($this->price);
    }

    public function getGetFormattedDiscountAttribute()
    {
        return number_format($this->discount);
    }

    public function getGetFullCountPriceAttribute()
    {
        return $this->price * $this->count;
    }

    public function getGetFullCountDiscountAttribute()
    {
        return $this->discount * $this->count;
    }

    public function getGetFullCountWeightAttribute()
    {
        return $this->inventory->weight * $this->count;
    }

    public function getGetFullCountWeightKgAttribute()
    {
        if ($this->inventory?->weight != null) {
            return ($this->inventory->weight * $this->count) / 1000;
        } else {
            return 0;
        }
    }


    public function getGetSharesAttribute()
    {
        $product = $this->product;

        $fullCountPrice = $this->price * $this->count;
        $productCommission = $product->commission;

        // affiliate
        $affiliateData = null;
        $affiliateUser = User::where('id', $this->affiliate)->first();
        if ($affiliateUser != null) {
            $levelCommission = null;
            switch ($affiliateUser->get_level) {
                case "bronze":
                    $levelCommission = $product->affiliate->bronze_commission;
                    break;
                case "silver":
                    $levelCommission = $product->affiliate->silver_commission;
                    break;
                case "gold":
                    $levelCommission = $product->affiliate->gold_commission;
                    break;
            }

            if ($levelCommission != null) {
                $affiliateShare = round(($fullCountPrice * $levelCommission) / 100);
                $affiliateData = [
                    'user' => [
                        'id' => $affiliateUser->id,
                        'get_name' => $affiliateUser->get_name,
                        'get_level' => $affiliateUser->get_level,
                    ],
                    'commission' => $levelCommission,
                    'share' => $affiliateShare,
                ];

                $fullCountPrice = $fullCountPrice - $affiliateShare;
            }
        }

        // seller and shop
        $shopShare = round(($fullCountPrice * $productCommission) / 100);
        $sellerShare = round($fullCountPrice - $shopShare);

        // final shares
        $finalShopShare = $this->store_id != null ? $shopShare : $fullCountPrice;
        $finalSellerShare = $this->store_id != null ? $sellerShare : 0;
        $finalAffiliateShare = $affiliateData != null ? $affiliateData['share'] : 0;

        /*if ($this->status == 'sent' || $this->status == 'delivered') {
            $finalShopShare = $this->shop_share;
            $finalSellerShare = $this->seller_share;
            $finalAffiliateShare = $this->affiliate_share;
        }*/

        return [
            'shop' => (int)$finalShopShare,

            'seller_information' => $this->store_id != null ? $this->store_id : null,
            'seller' => (int)$finalSellerShare,

            'affiliate_information' => $affiliateData,
            'affiliate' => (int)$finalAffiliateShare,
        ];
    }

    public function getJalaliCreatedAtAttribute()
    {
        $date = [
            Jalalian::forge($this->created_at)->format('%d %B %Y'),
            Jalalian::forge($this->created_at)->format('Y/m/d'),
            Jalalian::forge($this->created_at)->format('H:i - Y/m/d'),
            Jalalian::forge($this->created_at)->ago(),
            Jalalian::forge($this->created_at)->getTimestamp(),
        ];
        return $date;
    }

    public function getJalaliUpdatedAtAttribute()
    {
        $date = [
            Jalalian::forge($this->updated_at)->format('%d %B %Y'),
            Jalalian::forge($this->updated_at)->format('Y/m/d'),
            Jalalian::forge($this->updated_at)->format('H:i - Y/m/d'),
            Jalalian::forge($this->updated_at)->ago(),
            Jalalian::forge($this->updated_at)->getTimestamp(),
        ];
        return $date;
    }

    public function getSafeAttribute()
    {
        return [
            'id' => $this->id,
            'inventory_id' => $this->inventory_id,
            'title' => $this->title,
            'get_props' => $this->get_props,
            'count' => $this->count,
            'price' => $this->price,
            'get_formatted_price' => $this->get_formatted_price,
            'discount' => $this->discount,
            'get_formatted_discount' => $this->get_formatted_discount,
            'get_full_count_price' => $this->get_full_count_price,
            'get_full_count_discount' => $this->get_full_count_discount,
            'reason' => $this->reason,
            'status' => $this->status,
        ];
    }
    /** end append */

    /**
     * remove cache data in update
     */
    protected static function boot()
    {
        parent::boot();

        static::saved(function ($consignmentItem) {
            if ($consignmentItem->store_id != null)
                Cache::forget('store_get_meta_' . $consignmentItem->store_id);
        });

        static::deleted(function ($consignmentItem) {
            if ($consignmentItem->store_id != null)
                Cache::forget('store_get_meta_' . $consignmentItem->store_id);
        });
    }

    /* relationships **************/
    public function consignment(): BelongsTo
    {
        return $this->belongsTo(Consignment::class);
    }

    public function store(): BelongsTo
    {
        return $this->belongsTo(Store::class);
    }

    public function inventory(): BelongsTo
    {
        return $this->belongsTo(Inventory::class);
    }

    public function product(): BelongsTo
    {
        return $this->belongsTo(Product::class);
    }

    public function storage(): BelongsTo
    {
        return $this->belongsTo(Storage::class);
    }
}
