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

namespace app\api\logic;

use EasyWeChat\Factory;
use app\common\{
    enum\UserTerminalEnum,
    model\GoodsCollect,
    model\User,
    model\Order,
    enum\PayEnum,
    enum\OrderEnum,
    model\UserAuth,
    model\UserLevel,
    logic\BaseLogic,
    model\AfterSale,
    enum\AfterSaleEnum,
    service\ConfigService,
    service\sms\SmsDriver,
    service\WeChatConfigService,
};
use app\common\model\Article;
use app\common\model\UserCollect;
use app\common\model\UserFollow;
use think\Exception;
use think\facade\Config;
use think\facade\Db;

/**
 * 会员逻辑层
 * Class UserLogic
 * @package app\api\logic
 */
class UserLogic extends BaseLogic
{

    /**
     * @notes 个人中心
     * @param array $userInfo
     * @return array
     */
    public function centre(array $userInfo): array
    { 
        $with =['user_level','currentVip','label'];

        if(\isActivePluginByPluginName('merchant')){
            $with[]='merchant';
        }
        $user = User::with($with)->field('id,desc,sn,sex,nickname,avatar,user_money,user_integral,mobile,level,create_time,code,is_new_user,is_certification,vip_expire_time,vip_level_id,ip,user_earnings,home_bg,notice_comment_auth_check,private_like,private_follow,private_collect,private_fans,private_visitor,withdraw_wepay_code,withdraw_alipay_code,withdraw_name,withdraw_alipay_account,birth,career,height,weight,address,ip_address,font_size,theme')
            ->find($userInfo['user_id']);

        // --- 校准等级开始 ---
        $realIntegral = (int)($user->user_integral ?? 0);
        $levelList = \app\common\model\UserLevel::order('rank asc')->select();
        $correctLevel = $levelList[0] ?? null;
        if (!$levelList->isEmpty()) {
            foreach ($levelList as $lvl) {
                if ($realIntegral >= (int)$lvl->experience) {
                    $correctLevel = $lvl;
                } else {
                    break;
                }
            }
        }
        if ($correctLevel && $user->level != $correctLevel->id) {
            $user->level = $correctLevel->id;
            \app\common\model\User::where('id', $user->id)->update(['level' => $correctLevel->id]);
            // 重新关联最新的等级信息，确保返回给前端的数据是正确的
            $user->setRelation('user_level', $correctLevel);
        }
        // --- 校准等级结束 ---

        $user->level_rank = $user->user_level->rank ?? '';
        $user->level_name = $user->user_level->name ?? '';
        //待支付
        $user->wait_pay = Order::where(['user_id' => $userInfo['user_id'], 'order_status' => OrderEnum::STATUS_WAIT_PAY, 'pay_status' => PayEnum::UNPAID])->count();
        //待发货
        $user->wait_delivery = Order::where(['user_id' => $userInfo['user_id'], 'order_status' => OrderEnum::STATUS_WAIT_DELIVERY, 'pay_status' => PayEnum::ISPAID])->count();
        //待收货
        $user->wait_take = Order::where(['user_id' => $userInfo['user_id'], 'order_status' => OrderEnum::STATUS_WAIT_RECEIVE, 'pay_status' => PayEnum::ISPAID])->count();
        
        //退款、售后
        $user->after_sale = AfterSale::where(['user_id' => $userInfo['user_id'], 'status' => AfterSaleEnum::STATUS_ING])->count();
        

        //商品收藏数量
        // $user->collect = GoodsCollect::where(['user_id' => $userInfo['user_id']])->count();
        $user->collect = UserCollect::where([ 'type' => 1, 'user_id' => $userInfo['user_id'] ])->count();
               
        
        //关注数量
        $user->follow = UserFollow::where(['user_id' => $userInfo['user_id']])->count();
        //粉丝数量
        $user->fans_num = UserFollow::where(['follow_user_id' => $userInfo['user_id']])->count();
        // 帖子数量
        $user->article_num = Article::where(['user_id' => $userInfo['user_id'],'status'=>1,'is_show'=>1])->count();

        //是否有微信授权登录
        if (in_array($userInfo['terminal'], [UserTerminalEnum::WECHAT_MMP, UserTerminalEnum::WECHAT_OA])) {
            $auth = UserAuth::where(['user_id' => $userInfo['user_id'], 'terminal' => $userInfo['terminal']])->find();
            $user->is_auth = $auth ? 1 : 0;
        }

        // 昵称 和手机号一致时  做加密处理
        // if($user->nickname == $user->mobile){
        //     $user->nickname = substr_replace($user->nickname,'****',3,4);
        // }
        // $user->mobile = substr_replace($user->mobile,'****',3,4);

        $user->withdraw_wepay_code = $user->withdraw_wepay_code?\app\common\service\FileService::getFileUrl($user->withdraw_wepay_code):'';
        $user->withdraw_alipay_code = $user->withdraw_alipay_code?\app\common\service\FileService::getFileUrl($user->withdraw_alipay_code):'';
        

        $user->hidden(['name', 'rank']);
        return $user->toArray();
    }

