<?php

namespace Modules\Mall\Models;

use App\Models\Model;
use App\Traits\HasClicks;
use App\Traits\HasCovers;
use App\Traits\HasStatus;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\DB;
use Modules\Mall\Models\Traits\BelongsToShop;
use Overtrue\LaravelVersionable\Versionable;

class Goods extends Model
{

    use BelongsToShop,
        HasStatus,
        HasClicks,
        HasCovers,
        Versionable,
        SoftDeletes;

    /**
     * 规格，支持单规格和多规格
     */
    const TYPE_SINGLE   = 1;
    const TYPE_MULTIPLE = 2;
    const TYPE_MAP      = [
        self::TYPE_SINGLE   => '单规格',
        self::TYPE_MULTIPLE => '多规格',
    ];
    /**
     * 状态
     */
    const STATUS_AUDIT  = 0;
    const STATUS_UP     = 1;
    const STATUS_REJECT = 2;
    const STATUS_DOWN   = 3;
    const STATUS_MAP    = [
        self::STATUS_AUDIT  => '审核中',
        self::STATUS_UP     => '上架',
        self::STATUS_REJECT => '驳回',
        self::STATUS_DOWN   => '下架',
    ];
    /**
     * 库存的扣减方式
     */
    const DEDUCT_STOCK_ORDER = 1;
    const DEDUCT_STOCK_PAID  = 2;
    const DEDUCT_STOCK_MAP   = [
        self::DEDUCT_STOCK_ORDER => '下单减库存',
        self::DEDUCT_STOCK_PAID  => '付款减库存',
    ];
    /**
     * 支付方式
     */
    const PAY_TYPE_ONLINE  = 1;
    const PAY_TYPE_OFFLINE = 2;
    const PAY_TYPE_ALL     = 3;
    const PAY_TYPE_MAP     = [
        self::PAY_TYPE_ONLINE  => '在线支付',
        self::PAY_TYPE_OFFLINE => '货到付款',
        self::PAY_TYPE_ALL     => '在线支付/货到付款',
    ];

    /**
     * 商品类型
     */
    const CHANNEL_NORMAL = 1;
    const CHANNEL_SCORE  = 2;
    const CHANNEL_FREE   = 3;

    const Channels = [
        self::CHANNEL_NORMAL => '正常',
        self::CHANNEL_SCORE  => '积分兑换',
        self::CHANNEL_FREE   => '赠送',
    ];

    /**
     * 展示列表，从数据库查询的字段
     */
    const LIST_SELECT_FIELDS = [
        'id',
        'name',
        'description',
        'cover',
        'shop_id',
        'original_price',
        'sales',
        'clicks',
    ];

    protected $table = 'mall_goods';

    protected $casts = [
        'pictures' => 'json',
    ];

    protected $with = [
        'specs',
        'skus',
    ];

    /**
     * 不参与版本记录的字段
     *
     * @var array|string[]
     */
    protected array $dontVersionable = ['clicks', 'updated_at'];

    /**
     * Notes   : 商品分类
     *
     * @Date   : 2021/5/12 9:48 上午
     * @Author : < Jason.C >
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function category(): BelongsTo
    {
        return $this->belongsTo(Category::class);
    }

    /**
     * Notes   : 标签
     *
     * @Date   : 2021/5/12 10:14 上午
     * @Author : < Jason.C >
     * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
     */
    public function tags(): BelongsToMany
    {
        return $this->belongsToMany(Tag::class, 'mall_goods_tag');
    }

    /**
     * Notes   : 所属品牌
     *
     * @Date   : 2021/5/11 11:00 上午
     * @Author : < Jason.C >
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function brand(): BelongsTo
    {
        return $this->belongsTo(Brand::class);
    }

    /**
     * Notes   : 运费模板
     *
     * @Date   : 2021/5/11 11:04 上午
     * @Author : < Jason.C >
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function delivery(): BelongsTo
    {
        return $this->belongsTo(Delivery::class);
    }

    /**
     * Notes   : 商品属性
     *
     * @Date   : 2021/5/12 11:31 上午
     * @Author : < Jason.C >
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function specs(): HasMany
    {
        return $this->hasMany(GoodsSpec::class);
    }

    /**
     * Notes   : 商品SKU
     *
     * @Date   : 2021/5/11 1:47 下午
     * @Author : < Jason.C >
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function skus(): HasMany
    {
        return $this->hasMany(GoodsSku::class);
    }

    /**
     * Notes   : 获取规格的价格区间
     *
     * @Date   : 2021/5/13 11:49 上午
     * @Author : < Jason.C >
     * @return string
     */
    public function getPriceAttribute(): string
    {
        if ($this->type === self::TYPE_SINGLE) {
            return $this->price_min;
        } else {
            return $this->price_min.'|'.$this->price_max;
        }
    }

    /**
     * Notes   : 返回最低积分
     *
     * @Date   : 2021/5/20 11:26 上午
     * @Author : < Jason.C >
     * @return float
     */
    public function getScoreAttribute(): float
    {
        return $this->skus->min('score') ?? 0;
    }

    /**
     * Notes   : 最低价格
     *
     * @Date   : 2021/5/13 11:50 上午
     * @Author : < Jason.C >
     * @return float
     */
    public function getPriceMinAttribute(): float
    {
        return $this->skus->min('price') ?? 0;
    }

    /**
     * Notes   : 最高价格
     *
     * @Date   : 2021/5/13 11:51 上午
     * @Author : < Jason.C >
     * @return float
     */
    public function getPriceMaxAttribute(): float
    {
        return $this->skus->max('price') ?? 0;
    }

    /**
     * Notes   : 按价格排序
     *
     * @Date   : 2021/5/17 14:18
     * @Author : Mr.wang
     * @param  Builder  $query
     * @param  string  $direction
     * @return Builder
     */
    public function scopeOrderByPrice(Builder $query, string $direction = 'asc'): Builder
    {
        if ($direction) {
            $price = DB::raw('MIN(price) as min_price');
        } else {
            $price = DB::raw('MAX(price) as min_price');
        }

        $minPrice = DB::table('mall_goods_skus')
            ->select('goods_id', $price)
            ->whereNull('deleted_at')
            ->groupBy('goods_id');

        return $query->joinSub($minPrice, 'min_price', function ($join) {
            $join->on('mall_goods.id', '=', 'min_price.goods_id');
        })->orderBy('min_price', $direction);
    }

}
