<?php

namespace app\api\controller;

use app\common\model\AdvGroupModel;
use app\common\model\BoothModel;
use app\common\model\FeedbackModel;
use app\common\model\LinksModel;
use app\common\model\MemberAgentModel;
use app\common\model\MemberSignModel;
use app\common\model\NoticeModel;
use InvalidArgumentException;
use stdClass;
use think\Db;
use think\facade\Log;
use think\Response;
use think\response\Json;
use Throwable;

/**
 * 通用接口
 * Class CommonController
 * @package app\api\Controller
 */
class CommonController extends BaseController
{
    /**
     * 批量获取接口数据
     * 两种请求方式
     * 1. methods = a,b,c.d ; arg1 = a ;  arg2 = b ; ...
     *    该方式不能重复调同一个接口，各接口间参数不能有冲突
     * 2. { method1 => { arg1 => a, arg2 => b}, method2 => { call => controller.method, arg1 => a, arg2 => b} }
     *    此方法各接口的参数互相隔离，并可重复调用同一接口
     *    重复调用同一个接口时，使用自定义key，然后增加一个call来指定调用的方法
     * 
     * @return \think\response\Json
     */
    public function batch()
    {
        $methods = $this->request->param('methods');
        $data = [];
        if (!empty($methods)) {
            $methods = explode(',', $methods);
            $params = $this->request->param();
            foreach ($methods as $method) {
                $data[$method] = $this->call_api($method, $params);
            }
        } else {

            foreach ($this->input as $method => $arguments) {
                if ($method == 'token') continue;

                if (!is_array($arguments)) {
                    if (empty($arguments)) $arguments = [];
                    else continue;
                }

                if (isset($arguments['call'])) $calls = $arguments['call'];
                else $calls = $method;

                $data[$method] = $this->call_api($calls, $arguments);
            }
        }
        return $this->response($data);
    }

    private function call_api($calls, $arguments = [])
    {
        $m = explode('.', $calls);
        if (count($m) > 1) {
            if (strtolower($m[0]) == 'common') {
                $controller = $this;
            } else {
                if (strpos($m[0], '/') > 0 || strpos($m[0], '\\') > 0) {
                    $m[0] = str_replace('\\', '/', $m[0]);
                    $layers = explode('/', strtolower($m[0]));
                    $last = count($layers) - 1;
                    $layers[$last] = ucfirst($layers[$last]);
                    $m[0] = implode('\\', $layers);
                } else {
                    $m[0] = ucfirst($m[0]);
                }
                if (in_array($m[0], ['Base', 'Auth', 'Authed', 'Wechat'])) {
                    return null;
                }
                try {
                    $controller = \container()->make('\\app\\api\\controller\\' . $m[0] . 'Controller');
                } catch (\Exception $e) {
                    Log::error($e->getMessage());
                    return null;
                }
            }
            $m = $m[1];
        } else {
            $controller = $this;
            $m = $m[0];
        }

        if (method_exists($controller, $m)) {
            try {
                $args = [];
                $reflect = new \ReflectionMethod($controller, $m);
                foreach ($reflect->getParameters() as $param) {
                    if (isset($arguments[$param->name])) {
                        $args[] = $arguments[$param->name];
                    } elseif ($this->request->has($param->name)) {
                        $args[] = $this->request->param($param->name);
                    } elseif ($param->isDefaultValueAvailable()) {
                        $args[] = $param->getDefaultValue();
                    }
                }

                $response = $reflect->invokeArgs($controller, $args);
                if ($response instanceof Response) {
                    $curData = $response->getData();

                    return $curData['data'];
                } else {
                    return null;
                }
            } catch (\ReflectionException $e) {
                Log::error($e->getMessage());
            } catch (\Exception $e) {
                Log::error($e->getMessage());
            }
        }
        return null;
    }

    public function booth($flags)
    {
        return $this->response(BoothModel::fetchBooth($flags));
    }

