<?php

namespace Modules\User\Models;

use App\Traits\Macroable;
use App\Traits\OrderByIdDesc;
use Encore\Admin\Traits\DefaultDatetimeFormat;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Foundation\Auth\User as Authenticate;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Facades\Config;
use Laravel\Sanctum\HasApiTokens;
use Modules\Mall\Traits\HasAddresses;
use Modules\Mall\Traits\HasOrders;
use Modules\Task\Traits\HasTasks;
use Modules\User\Models\Traits\HasLog;
use Modules\User\Models\Traits\HasStock;
use Modules\User\Models\Traits\HasVipOrders;
use Modules\User\Models\Traits\HasWechat;
use Modules\User\Models\Order as UserOrder;
use Overtrue\LaravelFavorite\Traits\Favoriter;
use Overtrue\LaravelSubscribe\Traits\Subscriber;
use SimpleSoftwareIO\QrCode\Facades\QrCode;
use Vinkla\Hashids\Facades\Hashids;

class User extends Authenticate
{

    use HasApiTokens,
        DefaultDatetimeFormat,
        Macroable,
        HasStock,
        HasLog,
        HasOrders,
        HasVipOrders,
        HasWechat,
        HasAddresses,
        Notifiable,
        HasTasks,
        Subscriber,
        Favoriter,
        OrderByIdDesc,
        Traits\JoinIdentity,
        Traits\HasRelations,
        Traits\HasSign;

    const STATUS_INIT   = 1;
    const STATUS_REFUND = 2;

    const  STATUS = [
        self::STATUS_INIT   => '正常',
        self::STATUS_REFUND => '退费',
    ];

    /**
     * 禁止写入的字段
     *
     * @var array
     */
    protected $guarded = [];

    /**
     * 模型隐藏字段
     *
     * @var array
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];

    protected static function boot()
    {
        parent::boot();

        self::created(function ($user) {
            $user->info()->create([
                'nickname' => '用户'.substr($user->username, -4),
            ]);
            $user->sign()->create([
                'continue_days' => 0,
                'counts'        => 0,
                'last_sign_at'  => null,
            ]);
            $user->account()->create();

            $defaultIdentity = Identity::where('default', 1)->first();
            if ($defaultIdentity) {
                $user->joinIdentity($defaultIdentity->id, IdentityLog::CHANNEL_REG);
            }
        });
    }

    /**
     * Notes   : 用户资料
     *
     * @Date   : 2021/3/11 5:41 下午
     * @Author : < Jason.C >
     * @return HasOne
     */
    public function info(): HasOne
    {
        return $this->hasOne(UserInfo::class);
    }


    /**
     * Notes   : 用户账户
     *
     * @Date   : 2021/4/27 11:20 上午
     * @Author : < Jason.C >
     * @return HasOne
     */
    public function account(): HasOne
    {
        return $this->hasOne(Account::class);
    }

    /**
     * Notes   : 当用户有密码的时候才加密
     *
     * @Date   : 2021/3/11 1:43 下午
     * @Author : < Jason.C >
     * @param $password
     */
    public function setPasswordAttribute($password)
    {
        if ($password) {
            $this->attributes['password'] = bcrypt($password);
        }
    }

    /**
     * 第一身份
     *
     * @return mixed|null
     */
    public function identityFirst()
    {
        return $this->identities()->first();
    }

    /**
     * Notes   : 用户身份
     *
     * @Date   : 2021/5/6 12:00 下午
     * @Author : < Jason.C >
     */
    public function identities(): BelongsToMany
    {
        return $this->belongsToMany(Identity::class, 'user_identity')
            ->withTimestamps()
            ->withPivot(['started_at', 'ended_at', 'serial']);
    }

    /**
     * 用户中间表关联
     *
     * @return HasMany
     */
    public function identityMiddle(): HasMany
    {
        return $this->hasMany(IdentityMiddle::class);
    }

    /**
     * 身份变动表关联
     *
     * @return HasMany
     */
    public function identity_logs(): HasMany
    {
        return $this->hasMany(IdentityLog::class);
    }

    /**
     * Notes: 升级缴费订单
     *
     * @Author: 玄尘
     * @Date: 2022/9/7 13:57
     */
    public function vipOrders(): HasMany
    {
        return $this->hasMany(UserOrder::class);
    }

    /**
     * 用户个人认证
     *
     * @return HasOne
     */
    public function certification(): HasOne
    {
        return $this->hasOne(UserCertification::class);
    }

    /**
     * Notes: 获取状态信息
     *
     * @Author: 玄尘
     * @Date: 2022/8/3 16:30
     */
    public function getStateData(): array
    {
        $identity = $this->identities->first();

        return [
            'isSubscribe' => $this->isOfficialSubscribe(),//关注
            'isVip'       => $identity ? $identity->order : 0,//是否开会
        ];
    }

    /**
     * Notes: 获取当前状态
     *
     * @Author: 玄尘
     * @Date: 2022/8/3 16:38
     */
    public function getNowStatus(): array
    {
        $status = $this->getStateData();

        if (! $status['isSubscribe']) {
            return [
                'value' => 'isSubscribe',
                'text'  => '关注'
            ];
        }

        if (! $status['isCase']) {
            return [
                'value' => 'isCase',
                'text'  => '健康档案'
            ];
        }

        if (! $status['isVip']) {
            return [
                'value' => 'isVip',
                'text'  => '开通会员'
            ];
        }

        return [
            'value' => 'upCase',
            'text'  => '上传档案'
        ];

    }


    /**
     * Notes: 开通季卡的次数
     *
     * @Author: 玄尘
     * @Date: 2022/8/21 10:38
     */
    public function getOpenJkCount(): int
    {
        $jkIdentity = Identity::query()->Jk()->first();
        $num        = 0;
        if ($jkIdentity) {
            $num = UserOrder::query()
                ->byUser($this)
                ->where('identity_id', $jkIdentity->id)
                ->where('state', UserOrder::STATE_SUCCESS)
                ->count();
        }

        return $num;
    }

    /**
     * Notes: description
     *
     * @Author: 玄尘
     * @Date: 2022/9/28 13:08
     */
    public function getCodeAttribute()
    {
        $userIdentity = $this->identityFirst();

        if ($userIdentity && $userIdentity->id > 1) {
            $invite = Hashids::connection('code')->encode($this->id);
        } else {
            $invite = '';
        }

        $url = Config::get('user.invite_code.url').'?invite='.$invite;
        return 'data:image/png;base64,'.base64_encode(QrCode::format('png')
                ->size(100)
                ->margin(3)
                ->generate($url));
    }

}
