<?php
/**
 *  ╔═══════════════════════════════════════════════════╗
 *  ║                                                   ║
 *  ║     ██╗  ██╗   █████╗    ██████╗                  ║
 *  ║     ██║  ██║  ██╔══██╗  ██╔═══██╗                 ║
 *  ║     ███████║  ███████║  ██║   ██║                 ║
 *  ║     ██╔══██║  ██╔══██║  ██║   ██║                 ║
 *  ║     ██║  ██║  ██║  ██║  ╚██████╔╝   SNS           ║
 *  ║                                                   ║    
 *  ║                                                   ║    
 *  ║     © 2023 HaoSNS™ All Rights Reserved            ║
 *  ║     官方网站: https://www.haosns.com                *
 *  ║     本代码由赣州乐易网络科技有限公司®提供             *
 *  ║                                                    *
 *  ║   未经授权禁止复制、传播或用于其他商业目的            *
 *  ║                                                   ║
 *  ╚═══════════════════════════════════════════════════╝
 */


namespace app\common\logic;

use app\common\enum\NoticeEnum;
use app\common\enum\YesNoEnum;
use app\common\model\Notice;
use app\common\model\NoticeSetting;
use app\common\model\Order;
use app\common\model\OrderGoods;
use app\common\model\User;
use app\common\service\sms\SmsMessageService;
use app\common\model\TwoOrder;
use app\common\model\TwoOrderGoods;
use app\common\service\ConfigService;

/**
 * 通知逻辑层
 * Class NoticeLogic
 * @package app\common\logic
 */
