<?php

namespace app\services\chat;

use app\models\chat\ChatSession;
use app\models\chat\ChatMessage;
use think\facade\Cache;
use think\facade\Db;

/**
 * 会话服务
 * Class SessionService
 * @package app\services\chat
 */
class SessionService
{
    // Redis Key 前缀
    private const USER_ACTIVE_SESSION_PREFIX = 'cs:user:active_session:';
    private const CONN_USER_PREFIX = 'cs:conn:user:';
    private const CONN_AGENT_PREFIX = 'cs:conn:agent:';

    private $assignService;

    public function __construct()
    {
        $this->assignService = new AssignService();
    }

    /**
     * 创建会话
     * @param int $userId 用户ID
     * @param int $source 来源 1=PC 2=Game 3=Portal
     * @return array 会话数据
     */
    public function createSession($userId, $source)
    {
        $redis = $this->getRedis();

        // 检查是否已有活跃会话
        $existingSession = ChatSession::getActiveByUserId($userId);
        if ($existingSession) {
            return $existingSession;
        }

        // 创建新会话
        $session = [
            'user_id' => $userId,
            'source' => $source,
            'status' => ChatSession::STATUS_PENDING,
            'create_time' => time(),
            'update_time' => time(),
        ];

        $sessionId = ChatSession::insertGetId($session);
        $session['id'] = $sessionId;

        // 缓存用户活跃会话
        $redis->set(self::USER_ACTIVE_SESSION_PREFIX . $userId, $sessionId);

        // 尝试分配客服
        $adminId = $this->assignService->assignSession($userId, $sessionId);
        if ($adminId !== null) {
            $session['admin_id'] = $adminId;
            $session['status'] = ChatSession::STATUS_ACTIVE;
        }

        return $session;
    }

    /**
     * 获取用户活跃会话
     */
    public function getActiveSession($userId)
    {
        return ChatSession::getActiveByUserId($userId);
    }

    /**
     * 获取会话详情(含用户信息)
     */
    public function getSessionDetail($sessionId)
    {
        $session = ChatSession::find($sessionId);
        if (!$session) {
            return null;
        }

        $session = $session->toArray();

        // 获取用户信息
        $user = Db::name('user')->where('id', $session['user_id'])->find();
        if ($user) {
            $session['user_info'] = [
                'id' => $user['id'],
                'username' => $user['username'],
                'nickname' => $user['nickname'] ?? $user['username'],
                'money' => $user['money'],
                'agent_id' => $user['agent_id'] ?? null,
            ];
        }

        return $session;
    }

    /**
     * 结束会话
     */
    public function endSession($sessionId, $operatorId)
    {
        $session = ChatSession::find($sessionId);
        if (!$session) {
            return false;
        }

        $session = $session->toArray();

        // 只能结束进行中的会话
        if ($session['status'] === ChatSession::STATUS_ENDED) {
            return true;
        }

        // 更新会话状态
        ChatSession::where('id', $sessionId)->update([
            'status' => ChatSession::STATUS_ENDED,
            'end_time' => time(),
            'update_time' => time(),
        ]);

        // 清理Redis缓存
        $redis = $this->getRedis();
        $redis->del(self::USER_ACTIVE_SESSION_PREFIX . $session['user_id']);

        // 释放客服会话配额
        if ($session['admin_id']) {
            $this->assignService->releaseSession($sessionId, $session['admin_id']);
        }

        return true;
    }

    /**
     * 转接会话
     */
    public function transferSession($sessionId, $newAdminId)
    {
        $session = ChatSession::find($sessionId);
        if (!$session || $session['status'] !== ChatSession::STATUS_ACTIVE) {
            return false;
        }

        $oldAdminId = $session['admin_id'];

        // 更新会话归属
        ChatSession::where('id', $sessionId)->update([
            'admin_id' => $newAdminId,
            'update_time' => time(),
        ]);

        // 更新Redis
        $redis = $this->getRedis();
        $redis->set('cs:session:owner:' . $sessionId, $newAdminId);

        // 调整负载计数
        if ($oldAdminId) {
            $oldLoad = (int)$redis->get('cs:agent:load:' . $oldAdminId) ?: 0;
            if ($oldLoad > 0) {
                $redis->decr('cs:agent:load:' . $oldAdminId);
            }
        }
        $redis->incr('cs:agent:load:' . $newAdminId);

        return true;
    }