    public static function updateFake($user,$name=null,$avatar=null)
    {
        $realUser = User::find($user->fake_user_owner_id);

        if (!$realUser) {
            return;
        }

        $realUser->id = $user->id;

        if ($name !== null) {
            $realUser->nickname = $name;
        }

        if ($avatar !== null) {
            $realUser->avatar = $avatar;
        }

        $realUser->save();
    }

    /**
     * @notes 个人主页
     * @param array $userInfo
     * @return array
     */
    public function home(array $userInfo ,$params): array
    {

        $user = User::with(['label','user_level','chat_group'=>function($query){
            $query->where([
                ['home_show','=',1],
                ['status','=',1],
            ]);
        }])->field('id,sex,birth,nickname,avatar,level,user_integral,create_time,ip,ip_address,home_bg,desc,images')->find($params['user_id']);

        // --- 校准等级开始 ---
        $realIntegral = (int)($user->user_integral ?? 0);
        $levelList = \app\common\model\UserLevel::order('rank asc')->select();
        $correctLevel = $levelList[0] ?? null;
        if (!$levelList->isEmpty()) {
            foreach ($levelList as $lvl) {
                if ($realIntegral >= (int)$lvl->experience) {
                    $correctLevel = $lvl;
                } else {
                    break;
                }
            }
        }
        if ($correctLevel && $user->level != $correctLevel->id) {
            $user->level = $correctLevel->id;
            \app\common\model\User::where('id', $user->id)->update(['level' => $correctLevel->id]);
            $user->setRelation('user_level', $correctLevel);
        }
        // --- 校准等级结束 ---

        //关注数量
        $user->follow = UserFollow::where(['user_id' => $params['user_id']])->count();
        //粉丝数量
        $user->fans_num = UserFollow::where(['follow_user_id' => $params['user_id']])->count();
        // 帖子数量
        $user->article_num = Article::where(['user_id' => $params['user_id'],'status'=>1,'is_show'=>1])->count();
        
        if($userInfo) {
            //是否关注过改帖子用户
            $isFollow = UserFollow::where([ 'follow_user_id' => $user->id, 'user_id' => $userInfo['user_id']])->value('id');
            $user->is_follow = $isFollow ? 1 : 0;
        }
        
        return $user->toArray();

    }


    /**
     * @notes 设置用户信息
     * @param int $userId
     * @param array $params
     * @return bool
     */
    public static function setInfo(int $userId, array $params): bool
    {
        User::update([$params['field'] => $params['value']], ['id' => $userId]);
        return true;
    }

    /**
     * @notes 绑定手机号
     * @param $params
     * @return bool
     */
    public static function bindMobile($params)
    {
        try {
            $smsDriver = new SmsDriver();
            $result = $smsDriver->verify($params['mobile'], $params['code']);
            if (!$result) {
                throw new \Exception('验证码错误');
            }
            $user = User::where('mobile', $params['mobile'])->findOrEmpty();
            if (!$user->isEmpty()) {
                throw new \Exception('该手机号已被其他账号绑定');
            }
            unset($params['code']);
            User::update($params, ['id' => $params['id']]);
            return true;
        } catch (\Exception $e) {
            self::setError($e->getMessage());
            return false;
        }
    }

    /**
     * @notes 会员中心
     * @param int $userId
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function userLevel(int $userId): array
    {
       
        $user = User::field('id,nickname,avatar,level,user_integral')->find($userId);
        $levelList = UserLevel::order(['rank' => 'asc'])->withoutField('remark,create_time,update_time,delete_time')->select();
        
        // --- 实时校准当前用户等级开始 ---
        $realIntegral = (int)($user->user_integral ?? 0);
        $correctLevel = $levelList[0] ?? null;
        foreach ($levelList as $lvl) {
            if ($realIntegral >= (int)$lvl->experience) {
                $correctLevel = $lvl;
            } else {
                break;
            }
        }
        if ($correctLevel && $user->level != $correctLevel->id) {
            $user->level = $correctLevel->id;
            User::where('id', $user->id)->update(['level' => $correctLevel->id]);
        }
        // --- 实时校准当前用户等级结束 ---
        $levelName = '';
        foreach ($levelList as $levelKey => $level) {

            if ($level->discount > 0) {
                $level->discount = '会员折扣:' . floatval($level->discount) . '折';
            }
            //下个等级
            $level->next_level = $levelList[$levelKey + 1]->name ?? '';

            $level->status = 0;
            if ($user->level == $level->id) {
                $level->status = 1;
                $levelName = $level->name;
                $user->rank = $level->rank;//更新为等级权重
            }
            //会员条件
            $conditionArray = [];
            $level->condition = $conditionArray;
        }
        $user->level_name = $levelName;
        $data = [
            'user' => $user,
            'level_list' => $levelList,
        ];

        return $data;
    }

    /**
     * @notes 判断用户是否已设置支付密码
     * @param $userId
     * @return bool
     */
    public static function hasPayPassword($userId)
    {
        $user = User::findOrEmpty($userId);
        if (empty($user->pay_password)) {
            return ['has_pay_password' => false];
        }
        return ['has_pay_password' => true];
    }

