<?php

namespace App\Services;

use App\OracleBasCustomer;
use App\Owner;
use App\User;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Auth;

Class OwnerService
{
    /** @var CacheService $cacheService */
    private $cacheService;
    function __construct(){
        $this->cacheService=app('CacheService');
    }
    /*
     * array | string $column
     * 默认一些select字段,可传递string 或 array来指定select字段
     */
    public function getSelection(array $column = ['id', 'name'])
    {
        $ownerIds=app('UserService')->getPermittingOwnerIds(Auth::user());
        return $this->cacheService->getOrExecute('OwnersAll_IdName'.md5(json_encode($column).json_encode($ownerIds)),function()use($column,$ownerIds){
            if(empty($ownerIds))return new Collection();
            return Owner::query()->select($column)->whereIn('id', $ownerIds)->get();
        },config('cache.expirations.owners'));
    }
    public function getSelectionId($column = ['id'])
    {
        return $this->cacheService->getOrExecute('OwnersAll_Id',function()use($column){
            return Owner::filterAuthorities()->select($column)->get();
        },config('cache.expirations.owners'));
    }
    /**
     *同步WMS全部货主至WAS
     */
    public function syncOwnersData()
    {
        $basCustomers = OracleBasCustomer::query()
            ->select('CUSTOMERID', 'DESCR_C')
            ->where('DESCR_C', 'not like', '%换ERP%')
            ->where('DESCR_C', 'not like', '%退仓%')
            ->where('CUSTOMER_TYPE', 'OW')
            ->get();
        $ownerCount = Owner::query()->count();
        if (count($basCustomers) == $ownerCount) return null;
        foreach ($basCustomers as $basCustomer) {
            $owner = Owner::query()->where('code', $basCustomer['customerid'])->first();
            if (!isset($owner)){
                Owner::query()->create([
                    'code' => $basCustomer['customerid'],
                    'name' => $basCustomer['descr_c'],
                    'created_at' => Carbon::now()->format('Y-m-d H:i:s'),
                ]);
            }
            if ($owner['name']!=$basCustomer['descr_c']){
                $owner->update([
                    'code' => $basCustomer['customerid'],
                    'name' => $basCustomer['descr_c'],
                ]);
            }
        }
        $owners = Owner::query()->select('id', 'name')->get();
        return $owners;
    }

    public function first(array $params, array $rules =[]){
        return $this->cacheService->getOrExecute('OwnersFirst'.md5(json_encode($params),json_encode($rules)),function()use($params,$rules){
            $owner = Owner::query();
            foreach ($params as $column => $value){
                if (!isset($rules[$column]))$owner->where($column, $value);
                else{
                    switch ($rules[$column]){
                        case "or":
                            $owner->orWhere($column, $value);
                            break;
                    }
                }
            }
            return $owner->first();
        },config('cache.expirations.rarelyChange'));
    }

    public function find($id)
    {
        return Owner::query()->find($id);
    }

    public function update(Owner $owner, array $values, array $related = [])
    {
        if ($related["ownerStoragePriceModels"] ?? false)$owner->ownerStoragePriceModels()->sync($related["ownerStoragePriceModels"]);
        return $owner->update($values);
    }

    public function create(array $params, array $related = []){
        /** @var Owner $owner */
        $owner = Owner::query()->create($params);
        if ($related["ownerStoragePriceModels"] ?? false)$owner->ownerStoragePriceModels()->syncWithoutDetaching($related["ownerStoragePriceModels"]);
        return $owner;
    }

    public function firstOrCreate(array $params, array $values = null){
        if (!$values) return Owner::query()->firstOrCreate($params);
        return Owner::query()->firstOrCreate($params,$values);
    }


    public function 获取订单跟踪的货主(){
        return Owner::query()->with('orderTrackingOwner')->whereHas('orderTrackingOwner',function($query){
            $query->where('status','启用');
        })->get();
    }

    public function getByWmsOrders($orderHeaders){
        $customerIds = array_unique(data_get($orderHeaders,'*.customerid'));
        $customerIds = array_diff($customerIds,[null,'','*']);
        $owners = Owner::query()->whereIn('code',data_get($orderHeaders,'*.customerid'))->get();

        if($owners->count() < count($customerIds)){
            $customerIds = array_diff($customerIds,data_get($owners,'*.code'));
            $owner_list = $this->createByWmsCustomerIds($customerIds);
            $owners=$owners->concat($owner_list);
        }
        return $owners;
    }

    public function createByWmsCustomerIds($codes){
        if(!$codes) {return [];}
        $basCustomer = OracleBasCustomer::query()
            ->where('Customer_Type','OW')
            ->whereIn('CustomerID', $codes)
            ->get();

        $insert_params = [];
        $created_at = Carbon::now()->format('Y-m-d H:i:s');
        foreach ($basCustomer as $item) {
            $insert_params[] = [
                'code' => $item->customerid,
                'name' => $item->descr_c,
                'created_at' => $created_at,
            ];
        }

        try {
            if (count($insert_params) > 0) {
                $this->insert($insert_params);
                app('LogService')->log(__METHOD__, __FUNCTION__, '批量创建 owner ' . count($insert_params) . json_encode($insert_params) );
            }
        } catch (\Exception $e) {
            app('LogService')->log(__METHOD__, __FUNCTION__, '批量创建 owner error' . json_encode($insert_params) . '||' . $e->getMessage() . '||' . $e->getTraceAsString());
        } finally {
            return Owner::query()->whereIn('code', $codes)->get();
        }
    }

    public function insert($fillables){
        return Owner::query()->insert($fillables);
    }

    public function getAuthorizedOwners(){
        $user = Auth::user();
        return Owner::query()->whereIn('id',app('UserService')->getPermittingOwnerIds($user)??[])->get();
    }

    public function get(array $params, array $withs = null, bool $authority = true, bool $notShowSoftDelete = false,$user)
    {
        /** @var User $user */
        if ($user==null) {
            $user = Auth::user();
        }
        $query = Owner::query();
        if ($withs)$query->with($withs);
        if ($authority){
            $ids = $user->getPermittingOwnerIdsAttribute();
            if ($ids) $query->whereIn("id",$ids);
            else return null;
        }
        if ($notShowSoftDelete) $query->whereNull('deleted_at');
        $query = $this->query($query,$params);
        return $query->get();
    }

    public function paginate(array $params, array $withs = null, bool $authority = true, bool $notShowSoftDelete = false)
    {
        /** @var User $user */
        $user = Auth::user();
        $query = Owner::query();
        if ($withs)$query->with($withs);
        if ($authority){
            $ids = $user->getPermittingOwnerIdsAttribute();
            if ($ids) $query->whereIn("id",$ids);
            else return null;
        }
        if ($notShowSoftDelete) $query->whereNull('deleted_at');
        $query = $this->query($query,$params);
        return $query->paginate($params["paginate"] ?? 50);
    }

    private function query(Builder $builder, array $params)
    {
        foreach ($params as $column => $param){
            if ($param === true){
                $builder->whereNotNull($column);
                continue;
            }
            if ($param === false){
                $builder->whereNull($column);
                continue;
            }
            $builder->where($column,$params);
        }
        return $builder;
    }

}