    /**
     * 会话评价
     */
    public function rateSession($sessionId, $rating, $content = null)
    {
        $session = ChatSession::find($sessionId);
        if (!$session) {
            return false;
        }

        // 评分范围 1-5
        $rating = max(1, min(5, $rating));

        ChatSession::where('id', $sessionId)->update([
            'rating' => $rating,
            'rating_content' => $content ? mb_substr($content, 0, 500) : null,
            'update_time' => time(),
        ]);

        return true;
    }

    /**
     * 注册用户连接
     */
    public function registerUserConnection($userId, $fd)
    {
        $redis = $this->getRedis();
        $redis->setex(self::CONN_USER_PREFIX . $userId, 60, $fd);
    }

    /**
     * 注册客服连接
     */
    public function registerAgentConnection($adminId, $fd)
    {
        $redis = $this->getRedis();
        $redis->setex(self::CONN_AGENT_PREFIX . $adminId, 60, $fd);
    }

    /**
     * 刷新用户连接TTL
     */
    public function refreshUserConnection($userId)
    {
        $redis = $this->getRedis();
        $redis->expire(self::CONN_USER_PREFIX . $userId, 60);
    }

    /**
     * 刷新客服连接TTL
     */
    public function refreshAgentConnection($adminId)
    {
        $redis = $this->getRedis();
        $redis->expire(self::CONN_AGENT_PREFIX . $adminId, 60);
    }

    /**
     * 获取用户连接FD
     */
    public function getUserFd($userId): ?int
    {
        $redis = $this->getRedis();
        $fd = $redis->get(self::CONN_USER_PREFIX . $userId);
        return $fd ? (int)$fd : null;
    }

    /**
     * 获取客服连接FD
     */
    public function getAgentFd($adminId): ?int
    {
        $redis = $this->getRedis();
        $fd = $redis->get(self::CONN_AGENT_PREFIX . $adminId);
        return $fd ? (int)$fd : null;
    }

    /**
     * 清理用户连接
     */
    public function clearUserConnection($userId)
    {
        $redis = $this->getRedis();
        $redis->del(self::CONN_USER_PREFIX . $userId);
    }

    /**
     * 清理客服连接
     */
    public function clearAgentConnection($adminId)
    {
        $redis = $this->getRedis();
        $redis->del(self::CONN_AGENT_PREFIX . $adminId);
    }

    /**
     * 获取客服会话列表
     */
    public function getAgentSessions($adminId)
    {
        $sessions = ChatSession::getActiveByAdminId($adminId);

        // 附加用户信息和未读数
        foreach ($sessions as &$session) {
            $user = Db::name('user')->where('id', $session['user_id'])->find();
            $session['user_info'] = [
                'username' => $user['username'] ?? '',
                'nickname' => $user['nickname'] ?? $user['username'] ?? '',
                'money' => $user['money'] ?? 0,
            ];

            // 未读消息数
            $session['unread_count'] = ChatMessage::where('session_id', $session['id'])
                ->where('sender_type', ChatMessage::SENDER_USER)
                ->where('status', '<', ChatMessage::STATUS_READ)
                ->count();
        }

        return $sessions;
    }

    /**
     * 获取待分配会话列表
     */
    public function getPendingSessions()
    {
        $sessions = ChatSession::where('status', ChatSession::STATUS_PENDING)
            ->order('create_time', 'asc')
            ->select()
            ->toArray();

        foreach ($sessions as &$session) {
            $user = Db::name('user')->where('id', $session['user_id'])->find();
            $session['user_info'] = [
                'username' => $user['username'] ?? '',
                'nickname' => $user['nickname'] ?? $user['username'] ?? '',
                'money' => $user['money'] ?? 0,
            ];
        }

        return $sessions;
    }

    /**
     * 获取Redis实例
     */
    private function getRedis()
    {
        return Cache::store('redis')->handler();
    }
}
