<?php namespace Phpcmf\Model\Httpapi;

// api
class Http extends \Phpcmf\Model
{

    /**
     * 验证码http请求授权
     */
    public function check_auth() {

        $v = (string)\Phpcmf\Service::L('input')->request('v');
        if ($v == '2') {
            // v2版本的验证方式
            $appid = (int)\Phpcmf\Service::L('input')->request('appid');
            $signature = (string)\Phpcmf\Service::L('input')->request('signature');
            $timestamp = (string)\Phpcmf\Service::L('input')->request('timestamp');

            // 格式验证
            if (!$appid) {
                \Phpcmf\Service::C()->_json(0, 'appid值为空');
            } elseif (!$signature) {
                \Phpcmf\Service::C()->_json(0, 'signature值为空');
            } elseif (!$timestamp) {
                \Phpcmf\Service::C()->_json(0, 'timestamp值为空');
            } elseif (!is_numeric($timestamp)) {
                \Phpcmf\Service::C()->_json(0, 'timestamp值不规范');
            } elseif (SYS_TIME - $timestamp > 600) {
                \Phpcmf\Service::C()->_json(0, 'timestamp值不匹配');
            }

            define('IS_API_HTTP_CODE', md5($appid.$signature));

            $appsecret = \Phpcmf\Service::C()->get_cache('api_auth', $appid);
            $string = md5($appid.$appsecret.$timestamp);
            if ($string != $signature) {
                \Phpcmf\Service::C()->_json(0, 'signature值不匹配');
            }

        } else {
            // 老版本的验证方式
            $appid = (int)\Phpcmf\Service::L('input')->request('appid');
            $appsecret = (string)\Phpcmf\Service::L('input')->request('appsecret');

            define('IS_API_HTTP_CODE', md5($appid.$appsecret));

            // 格式验证
            if (!$appid || !$appsecret) {
                \Phpcmf\Service::C()->_json(0, 'AppID和AppSecret值为空');
            }
            $cache = \Phpcmf\Service::C()->get_cache('api_auth', $appid);
            if (!$cache) {
                \Phpcmf\Service::C()->_json(0, 'AppID不存在');
            } elseif (strtoupper($cache) != strtoupper($appsecret)) {
                \Phpcmf\Service::C()->_json(0, 'AppID和AppSecret值不匹配');
            }
        }

        // 验证账号授权并登录
        $auth = \Phpcmf\Service::L('input')->request('api_auth_code');  // 获取当前的登录记录
        if ($auth) {
            // 通过接口的post认证
            $uid = (int)\Phpcmf\Service::L('input')->get('api_auth_uid');
            if ($uid) {
                $member = \Phpcmf\Service::M('member')->get_member($uid);
                // 表示登录成功
                if (!$member) {
                    // 不存在的账号
                    \Phpcmf\Service::C()->_json(0, dr_lang('api_auth_uid 账号不存在'));
                } elseif (md5($member['password'].$member['salt']) != $auth) {
                    \Phpcmf\Service::C()->_json(0, dr_lang('登录超时，请重新登录'));
                }

                \Phpcmf\Service::C()->uid = $uid;
                \Phpcmf\Service::C()->member = $member;
            } else {
                \Phpcmf\Service::C()->uid = 0;
                \Phpcmf\Service::C()->member = [];
            }
        } else {
            \Phpcmf\Service::C()->uid = 0;
            \Phpcmf\Service::C()->member = [];
        }
    }


    /**
     * 解析接口数据
     */
    public function get_api_data($data) {

        if (!$data) {
            return dr_return_data(0, dr_lang('接口数据不存在'));
        }

        switch ($data['type']) {

            case 0:
                return dr_return_data(1, 'ok', $data['data']);
                break;

            case 1:
                $rt = dr_string2array($data['data']);
                if (!$rt) {
                    return dr_return_data(0, dr_lang('接口数据内容格式必须是数组'));
                }

                return dr_return_data(1, 'ok', $rt);
                break;

            case 2:
                $return = null;
                if (is_file(dr_get_app_dir('httpapi').'Api/'.$data['file'])) {
                    require dr_get_app_dir('httpapi').'Api/'.$data['file'];
                } else {
                    return dr_return_data(0, dr_lang('接口程序文件【Api/'.$data['file'].'】不存在'));
                }
                return dr_return_data(1, 'ok', $return);
                break;

            case 3:
                $return = null;
                $param = trim(trim($data['list'], '{'), '}');
                $rt = \Phpcmf\Service::V()->list_tag($param);
                if (!$rt['return']) {
                    return dr_return_data(0, $rt['debug']);
                }

                $call = $data['call'];
                if ($call) {
                    // 回调函数
                    if (method_exists(\Phpcmf\Service::L('http'), $call)) {
                        $rt['return'] = \Phpcmf\Service::L('http')->$call($rt['return']);
                    } else {
                        $this->_json(0, '回调方法【'.$data['call'].'】未定义');
                    }
                }
                return dr_return_data(1, 'ok', $rt['return']);
                break;

            case 4:
                $return = null;
                if (!$data['sql']) {
                    return dr_return_data(0, 'SQL内容不存在');
                }

                $return = \Phpcmf\Service::M()->db->query($data['sql'])->getResultArray();

                $call = $data['call'];
                if ($call) {
                    // 回调函数
                    if (method_exists(\Phpcmf\Service::L('http'), $call)) {
                        $rt['return'] = \Phpcmf\Service::L('http')->$call($return);
                    } else {
                        $this->_json(0, '回调方法【'.$data['call'].'】未定义');
                    }
                }
                return dr_return_data(1, 'ok', $return);
                break;

            case 5:
                $api = [];
                $return = null;
                $param = '{php $api = [];}'.$data['tpl'];
                $param = preg_replace('/\{api::([\w]+)\=(.+)\}/iU', '{php \$api[\$key][\'$1\']=$2;}', $param);
                $file = \Phpcmf\Service::V()->code2php($param);
                require $file;
                return dr_return_data(1, 'ok', $api);
                break;
        }

        return dr_return_data(0, dr_lang('未知接口类型'));
    }

