<?php

namespace App\Services;

use App\Owner;
use App\OwnerPriceDirectLogistic;
use App\OwnerPriceDirectLogisticCar;
use App\Services\common\QueryService;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\DB;
use App\Traits\ServiceAppAop;


class OwnerPriceDirectLogisticService
{
    use ServiceAppAop;
    protected $modelClass=OwnerPriceDirectLogistic::class;
    public function paginate($id = null)
    {
        $query = OwnerPriceDirectLogistic::query()->with("owners");
        if($id)$query->where("id",$id);
        return $query->paginate(50);
    }

    public function create(array $params)
    {
        $params["operation"] = "C";
        return OwnerPriceDirectLogistic::query()->create($params);
    }

    /**
     * 拷贝目标数据
     *
     * @param object|int $model
     * @param array $values
     * @param array|null $owners
     * @param array $items
     * @param bool $isLoadItem
     *
     * @return object|null
     */
    public function copy($model, $values = [], $owners = null, $items = [], $isLoadItem = true)
    {
        if (is_integer($model))$model = OwnerPriceDirectLogistic::query()->find($model);
        if (!$model)return null;
        $values["operation"] = "U";
        $values["target_id"] = $model->id;
        foreach ($model->getFillable() as $column){
            if (!array_key_exists($column,$values))$values[$column] = $model[$column];
        }
        /** @var OwnerPriceDirectLogistic $copyModel */
        $copyModel = OwnerPriceDirectLogistic::query()->create($values);

        if ($owners===null){
            $query = DB::raw("SELECT * FROM owner_price_direct_logistic_owner WHERE owner_price_direct_logistic_id = {$model->id}");
            $owners = array_column(DB::select($query),"owner_id");
        }
        $copyModel->owners()->sync($owners);
        $insert = [];
        if ($isLoadItem){
            $model->loadMissing("details");
            /** @var \stdClass $model */
            foreach ($model->details as $item){
                $columns = ["car_type_id", "base_fee", "additional_fee"];
                if ($items[$item->id] ?? false){
                    foreach ($columns as $column){
                        if (!array_key_exists($column,$items[$item->id]))$items[$item->id][$column] = $item[$column];
                    }
                    $obj = $items[$item->id];
                    unset($items[$item->id]);
                }else{
                    /** @var OwnerPriceDirectLogisticCar $item */
                    $obj = $item->toArray();
                    unset($obj["id"]);
                }
                $obj["owner_price_direct_logistic_id"] = $copyModel->id;
                $insert[] = $obj;
            }
        }else{
            foreach ($items as $item){
                $item["owner_price_direct_logistic_id"] = $copyModel->id;
                $insert[] = $item;
            }
        }
        if ($insert)OwnerPriceDirectLogisticCar::query()->insert($insert);
        return $copyModel;
    }

    /**
     * 审核或恢复目标集
     *
     * @param bool $isAudit
     * @param integer|null|array $ownerId
     * @param integer|null|array $ids
     */
    public function auditOrRecover($isAudit = true, $ownerId = null, $ids = null)
    {
        if (!$ownerId && !$ids)return;
        $result = app(QueryService::class)->priceModelAuditOrRecoverQuery($isAudit,OwnerPriceDirectLogistic::query(),$ownerId,$ids);
        if ($result["delete"])$this->destroy($result["delete"]);
        if ($result["update"])OwnerPriceDirectLogistic::query()->whereIn("id",$result["update"])->update(["operation"=>null,"target_id"=>null]);
    }

    public function destroy($id)
    {
        if (!is_array($id))$id = [$id];
        OwnerPriceDirectLogisticCar::query()->whereIn("owner_price_direct_logistic_id",$id)->delete();

        $query = "IN (";
        for ($i=0;$i<count($id)-1;$i++)$query .= "{$id[$i]},";
        $query .= "{$id[count($id)-1]})";

        $sql = "SELECT * FROM owner_price_direct_logistic_owner WHERE owner_price_direct_logistic_id {$query}";
        $owners = array_column(DB::select(DB::raw($sql)),"owner_id");
        DB::table("owner_price_direct_logistic_owner")->whereIn("owner_price_direct_logistic_id",$id)->delete();
        app("OwnerService")->refreshRelevance($owners,4,true);
        return OwnerPriceDirectLogistic::destroy($id);
    }

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

    public function update(array $params, array $values)
    {
        $query = OwnerPriceDirectLogistic::query();
        foreach ($params as $column=>$param){
            $query->where($column,$param);
        }
        return $query->update($values);
    }

    public function updateDetail(array $params, array $values)
    {
        $query = OwnerPriceDirectLogisticCar::query();
        foreach ($params as $column => $param){
            $query->where($column,$param);
        }
        return $query->update($values);
    }

    public function isExistDetail(array $params)
    {
        $query = OwnerPriceDirectLogisticCar::query();
        foreach ($params as $column => $param){
            $query->where($column,$param);
        }
        return $query->count();
    }

    public function createDetail(array $params)
    {
        return OwnerPriceDirectLogisticCar::query()->create($params);
    }

    public function destroyDetail($id)
    {
        return OwnerPriceDirectLogisticCar::destroy($id);
    }

    public function getExistOwnerName($owner_id, $id) :array
    {
        if (!is_array($owner_id))$owner_id = [$owner_id];
        $owners = Owner::query()->withCount(["ownerPriceDirectLogistics"=>function($query)use($id){
            if ($id)$query->where("id","!=",$id);
        }])->whereIn("id",$owner_id)->get();
        $arr = [];
        foreach ($owners as $owner){
            if ($owner->owner_price_direct_logistics_count > 0)$arr[] = $owner->name;
        }
        return $arr;
    }


    /**
     *
     * @param double $amount
     * @param integer $owner_id
     * @param integer $car_id
     * @return array
     */
    public function matching($amount, $owner_id, $car_id)
    {
        $model = OwnerPriceDirectLogistic::query()->with(["details"=>function($query)use($car_id){
            /** @var Builder $query */
            $query->where("car_type_id",$car_id);
        }])->whereHas("owners",function ($query)use($owner_id){
            /** @var Builder $query */
            $query->where("id",$owner_id);
        })->where(function(Builder $query){
            $query->whereNull("operation")->orWhere("operation","");
        })->first();
        if (!$model || !$model->details)return array(null,null);
        if ($amount < $model->base_km)$amount = $model->base_km;
        $initialMoney = $model->details[0]->base_fee;
        $amount -= $model->base_km;
        $money = ($amount*$model->details[0]->additional_fee)+$initialMoney;
        if ($model->tax_rate_id && $model->taxRate){
            $taxFee = $money*($model->taxRate->value/100);
        }else{
            /** @var Owner|\stdClass $owner */
            $owner = Owner::query()->with("taxRate")
                ->whereHas("taxRate")->find($owner_id);
            if ($owner)$taxFee = $money*($owner->taxRate->value/100);
            else $taxFee = null;
        }
        return array($money,$taxFee);
    }
}