    /**
     * 全站搜索
     */
    public function search($keyword, $model = '', $price = '')
    {

        $unionModel = Db::field('id,title,vice_title,cover as image,0 as price,status,0 sale,create_time,update_time,\'article\' as model')
            ->name('article');
        if (empty($model) || $model == 'product') {
            $unionModel->union(function ($query) {
                $query->field('id,title,vice_title,image,min_price as price,status,sale,create_time,update_time,\'product\' as model')
                    ->name('product');
            });
        }
        if (empty($model) || $model == 'goods') {
            $unionModel->union(function ($query) {
                $query->field('id,title,vice_title,image,price,status,sale,create_time,update_time,\'goods\' as model')
                    ->name('goods');
            });
        }

        $table = Db::table(
            $unionModel->buildSql() . ' search_table'
        )
            ->where('status', 1);

        if (!empty($keyword)) {
            $table->whereLike('title|vice_title', "%$keyword%");
        }
        if (!empty($price)) {
            $parts = explode('-', $price);
            if (count($parts) > 1) {
                $table->whereBetween('price', [intval($parts[0]), intval($parts[1])]);
            } else {
                $table->where('price', 'gt', intval($price));
            }
        }
        if (!empty($model)) {
            $table->where('model', $model);
        }

        $lists = $table->order('sale DESC,create_time DESC')->paginate(10);

        return $this->response([
            'lists' => $lists->items(),
            'page' => $lists->currentPage(),
            'total' => $lists->total(),
            'total_page' => $lists->lastPage(),
        ]);
    }

    /**
     * 获取广告图
     * @param $flag
     * @return Response
     */
    public function advs($flag)
    {
        return $this->response(AdvGroupModel::getAdList($flag));
    }

    public function notice($flag = '', $id = 0)
    {
        $model = NoticeModel::where('status', 1);
        if (!empty($flag)) {
            $model->where('page', $flag);
        }
        if ($id > 0) {
            $model->where('id', $id);
        }

        return $this->response($model->order('create_time DESC')->find());
    }
    public function notices($flag = '', $count = 10)
    {
        $model = NoticeModel::where('status', 1);
        if (!empty($flag)) {
            $model->where('page', $flag);
        }

        return $this->response($model->order('create_time DESC')->limit($count)->select());
    }

    public function links($group = '', $islogo = -1, $count = 10)
    {
        $model = LinksModel::where('status', 1);
        if (!empty($group)) {
            $model->where('group', $group);
        }
        if ($islogo > -1) {
            if ($islogo) {
                $model->where('logo', '<>', '');
            } else {
                $model->where('logo', '');
            }
        }

        return $this->response($model->order('sort ASC,create_time DESC')->limit($count)->select());
    }


    public function feedbacks($pagesize = 10)
    {
        $model = Db::view('feedback', '*')
            ->view("member", ["username", "nickname", "avatar"], "Feedback.member_id=member.id", "LEFT")
            ->view("manager", ["realname" => "manager_name"], "Feedback.manager_id=manager.id", "LEFT")
            ->where("Feedback.status", 1)
            ->order("Feedback.create_time DESC");

        $list = $model->paginate($pagesize);

        return $this->response([
            'lists' => $list,
            'total' => $list->total(),
            'page' => $list->currentPage(),
            'total_page' => $list->lastPage(),
        ]);
    }

