<?php
namespace model;
use \model;
use model\wdzy\factory;

/**
 * Class Rca接口
 * @package model
 */
class rcaApi
{
    protected $config = null;
    protected $tokenName = 'rca.token.json';
    protected $apiName = 'EDC rcaApi';
    function __construct()
    {
        $this->config = \mvc::$cfg['RCAAPI'];
        //如果有租户
        if($this->config['tenant'])
        {
            $this->tokenName = $this->config['tenant'].'rca.token.json';
        }
    }

    /**
     * @method 统一请求入口：自动识别 GET/POST
     * @param string $urlPath 请求路径
     * @param array $get_arr GET 参数
     * @param array $post_arr POST 数据
     * @param int $run 重试次数
     * @param method POST 默认都是 POST，需要GET 请求请自行声明
     * @return mixed
     */
    public function Get($urlPath, $get_arr = [], $post_arr = [],$headers=[], $method = 'POST',$run = 0)
    {   
        if($this->apiName=='EDC rcaApi'){
            $status =  makeOne(\model\ckv::class)->getKV('edc_status');
            
        }elseif($this->apiName=='HDC 宜配资源'){
            $status =  makeOne(\model\ckv::class)->getKV('hdc_status');
        }
        if($status==-1){
            return [];
        }
        $run++;
        try {
            $url = $this->config['base_url'] . $urlPath;

            // 添加 GET 参数
            if (!empty($get_arr)) {
                $url .= (strpos($url, '?') === false ? '?' : '&') . http_build_query($get_arr);
            }

            $ch = curl_init();

            // 是否是上传文件的请求
            $isFormRequest = isset($post_arr['is_form']) && $post_arr['is_form'];
            $isQuery = isset($post_arr['is_query']) && $post_arr['is_query'];
            // 构建 headers
            $defaultHeaders = [];

            if ($isFormRequest) {
                $defaultHeaders[] = 'Content-Type: multipart/form-data';
            }elseif ($isQuery) {
                # code...
            } else {
                $defaultHeaders[] = 'Content-Type: application/json';
            }
                    

            $effectiveHeaders = array_merge($defaultHeaders, $headers);

            if(stripos($urlPath, 'account/login') === false && stripos($urlPath, 'tokens/get') === false ){
                $effectiveHeaders[] = 'Authorization: Bearer ' . $this->getToken();
            }

        
            if($effectiveHeaders){
                curl_setopt($ch, CURLOPT_HTTPHEADER, $effectiveHeaders);
            }
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT,10);
            curl_setopt($ch, CURLOPT_TIMEOUT,10);  
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);

