<?php


namespace App\Models;


use Illuminate\Support\Facades\DB;
use Jenssegers\Mongodb\Eloquent\Model;

class BaseMongoModel extends Model
{
    protected $connection = 'mongodb';
    protected $db = null;

    public function __construct()
    {
        parent::__construct();
        $this->db =   DB::connection('mongodb');
    }

    /**
     * @function 公用查询model
     * @param array $param
     * @param array $fields 返回字段名数组['_id', 'res_count'],一维数组
     * @param array $sort
     * @param string $pageNo
     * @param string $perPage
     * @param array $group
     * @param array $lookup
     * @param array $unwind
     * @param array $match
     * @return array totalCount表示返回如果有分页总条数，data返回查询后的数据
     */
    public function getListByCondition(
        $param = [],
        $fields = [],
        $sort = [],
        $pageNo = '',
        $perPage = '',
        $group = [],
        $lookup = [],
        $unwind = [],
        $match = []
    ) {
        $result = [];
        $condition = [];
        //过滤条件，过滤字段
        if ($param) {
            $condition [] = $param;
        }

        //连表查询
        if ($lookup && is_array($lookup)) {
            $condition[] = ['$lookup' => $lookup];
        }

        if ($unwind && is_array($unwind)) {
            $condition[] = ['$unwind' => $unwind];
        }

        if ($match && is_array($match)) {
            $condition[] = ['$match' => $match];
        }

        //是否有分组过滤
        if ($group && is_array($group)) {
            $condition[] = ['$group' => $group];
        }

        //是否有排序
        if ($sort && is_array($sort)) {
            $condition[] = ['$sort' => $sort];
        }

        //是否有分页
        if ($pageNo) {
            //有分页需要获取总条数
            $totalCount = $this->statCountByCondition($condition);
            $result['totalCount'] = $totalCount;
            $perPage = $this->getPerPage($perPage);
            $pageNo = $this->getPage($pageNo);
            $condition[] = ['$skip' => (int)(($pageNo - 1) * $perPage)];
            $condition[] = ['$limit' => $perPage];
        }

        //字段过滤
        if ($fields && is_array($fields)) {
            $project = [];
            foreach ($fields as $value) {
                $project[$value] = 1;
            }
            $condition[] = ['$project' => $project];
        }

        $respData = $this->db->selectCollection($this->collection)->aggregate($condition)->toArray();
        $respData = $respData ? $respData : [];
        $result['data'] = $respData;
        return $result;
    }

    /**
     * @function 根据条件来获取相应的数据
     * @param array $param
     * @param array $fields
     * @param bool $is_one
     * @param string $sortField
     * @param string $sort
     * @return bool|mixed
     */
    public function getInfoByCondition($param = [], $fields = [], $is_one = false, $sortField = '', $sort = 'desc')
    {
        if (empty($param)) {
            return false;
        }
        if ($is_one) {
            $respData = $this->whereRaw($param)->first($fields);
        } else {
            if ($sortField) {
                $respData = $this->whereRaw($param)->orderBy($sortField, $sort)->get($fields);
            } else {
                $respData = $this->whereRaw($param)->get($fields);
            }
        }
        return $respData ? json_decode($respData, true) : [];
    }

    /**
     * @function 根据条件统计条数
     * @param array $param
     * @param array $field
     * @return int
     */
    public function statCountByCondition($param = [], $field = ['$count' => 'id'])
    {
        $condition = $param;
        $condition[] = $field;
        $result = $this->db->selectCollection($this->collection)->aggregate($condition)->toArray();
        $resCount = 0;

        if ($result) {
            foreach ($result as $value) {
                foreach ($value as $item) {
                    $resCount = $item;
                }
            }
        }

        return $resCount;
    }

    /**
     * @function 更新数据updateData
     * @param array $condition
     * @param array $updateData
     * @param bool $isOne
     * @return bool
     */
    public function updateData($condition = [], $updateData = [], $isOne = true)
    {
        if (!$updateData || !is_array($updateData)) {
            return false;
        }
        if ($isOne) {
            return $this->db->selectCollection($this->collection)->updateOne($condition, $updateData);
        } else {
            return $this->db->selectCollection($this->collection)->updateMany($condition, $updateData);
        }
    }


    /**
     * @function 插入数据
     * @param array $insertData 要插入的数据
     * @param bool $isOne 是否插入单条数据
     * @param bool $getId 是否返回插入ID（单条有效）
     * @return bool 返回数据
     */
    public function insertData($insertData = [], $isOne = true, $getId = false)
    {
        if (!$insertData || !is_array($insertData)) {
            return false;
        }
        //插入一条数据
        if ($isOne) {
            $result = $this->db->selectCollection($this->collection)->insertOne($insertData);
            if ($getId) {
                $result = $result->getInsertedId();
            }
        } else {
            $result = $this->db->selectCollection($this->collection)->insertMany($insertData);
        }
        return $result;
    }

    /**
     * 获取分页行数
     * @param $data
     * @return int
     */
    protected function getPageSize($data)
    {
        return $data['page_size'] ?? config('app.app_rows');
    }

    /**
     * 获取页码
     * @param $data
     * @return int
     */
    protected function getPageNo($data)
    {
        return $data['page'] ?? config('app.app_page_no');
    }

    /**
     * 获取查询偏移量
     * @param $data
     * @return int
     */
    protected function getSkip($page,$pageSize)
    {
        return ($page - 1) * $pageSize;;
    }

    /**
     * 获取分页参数
     * */
    protected function getPaginatorParams($params){

        $pageSize = $this->getPageSize($params);
        $page =  $this->getPageNo($params);
        $skip =  $this->getSkip($page,$pageSize);
        return array($pageSize, $page,$skip);
    }

    /**
     * @function 获取页数
     * @author lin
     * @param $pageNo
     * @return int
     */
    public function getPage($pageNo)
    {
        $pageNo = intval($pageNo);
        return $pageNo ? $pageNo : 1;
    }

    /**
     * @function 获取分页
     *
     * @author lin
     * @param string $perPage
     * @return int|mixed
     */
    public function getPerPage($perPage = '')
    {
        $perPage = intval($perPage);
        return $perPage ? $perPage : config('app.app_rows');
    }

    /**
     * 构造返回页面数据
     * @param $data //数据
     * @param $formNb //开始数量
     * @param $page //页数
     * @param $perPageSize //每页数量
     * @param $total //总数量
     * @return mixed
     */
    public function buildPaginator($data = [], $formNb = 0, $page = 1, $perPageSize = 10, $total = 0)
    {
        $lastPage = ceil($total / $perPageSize);
        $toNb = $page * $perPageSize;
        if (empty($formNb)) {
            $formNb = $toNb - $perPageSize;
        }
        if ($toNb > $total) {
            $toNb = $total;
        }
        $resultDdata = array(
            'current_page' => $page,
            'data' => $data,
            'from' => $formNb,
            'last_page' => $lastPage,
            'per_page' => $perPageSize,
            'to' => $toNb,
            'total' => $total,
        );
        return $resultDdata;
    }

}