    // 接口输出
    public function json($call, $code, $msg, $data) {

        switch ($call) {

            case 'module_list':
                // 模块内容列表页面
                if ($code > 0) {
                    $config = \Phpcmf\Service::C()->get_cache('api_config', 'module_list', \Phpcmf\Service::C()->module['dirname']);
                    if (!$config) {
                        echo dr_array2string(dr_return_data(0, '模块内容接口未配置'));exit;
                    } elseif (!$config['field']) {
                        echo dr_array2string(dr_return_data(0, '模块内容接口未配置输出字段'));exit;
                    }
                    $rt = [];
                    foreach ($data['list'] as $i => $r) {
                        $rt[$i] = [];
                        foreach ($config['field'] as $n => $t) {
                            if ($t['use']) {
                                $value = $r[$n];
                                if ($n == 'catname') {
                                    $value = dr_cat_value($r['catid'], 'name');
                                }
                                if ($t['func']) {
                                    $arr = explode('|', $t['func']);
                                    foreach ($arr as $a) {
                                        if (function_exists($a)) {
                                            $value = call_user_func_array($a, [$value]);
                                        }
                                    }
                                }
                                $rt[$i][$n] = $value;
                            }
                        }
                    }

                    if ($config['call']) {
                        $call2 = $config['call'];
                        // 回调函数
                        if (method_exists(\Phpcmf\Service::L('http'), $call2)) {
                            $rt = \Phpcmf\Service::L('http')->$call2($rt);
                        } else {
                            $this->_json(0, '回调方法【'.$call2.'】未定义');
                        }
                    }

                    return $rt;
                }

                break;

            case 'module_show':
                // 模块内容详情页面
                if ($code > 0) {
                    $config = \Phpcmf\Service::C()->get_cache('api_config', 'module_show', \Phpcmf\Service::C()->module['dirname']);
                    if (!$config) {
                        echo dr_array2string(dr_return_data(0, '模块内容接口未配置'));exit;
                    } elseif (!$config['field']) {
                        echo dr_array2string(dr_return_data(0, '模块内容接口未配置输出字段'));exit;
                    }
                    $rt = [];
                    foreach ($config['field'] as $n => $t) {
                        if ($t['use']) {
                            $value = $data[$n];
                            if ($n == 'catname') {
                                $value = $data['cat']['name'];
                            }
                            if ($t['func']) {
                                $arr = explode('|', $t['func']);
                                foreach ($arr as $a) {
                                    if (function_exists($a)) {
                                        $value = call_user_func_array($a, [$value]);
                                    }
                                }
                            }
                            $rt[$n] = $value;
                        }
                    }

                    if ($config['call']) {
                        $call2 = $config['call'];
                        // 回调函数
                        if (method_exists(\Phpcmf\Service::L('http'), $call2)) {
                            $rt = \Phpcmf\Service::L('http')->$call2($rt);
                        } else {
                            $this->_json(0, '回调方法【'.$call2.'】未定义');
                        }
                    }

                    return $rt;
                }

                break;

            default:
                // 其他回调
                if (!method_exists(\Phpcmf\Service::L('http'), $call)) {
                    echo dr_array2string(dr_return_data(0, '回调方法(' . $call . ')未定义'));exit;
                }
                $data = \Phpcmf\Service::L('http')->$call($data);
                break;
        }

        return $data;
    }

    // 缓存
    public function cache() {

        $table = $this->dbprefix('api_config');
        if (!\Phpcmf\Service::M()->db->tableExists($table)) {
            \Phpcmf\Service::M()->query(dr_format_create_sql('CREATE TABLE IF NOT EXISTS `'.$table.'` (
  `id` int(10) NOT NULL AUTO_INCREMENT COMMENT \'Id\',
  `name` varchar(50) NOT NULL,
  `value` mediumtext NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT=\'api属性配置表\';'));
        }

        // api 授权码
        $data = $this->table('api_auth')->where('disabled', 0)->getAll();
        $cache = $config = [];
        if ($data) {
            foreach ($data as $t) {
                $cache[$t['id']] = $t['secret'];
                $val = dr_string2array($t['setting']);
                $val['table'] = explode(',', $val['table']);
                $config[$t['id']] = $val;
            }
        }

        \Phpcmf\Service::L('cache')->set_file('api_auth', $cache);
        \Phpcmf\Service::L('cache')->set_file('api_db_auth', $config);

        // api 返回数据
        $data = $this->table('api_http')->where('disabled', 0)->getAll();
        $cache = [];
        if ($data) {
            foreach ($data as $t) {
                $cache[$t['id']] = dr_string2array($t['content']);
            }
        }

        \Phpcmf\Service::L('cache')->set_file('api_http', $cache);

        // api 配置
        $data = $this->table('api_config')->getAll();
        $cache = [];
        if ($data) {
            foreach ($data as $t) {
                $cache[$t['name']] = dr_string2array($t['value']);
            }
        }

        \Phpcmf\Service::L('cache')->set_file('api_config', $cache);

    }

}