<?php
// +----------------------------------------------------------------------
// | onezan-admin 快速开发的管理平台
// +----------------------------------------------------------------------
// | 官方网址：https://www.onezan.cn
// +----------------------------------------------------------------------
// | onezan团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: 543885307@qq.com
// +----------------------------------------------------------------------
namespace app\service\domain\security;

use app\repository\channel\ChannelRepository;
use app\service\domain\channel\driver\wechat\EasywechatFactory;
use Core\service\BaseCoreService;
use think\facade\Log;

/**
 * 核心安全过滤服务
 * @class CoreSecurityFilterService
 * @package app\service\domain\security
 */
class CoreSecurityFilterService extends BaseCoreService
{
    private const TARGET_CHANNEL = 'weapp';
    private const CONFIG_KEY = 'content_security_enabled';
    private const MAX_TEXT_LENGTH = 500 * 1024;

    /**
     * 是否启用核心安全过滤
     * @return bool
     */
    public function isEnabled(): bool
    {
        try {
            $config = $this->channelRepository()->getConfig(self::TARGET_CHANNEL, 'base');
            return (string)($config[self::CONFIG_KEY] ?? '') === '1';
        } catch (\Throwable $e) {
            return false;
        }
    }

    /**
     * 过滤文本
     * @param string $content 文本内容
     * @return array{code:int, msg:string}
     */
    public function filterText(string $content): array
    {
        $content = trim($content);
        if ($content === '') {
            return ['code' => 0, 'msg' => 'ok'];
        }

        if (!$this->isEnabled()) {
            return ['code' => 0, 'msg' => 'ok'];
        }

        if ($this->app->isDebug()) {
            Log::info('[] (Mock)', ['preview' => mb_substr($content, 0, 100)]);
            return ['code' => 0, 'msg' => 'ok'];
        }

        if (strlen($content) > self::MAX_TEXT_LENGTH) {
            Log::warning('content security check: empty or too long', ['length' => strlen($content)]);
            return ['code' => 0, 'msg' => 'ok'];
        }

        try {
            $weapp = $this->getWeappApp();
            if (!$weapp) {
                Log::warning('weapp not available for content check');
                return ['code' => 0, 'msg' => 'ok'];
            }

            $result = $weapp->getClient()->postJson('wxa/msg_sec_check', [
                'content' => $content,
            ]);

            $body = $result->toArray();
            $errCode = (int)($body['errcode'] ?? 0);

            if ($errCode === 0) {
                return ['code' => 0, 'msg' => 'ok'];
            }

            Log::warning('[] ', [
                'errcode' => $errCode,
                'errmsg'  => $body['errmsg'] ?? '',
                'preview' => mb_substr($content, 0, 100),
            ]);

            return ['code' => 1, 'msg' => ''];
        } catch (\Throwable $e) {
            Log::error('[] : ' . $e->getMessage());
            return ['code' => 0, 'msg' => 'ok'];
        }
    }

    /**
     * 过滤图片
     * @param string $imagePath 图片路径
     * @return array{code:int, msg:string}
     */
    public function filterImage(string $imagePath): array
    {
        if ($imagePath === '' || !file_exists($imagePath)) {
            return ['code' => 0, 'msg' => 'ok'];
        }

        if (!$this->isEnabled()) {
            return ['code' => 0, 'msg' => 'ok'];
        }

        if ($this->app->isDebug()) {
            Log::info('[] (Mock)', ['path' => $imagePath]);
            return ['code' => 0, 'msg' => 'ok'];
        }

        try {
            $weapp = $this->getWeappApp();
            if (!$weapp) {
                Log::warning('weapp not available');
                return ['code' => 0, 'msg' => 'ok'];
            }

            $result = $weapp->getClient()->httpUpload('wxa/img_sec_check', [
                'media' => $imagePath,
            ]);

            $body = $result->toArray();
            $errCode = (int)($body['errcode'] ?? 0);

            if ($errCode === 0) {
                return ['code' => 0, 'msg' => 'ok'];
            }

            Log::warning('[] ', [
                'errcode' => $errCode,
                'errmsg'  => $body['errmsg'] ?? '',
                'path'    => $imagePath,
            ]);

            return ['code' => 1, 'msg' => ''];
        } catch (\Throwable $e) {
            Log::error('[] : ' . $e->getMessage());
            return ['code' => 0, 'msg' => 'ok'];
        }
    }

    // ---------- private ----------

    /**
     * 获取微信小程序应用实例
     * @return \EasyWeChat\MiniApp\Application|null
     */
    private function getWeappApp(): ?\EasyWeChat\MiniApp\Application
    {
        try {
            $config = $this->channelRepository()->getConfig(self::TARGET_CHANNEL, 'base');
            if (empty($config['app_id'] ?? '') || empty($config['app_secret'] ?? '')) {
                return null;
            }
            return $this->app->make(EasywechatFactory::class)->miniApp($config);
        } catch (\Throwable $e) {
            Log::error('[] ? ' . $e->getMessage());
            return null;
        }
    }

    /**
     * 获取渠道仓库实例
     * @return ChannelRepository
     */
    private function channelRepository(): ChannelRepository
    {
        return $this->app->make(ChannelRepository::class);
    }
}