            if (!empty($post_arr) || $method == 'POST') { 
                curl_setopt($ch, CURLOPT_POST, true);
            }
            // 自动识别是否为 POST 请求
            if (!empty($post_arr)) {
               
                if ($isFormRequest) {
                    curl_setopt($ch, CURLOPT_POSTFIELDS, $post_arr);
                } elseif ($isQuery) {
    
                    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_arr));
                } else {
                    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($post_arr));
                }
            }

            $output = curl_exec($ch);

            if ($error = curl_error($ch)) {
                curl_close($ch);
                throw new \Exception($error, 1);
            }
            $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); // 获取 HTTP 状态码
            $contentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
            curl_close($ch);
            //
            if ($httpCode >= 400) {
                $output_json = json_decode($output, true);
                if($output_json && isset($output_json['success']) && !$output_json['success'] && isset($output_json['message'])){
                    exitJson(-1,$this->apiName.$urlPath.'接口异常:' . $output_json['message']); 
                }
                // 检查是否是另一种常见的错误格式
                if($output_json && isset($output_json['error'])){
                    $errorMsg = isset($output_json['error']['message']) ? $output_json['error']['message'] : (is_string($output_json['error']) ? $output_json['error'] : '未知错误');
                    exitJson(-1, $this->apiName.$urlPath. '接口异常:' . $errorMsg);
                }
                
                // 如果响应不是JSON格式且不为空，可能是错误页面
                if (!$output_json && trim($output) !== '') {
                    // 检查是否包含常见的错误页面关键词
                    if (stripos($output, '<html') !== false || 
                        stripos($output, 'error') !== false || 
                        stripos($output, 'exception') !== false) {
                        errorLog(['url' => $url, 'post' => $post_arr, 'html' => $output], 'rcaapi');
                        exitJson(-1, $this->apiName.$urlPath. '接口异常: 返回了错误页面内容');
                    }
                }
                errorLog(['url' => $url, 'post' => $post_arr, 'html' => $output, 'httpCode' => $httpCode], 'rcaapi');
                exitJson(-1, $this->apiName.$urlPath. '接口异常: 服务器错误 (HTTP ' . $httpCode . ')');
            }
            // 处理响应
            if (strpos($contentType, 'image/') !== 0) {
                $output_json = json_decode($output, true);
                if($output_json && isset($output_json['success']) && !$output_json['success'] && isset($output_json['message'])){
                    exitJson(-1,$this->apiName.$urlPath.'接口异常:' . $output_json['message']); 
                }
                return $output_json ?: $output;
            } else {
                $mimeMap = [
                    'image/jpg' => 'jpg',
                    'image/jpeg' => 'jpg',
                    'image/png' => 'png',
                    'image/gif' => 'gif',
                    'image/bmp' => 'bmp',
                    'image/webp' => 'webp'
                ];
                $mimeType = explode(';', $contentType)[0];
                return ['data' => ['data' => $output, 'ext' => $mimeMap[$mimeType] ?? 'bin']];
            }

            // 递归重试
            //if ($run < 5) return $this->Get($urlPath, $get_arr, $post_arr,$headers,$method, $run);

            errorLog(['url' => $url, 'post' => $post_arr, 'html' => $output], 'rcaapi');
            exitJson(-1,$this->apiName.$urlPath.'接口异常:' . $output);

        } catch (\Exception $e) {
            
            //if ($run < 5) return $this->Get($urlPath, $get_arr, $post_arr,$headers,$method, $run);
            errorLog(['url' => $url, 'post' => $post_arr, 'html' => $e->getMessage()], 'rcaapi');
            exitJson(-1,$this->apiName.$urlPath.'接口异常:' . $e->getMessage());
        }
    }

    /**
     * @method 获取token
     * @author zhengweihua 
     * @copyright 2023-12-12
     */
    public function getToken()
    {
        if ($this->hasValidToken()) {
            return json_decode(file_get_contents($this->getTokenFile()), true)['token'];
        }
        // 如果租户存在，先获取租户token再用密码登录（否则接口莫名无法同步客户)
        if($this->config['tenant'])
        {
            $urlPath = 'tokens/get';
            $data = [
                'grantType'=>'client_credentials',
                'clientId' => $this->config['clientId'],
                'clientSecret' => $this->config['clientSecret']
            ];
            $res = $this->Get($urlPath, [], $data);
            $cretoken = $res['data'];
            $headers = [
                'Authorization: Bearer '.$cretoken['token']
            ];
        }
        // 如果租户不存在，直接使用账号密码登录
        else
        {
            $headers = [];
        }
        $urlPath = 'api/app/account/login';
        $data = [
            'name' => $this->config['name'],
            'password' => $this->config['password']
        ];
        $res = $this->Get($urlPath, [], $data, $headers);
        $token = $res;
        
        if($token['error']){
            exitJson(-1,'获取token失败：'.$token['error']['message']);
        }
        
        $this->setToken($token['token'], $token['expires']);
        return $token['token'];
    }


    /**
     * @method 获取租户信息
     * @author zhengweihua 
     * @copyright 2025-07-28
     */
    public function getTenant()
    {
        $url = 'Tenants/find';
        $data = [
            "name"=> $this->config['tenant']
        ];
        $res = $this->Get($url, [], $data);
        \mvc::$cfg['RCAAPI']['tenantId'] = $res['tenantId'] ?? '';
        \mvc::$cfg['RCAAPI']['tenant'] = $this->config['tenant'] ?? '';
    }

    /**
     * @method token文件
     * @author zhengweihua 
     * @copyright 2023-12-19
     */
    protected function getTokenFile()
    {
        return \mvc::$cfg['siteDir'] . '/' . $this->tokenName;
    }

    /**
     * @param  string $token
     * @param  string $expiresAt
     * @method 设置token
     * @author zhengweihua 
     * @copyright 2023-12-19
     */
    public function setToken($token, $expiresAt)
    {   
        $payload = [
            'token' => $token,
            'exp_time' => strtotime($expiresAt)<0?time()+3600:strtotime($expiresAt),
        ];

        file_put_contents($this->getTokenFile(), json_encode($payload));
    }

    /**
     * @method 判断token是否有效
     * @author zhengweihua 
     * @copyright 2023-12-19
     * @return bool
     */
    protected function hasValidToken()
    {
        if (!file_exists($this->getTokenFile())) {
            return false;
        }

        $token = json_decode(file_get_contents($this->getTokenFile()));
        return $token->exp_time >= time();
    }

    /**
     * @param  [type] $params
     * @param  [type] $numArr
     * @method 获取资源搜索结果
     * @author zhengweihua 
     * @copyright 2025-07-01
     */
    public function getSourceSearch($numArr, $type = 'num')
    {
        if (!$numArr) return [];
        $result = [];

        foreach ($numArr as $num) {
            $data = [
                'input' => $num,
                'priority' => 1,
                'fromPlatform' => 'web',
                'limit'=>200
            ];
            $arr = $this->Get('resources/searchbyindex', [], $data);
            if ($arr['data']) {
                foreach ($arr['data'] as $key => &$val) {
                    $val['searchNumber'] = $num;
                }
                unset($val);
                $result = array_merge($result, $arr['data'] ?: []);
            }
        }

        if ($result) {
            usort($result, function ($a, $b) {
                return strtotime($b['creationTime']) - strtotime($a['creationTime']);
            });

            $factory = new factory();
            $cates = \p::cates('1300');

            if (!\p::isAdmin() && $cates) {
                $join = ['[><]factory_cate(fc)' => ['fac.fac_id' => 'fc_fac_id']];
                $limitFac = $factory->db->select(
                    'factory(fac)',
                    $join,
                    ['fac_resource_facid'],
                    ['fc_cat_id' => explode(',', $cates), 'GROUP' => 'fac_resource_facid']
                );
                $limitFac = $limitFac ? array_column($limitFac, 'fac_resource_facid') : [];
            }

            $returnData = [];
            foreach ($result as $val) {
                if (isset($limitFac) && !in_array($val['resourceFactoryId'], $limitFac)) {
                    continue;
                }
                $val['creationTime'] = date('Y-m-d H:i:s', strtotime($val['creationTime']));
                if($val['rowData'] ){
                    foreach ($val['rowData'][0] as $field => &$v) 
                    {
                        if((stripos($field, '图片') !== false ||stripos($field, 'PHOTO') !== false||
                        stripos($field, 'picture') !== false ||
                        stripos($field, 'DIAGRAM') !== false || stripos($field, '照片') !== false) && !$v['Value'] && $val['pictureUrls']){
                            $v['Value'] = $val['pictureUrls'];
                            $v['Type'] = 'picture';
                            break;
                        }
                        $v = str_replace(["\n","\r\n"],"<br />",$v);
                    }
                    unset($v);
                }
                $returnData[] = $val;
            }
            unset($val);
            if(!$returnData){
                return [];
            }
            $facIds = array_column($returnData, 'resourceFactoryId');
            $arr = $factory->db->select(
                'factory',
                ['fac_id', 'fac_resource_facid'],
                ['fac_resource_facid' => $facIds]
            );
            $arr = $arr ? array_column($arr, 'fac_id', 'fac_resource_facid') : [];

            foreach ($returnData as $key => $val) {
                $returnData[$key]['fac_id'] = $arr[$val['resourceFactoryId']] ?? '';
            }
        }

        return $returnData;
    }

    /**
     * @param  string $id
     * @method 通过ID获取资源访问链接
     * @author zhengweihua 
     * @copyright 2025-07-01
     */
    public function getResourcesUrlById($id)
    {
        $res = $this->Get('resources/getbyid', [], ['id' => $id]);

        if ($res['data'] && isset($res['data']['relativePath']) && $res['data']['relativePath']) {
            $relativePath = $res['data']['relativePath'];
            $arr = $this->Get('tencentcos/getobjecturl?'. http_build_query(['relativePaths' => $relativePath]));
            return ['url' => $arr['data']];
        }

        return '';
    }

    public function getFactorySearch($keyword)
    {
        $data = [
            'input'=> '',
            'proCategoryNames'=>[$keyword],
            'fromPlatform' => 'frey',
            'fromCustomer' => 'frey'
        ];
        $arr = $this->Get('resourcefactory/listsimple', [], $data);
        
        return $arr['data']?array_slice($arr['data'],0,10):[];
    }
}