class NoticeLogic extends BaseLogic
{
    /**
     * @notes 根据不同的场景发送通知
     * @param $params
     * @return bool
     */
    public static function noticeByScene($params)
    {
        try {
            $noticeSetting = NoticeSetting::where('scene_id', $params['scene_id'])->findOrEmpty()->toArray();

            if(empty($noticeSetting)) {
                throw new \Exception('找不到对应场景的配置');
            }
            
            
            $extra = json_encode($params);
          
            // 合并额外参数
            $params = self::mergeParams($params);
            $res = false;
            self::setError('通知功能未开启');

            
            // 系统通知
            if(isset($noticeSetting['system_notice']['status']) &&  $noticeSetting['system_notice']['status'] == YesNoEnum::YES) {
                $content = self::contentFormat($noticeSetting['system_notice']['content'], $params);
                $notice = self::addNotice($params, $noticeSetting, NoticeEnum::SYSTEM, $content ,$extra);
                if($notice) {
                    $res = true;
                }
            }
            // 短信通知
            if (isset($noticeSetting['sms_notice']['status']) &&  $noticeSetting['sms_notice']['status'] == YesNoEnum::YES) {

                // 短信发送限制====
                // 每日总发送量 
                $todayZero = strtotime('today');
                $day_limit_key = "day_limit_key_".$todayZero;
                $currentDaySendCount = cache($day_limit_key);
                if(!$currentDaySendCount){
                    $currentDaySendCount = 0;
                }
                // 每日总发送限制
                if(ConfigService::get('config', 'sms_send_day_limit_status',0)==1 &&  $currentDaySendCount>ConfigService::get('config', 'sms_send_day_limit_num', 0)){
                    throw new \think\Exception(ConfigService::get('sms_ip_limit', 'send_err', "短信发送太频繁了，请稍后再试，如有疑问请联系平台管理员"));
                }
                // 同一手机号每日总发送量
                $mobile_hour_key = 'mobile_hour_send_num_'.$params['params']['mobile'];
                $mobile_day_key = 'mobile_day_send_num_'.$params['params']['mobile'];
                $mobile_hour_num = cache($mobile_hour_key);
                $mobile_day_num = cache($mobile_day_key);
                if(ConfigService::get('sms_mobile_limit', 'send_count_limit_status',0)==1){
                    if($mobile_hour_num && $mobile_hour_num>ConfigService::get('sms_mobile_limit', 'hour_send_num', 0)){
                        throw new \think\Exception(ConfigService::get('sms_mobile_limit', 'send_err', "短信发送太频繁了，请稍后再试，如有疑问请联系平台管理员")); 
                    }
                    if($mobile_day_num && $mobile_day_num>ConfigService::get('sms_mobile_limit', 'day_send_num', 0)){
                        throw new \think\Exception(ConfigService::get('sms_mobile_limit', 'send_err', "短信发送太频繁了，请稍后再试，如有疑问请联系平台管理员")); 
                    }
                    
                }
                // 同一ip每日总发送量
                $ip_hour_key = 'ip_hour_send_num_'.$_SERVER['REMOTE_ADDR'];
                $ip_day_key = 'ip_day_send_num_'.$_SERVER['REMOTE_ADDR'];
                $ip_hour_num = cache($ip_hour_key);
                $ip_day_num = cache($ip_day_key);
                if(ConfigService::get('sms_ip_limit', 'send_count_limit_status',0)==1){
                    if($ip_hour_num && $ip_hour_num>ConfigService::get('sms_ip_limit', 'hour_send_num', 0)){
                        throw new \think\Exception(ConfigService::get('sms_ip_limit', 'send_err', "短信发送太频繁了，请稍后再试，如有疑问请联系平台管理员")); 
                    }
                    if($ip_day_num && $ip_day_num>ConfigService::get('sms_ip_limit', 'day_send_num', 0)){
                        throw new \think\Exception(ConfigService::get('sms_ip_limit', 'send_err', "短信发送太频繁了，请稍后再试，如有疑问请联系平台管理员")); 
                    }
                    
                }

                
                $res = (new SmsMessageService())->send($params);

                // 短信发送限制
                if($res){
                    // 每日数量统计
                    cache($day_limit_key,$currentDaySendCount+1, 60*60*24);

                    // 同一手机号每天发送总数
                    if(!$mobile_day_num){
                        cache($mobile_day_key,1, 60*60*24);
                    }else{
                        cache($mobile_day_key,$mobile_day_num+1, 60*60*24);
                    }
                    // 同一手机号每小时发送总数
                    if(!$mobile_hour_num){
                        cache($mobile_hour_key,1, 60*60);
                    }else{
                        cache($mobile_hour_key,$mobile_day_num+1, 60*60);
                    }
                    
                    // 同一ip每天发送总数
                    if(!$ip_day_num){
                        cache($ip_day_key,1, 60*60*24);
                    }else{
                        cache($ip_day_key,$ip_day_num+1, 60*60*24);
                    }
                    // 同一ip每小时发送总数
                    if(!$ip_hour_num){
                        cache($ip_hour_key,1, 60*60);
                    }else{
                        cache($ip_hour_key,$ip_day_num+1, 60*60);
                    }
                }


            }

            return $res;
        } catch (\Exception $e) {
            self::setError($e->getMessage());
            return false;
        }
    }