    /**
     * @notes 设置/修改交易密码
     * @param $params
     * @return bool
     */
    public static function setPayPassword($params)
    {
        try {
            $user = User::findOrEmpty($params['user_id']);
            if (empty($user->pay_password)) {
                // 首次设置密码
                $user->pay_password = md5($params['pay_password']);
                $user->save();
                return true;
            }
            // 修改密码
            if (!isset($params['origin_pay_password']) || empty($params['origin_pay_password'])) {
                throw new \think\Exception('请输入原支付密码');
            }
            if ($user->pay_password != md5($params['origin_pay_password'])) {
                throw new \think\Exception('原支付密码错误');
            }
            // 设置新支付密码
            $user->pay_password = md5($params['pay_password']);
            $user->save();

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

    /**
     * @notes 重置支付密码
     * @param $params
     * @return bool
     */
    public static function resetPayPassword($params)
    {
        try {
            // 校验验证码
            $smsDriver = new SmsDriver();
            if (!$smsDriver->verify($params['mobile'], $params['code'])) {
                throw new \Exception('验证码错误');
            }
            $params['pay_password'] = md5($params['pay_password']);
            unset($params['code']);
            unset($params['mobile']);
            User::update($params, ['id' => $params['id']]);

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

    /**
     * @notes 重置登录密码
     * @param $params
     * @return bool
     */
    public static function resetPassword($params)
    {
        try {
            // 校验验证码
            $smsDriver = new SmsDriver();
            if (!$smsDriver->verify($params['mobile'], $params['code'])) {
                throw new \Exception('验证码错误');
            }
            $passwordSalt = Config::get('project.unique_identification');
            $password = create_password($params['password'], $passwordSalt);

            User::where('mobile', $params['mobile'])->update([
                'password' => $password,
                'salt' => $passwordSalt
            ]);

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

    /**
     * @notes 钱包
     * @param $userId
     * @return array
     */
    public static function wallet($userId)
    {
        $user = User::findOrEmpty($userId);
        $rechargeOpen = ConfigService::get('recharge', 'open');
        $userMoney = is_null($user->user_money) ? 0 : $user->user_money;
        $userEarnings = is_null($user->user_earnings) ? 0 : $user->user_earnings;
        return [
            'user_money' => $userMoney,
            'user_earnings' => $userEarnings,
            'total_amount' => round($userMoney + $userEarnings, 2),
            'recharge_open' => $rechargeOpen
        ];
    }

    /**
     * @notes 用户信息
     * @param $userId
     * @return array
     */
    public static function info($userId)
    {
        $user = User::field('sn,avatar,nickname,sex,mobile,create_time,desc,longitude,latitude,address,district,province,county,area,birth,career,height,weight,images')->findOrEmpty($userId)->toArray();
        $user['has_password'] = empty($user['password']) ? '未设置' : '已设置';
        $user['version'] = request()->header('version');
        return $user;
    }

    /**
     * @notes 获取微信手机号
     * @param $params
     * @return array|false
     * @deprecated 小程序获取手机号码更新升级，旧接口放弃
     */
    public static function getMobileByMnp($params)
    {
        try {
            $config = [
                'app_id' => ConfigService::get('mini_program', 'app_id'),
                'secret' => ConfigService::get('mini_program', 'app_secret'),
            ];
            $app = Factory::miniProgram($config);
            $response = $app->auth->session($params['code']);
            if (!isset($response['session_key'])) {
                throw new \Exception('获取用户信息失败');
            }
            $response = $app->encryptor->decryptData($response['session_key'], $params['iv'], $params['encrypted_data']);
            $user = User::where([
                ['mobile', '=', $response['phoneNumber']],
                ['id', '<>', $params['user_id']]
            ])->findOrEmpty();
            if (!$user->isEmpty()) {
                throw new \Exception('手机号已被其他账号绑定');
            }
            // 绑定手机号
            self::setInfo($params['user_id'], [
                'field' => 'mobile',
                'value' => $response['phoneNumber']
            ]);

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

    /**
     * @notes 微信小程序获取手机号码并绑定
     * @param $params
     * @return bool
     * @throws \GuzzleHttp\Exception\GuzzleException
     * @author lgp
     * @date 2022/5/17 9:34
     */
    public static function getNewMobileByMnp($params)
    {
        try {
            $getMnpConfig = WeChatConfigService::getMnpConfig();
            $app = Factory::miniProgram($getMnpConfig);
            $response = $app->phone_number->getUserPhoneNumber($params['code']);

            $phoneNumber = $response['phone_info']['purePhoneNumber'] ?? '';
            if(empty($phoneNumber)){
                throw new Exception('获取手机号码失败');
            }
            $user = User::where([
                ['mobile', '=', $phoneNumber],
                ['id', '<>', $params['user_id']]
            ])->findOrEmpty();

            if (!$user->isEmpty()) {
                throw new \Exception('手机号已被其他账号绑定');
            }

            // 绑定手机号
            self::setInfo($params['user_id'], [
                'field' => 'mobile',
                'value' => $phoneNumber
            ]);

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

    }

    /**
     * @notes 获取服务协议
     * @return array
     */
    public static function getServiceAgreement()
    {
        $data = [
            'service_agreement_name' => ConfigService::get('shop', 'service_agreement_name', ''),
            'service_agreement_content' => ConfigService::get('shop', 'service_agreement_content', ''),
        ];
        return $data;
    }

    /**
     * @notes 获取隐私政策
     * @return array
     */
    public static function getPrivacyPolicy()
    {
        $data = [
            'privacy_policy_name' => ConfigService::get('shop', 'privacy_policy_name', ''),
            'privacy_policy_content' => ConfigService::get('shop', 'privacy_policy_content', '')
        ];
        return $data;
    }

    /**
     * @notes 设置登录密码
     */
    public static function setPassword($params)
    {
        try {
            $user = User::findOrEmpty($params['user_id']);
            if ($user->isEmpty()) {
                throw new \Exception('用户不存在');
            }
            if (!empty($user->password)) {
                throw new \Exception('用户已设置登录密码');
            }
            $passwordSalt = Config::get('project.unique_identification');
            $password = create_password($params['password'], $passwordSalt);
            $user->password = $password;
            $user->save();

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

    public static function generateRandomString($length = 6) {
        // 定义包含大小写字母和数字的字符集
        $letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
        $numbers = '0123456789';
        $charset = $letters . $numbers;
        
        // 获取字符集的总长度
        $charsetLength = strlen($charset);
        
        // 初始化结果字符串
        $randomString = '';
        
        // 生成指定长度的随机字符串
        for ($i = 0; $i < $length; $i++) {
            // 随机获取一个字符的索引
            $randomIndex = mt_rand(0, $charsetLength - 1);
            // 将随机字符拼接到结果字符串
            $randomString .= $charset[$randomIndex];
        }
        
        return $randomString;
    }

    /**
     * @notes 修改登录密码
     * @param $params
     * @return bool
     */
    public static function changePassword($params)
    {
        try {
            $user = User::findOrEmpty($params['user_id']);
            if ($user->isEmpty()) {
                throw new \Exception('用户不存在');
            }

            $oldPassword = create_password($params['old_password'], $user->salt);

            $passwordSalt = static::generateRandomString();
            $user->salt = $passwordSalt;

            $newPassword = create_password($params['password'], $passwordSalt);
            if ($user->password != $oldPassword) {
                throw new \Exception('原密码错误');
            }
            $user->password = $newPassword;
            $user->save();

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

    /**
     * @notes 判断用户是否有设置登录密码
     * @param $userId
     */
    public static function hasPassword($userId)
    {
        $user = User::findOrEmpty($userId);
        return empty($user->password) ? false : true;
    }



    /**
     * @notes 设置用户认证信息
     * @param int $userId
     * @param array $params
     * @return bool
     */
    public static function setUserCertification(int $userId, array $params): bool
    {
        $user = User::findOrEmpty($userId);
        if( $user['is_certification'] == 1){
            self::setError('您已经认证过了~');
            return false;
        }
        User::update([
            'real_name' => $params['real_name'],
            'id_card' => $params['id_card'],
            'is_certification' => 1,
            'level'  => 2
        ], ['id' => $userId]);
        return true;
    }


    


}