    /**
     * 反馈提交接口
     * @return void 
     * @throws InvalidArgumentException 
     * @throws Throwable 
     */
    public function do_feedback()
    {
        $this->check_submit_rate();
        $content = $this->request->param('content');
        $realname = $this->request->param('realname');
        $mobile = $this->request->param('mobile');
        $email = $this->request->param('email');
        $type = $this->request->param('type');
        $data = array();
        $data['content'] = htmlspecialchars($content);
        $data['email'] = htmlspecialchars($email);
        $data['realname'] = htmlspecialchars($realname);
        $data['mobile'] = htmlspecialchars($mobile);
        $data['member_id'] = $this->isLogin ? $this->user['id'] : 0;
        $data['type'] = empty($type) ? 1 : intval($type);
        $data['ip'] = $this->request->ip();
        $data['status'] = 0;
        $data['reply_time'] = 0;
        try {
            $feeded = FeedbackModel::create($data);
            if (!$feeded || !$feeded['id']) {
                $this->error('系统错误');
            }
        } catch (\Exception $e) {
            $this->error($e->getMessage());
        }
        $this->success('反馈成功');
    }

    /**
     * 获取网站通用配置
     * @return Json 
     */
    public function siteinfo()
    {
        $settings = getSettings(false, true);
        $data = [];
        foreach ($settings['common'] as $k => $v) {
            if (strpos($k, 'site-') === 0) {
                $data[substr($k, 5)] = $v;
            } else {
                $data[$k] = $v;
            }
        }
        if ($this->request->param('tencent-key') == '1') {
            $data['mapkey_tencent'] = $settings['third']['mapkey_tencent'];
        }
        return $this->response($data);
    }


    /**
     * 获取配置信息，系统不会输出第三方配置（一般包含授权码之类）获取配置信息，系统不会输出第三方配置（一般包含授权码之类）
     * @param mixed $group 
     * @return Json 
     */
    public function config($group)
    {
        $rdata = new \stdClass();
        if (!empty($group) && $group != 'third') {
            $settings = getSettings(false, true);
            if (strpos($group, ',') === false) {
                if ($group == 'wechat') {
                    $rdata = $this->getDefaultWechat();
                } elseif (isset($settings[$group])) {
                    $rdata = $settings[$group];
                }
            } else {
                $groups = explode(',', $group);
                $rdata = [];
                foreach ($groups as $g) {
                    $g = trim(strtolower($g));
                    if ($g == 'wechat') {
                        $rdata[$g] = $this->getDefaultWechat();
                    } elseif ($g != 'third' && isset($settings[$g])) {
                        $rdata[$g] = $settings[$g];
                    } else {
                        $rdata[$g] = new \stdClass();
                    }
                }
            }
        }
        return $this->response($rdata);
    }

    /**
     * 获取默认微信账号，一般为公众号
     * @return array|stdClass 
     */
    private function getDefaultWechat()
    {
        $wechat = Db::name('wechat')->where('is_default', 1)->field('type,account_type,title,logo,qrcode,shareimg,appid,subscribeurl')->find();
        if (!empty($wechat)) {
            return $wechat;
        }
        return new \stdClass();
    }

    /**
     * 获取签到排名
     * @param int $date
     * @return \think\response\Json
     */
    public function signrank($date = 0)
    {
        if (!$date) $time = time();
        else $time = strtotime($date);
        $ranking = MemberSignModel::getInstance()->getSignRank($time);
        return $this->response($ranking);
    }

    /**
     * 获取公用数据
     * 银行列表-banklist
     * 日志类型-log_types
     * 财务字段-money_fields
     * 会员等级-levels
     * 代理等级-agents
     * @param string $keys 可指定一个或多个数据类型
     * @return Json 
     */
    public function data($keys)
    {
        $datas = [];
        $keyarr = explode(',', $keys);
        if (in_array('banklist', $keyarr)) {
            $datas['banklist'] = banklist();
        }
        if (in_array('log_types', $keyarr)) {
            $datas['log_types'] = getLogTypes();
        }
        if (in_array('money_fields', $keyarr)) {
            $datas['money_fields'] = getMoneyFields();
        }
        if (in_array('levels', $keyarr)) {
            $datas['levels'] = getMemberLevels();
        }
        if (in_array('agents', $keyarr)) {
            $datas['agents'] = MemberAgentModel::getCacheData();
        }

        return $this->response($datas);
    }
}