    /**
     * @notes 拼装额外参数
     * @param $params
     * @return array
     */
    public static function mergeParams($params)
    {
        // 订单相关
        if(!empty($params['params']['order_id'])) {
            if($params['params']['order_type'] == 'two_order'){
                $order = TwoOrder::findOrEmpty($params['params']['order_id'])->toArray();
                $order_goods = TwoOrderGoods::field('goods_name,goods_snap')
                    ->where('order_id', $params['params']['order_id'])
                    ->findOrEmpty()
                    ->toArray();
                $params['params']['goods_name'] = $order_goods['goods_name'] ?? '商品';
            

                if(mb_strlen($params['params']['goods_name']) > 8) {
                    $params['params']['goods_name'] = mb_substr($params['params']['goods_name'], 0, 8) . '...';
                }
                $params['params']['order_sn'] = $order['sn'];
                $params['params']['create_time'] = $order['create_time'];
                $params['params']['pay_time'] = $order['pay_time'];
                $params['params']['total_num'] = $order['total_num'];
                $params['params']['order_amount'] = $order['order_amount'];
            }else{
                $order = Order::findOrEmpty($params['params']['order_id'])->toArray();
                $order_goods = OrderGoods::field('goods_name,goods_snap')
                    ->where('order_id', $params['params']['order_id'])
                    ->findOrEmpty()
                    ->toArray();
                $params['params']['goods_name'] = $order_goods['goods_name'] ?? '商品';
            

                if(mb_strlen($params['params']['goods_name']) > 8) {
                    $params['params']['goods_name'] = mb_substr($params['params']['goods_name'], 0, 8) . '...';
                }
                $params['params']['order_sn'] = $order['sn'];
                $params['params']['create_time'] = $order['create_time'];
                $params['params']['pay_time'] = $order['pay_time'];
                $params['params']['total_num'] = $order['total_num'];
                $params['params']['order_amount'] = $order['order_amount'];
            };
            
        }

    
        // 用户相关
        if(!empty($params['params']['user_id'])) {
           
            $user = User::findOrEmpty($params['params']['user_id'])->toArray();
            $params['params']['nickname'] = $user['nickname'];
            $params['params']['user_name'] = $user['nickname'];
            $params['params']['user_sn'] = $user['sn'];
            $params['params']['mobile'] = $params['params']['mobile'] ?? $user['mobile'];

        }

        // 粉丝
        if(!empty($params['params']['fans_id'])) {
            $user = User::findOrEmpty($params['params']['fans_id'])->toArray();
            $params['params']['fans_name'] = $user['nickname'];
            $params['params']['fans_sn'] = $user['sn'];
        }

        // 跳转路径
        $jumpPath = self::getPathByScene($params['scene_id'], $params['params']['order_id'] ?? 0);
        $params['url'] = $jumpPath['url'];
        $params['page'] = $jumpPath['page'];
        return $params;
    }

    /**
     * @notes 根据场景获取跳转链接
     * @param $sceneId
     * @param $extraId
     * @return string[]
     */
    public static function getPathByScene($sceneId, $extraId)
    {
        // 主页路径
        $page = '/pages/index/index';
        // H5主页路径
        $url = '/mobile/pages/index/index';
        if(in_array($sceneId, NoticeEnum::ORDER_SCENE)) {
            $url = '/mobile/pages/order_detail/order_detail?order_id='.$extraId;
            $page = '/pages/order_detail/order_detail?order_id='.$extraId;
        }
        return [
            'url' => $url,
            'page' => $page,
        ];
    }

    /**
     * @notes 格式化消息内容(替换内容中的变量占位符)
     * @param $content
     * @param $params
     * @return array|mixed|string|string[]
     */
    public static function contentFormat($content, $params)
    {
        foreach($params['params'] as $k => $v) {
            $search = '{' . $k . '}';
            $content = str_replace($search, $v, $content);
        }
        return $content;
    }

    /**
     * @notes 添加通知记录
     * @param $params
     * @param $noticeSetting
     * @param $sendType
     * @param $content
     * @param string $extra
     * @return Notice|\think\Model
     */
    public static function addNotice($params, $noticeSetting, $sendType, $content, $extra = '')
    {
        $data = [
            'user_id' => $params['params']['user_id'] ?? 0,
            'title' => self::getTitleByScene($sendType, $noticeSetting),
            'content' => $content,
            'scene_id' => $noticeSetting['scene_id'],
            'read' => YesNoEnum::NO,
            'recipient' => $noticeSetting['recipient'],
            'send_type' => $sendType,
            'notice_type' => $noticeSetting['type'],
            'extra' => $extra,
        ];

        return Notice::create($data);
    }

    /**
     * @notes 根据场景获取标题
     * @param $sendType
     * @param $noticeSetting
     * @return string
     */
    public static function getTitleByScene($sendType, $noticeSetting)
    {
        switch ($sendType)
        {
            case NoticeEnum::SYSTEM:
                $title = $noticeSetting['system_notice']['title'] ?? '';
                break;
            case NoticeEnum::SMS:
                $title = '';
                break;
            case NoticeEnum::OA:
                $title = $noticeSetting['oa_notice']['name'] ?? '';
                break;
            case NoticeEnum::MNP:
                $title = $noticeSetting['mnp_notice']['name'] ?? '';
                break;
            default:
                $title = '';
        }

        return $title;
    }

}