<?php


namespace app\listener\chat;

use app\services\chat\SessionService;
use app\services\chat\AssignService;
use app\services\chat\MessageService;
use app\models\chat\ChatSession;
use app\models\chat\ChatMessage;
use think\facade\Db;
use think\swoole\WebSocket;

/**
 * 聊天会话监听器
 * 处理: chat.session.end, chat.session.rate, chat.agent.online, chat.agent.offline, chat.session.transfer
 * Class ChatSessionListener
 * @package app\listener\chat
 */
class ChatSessionListener
{
    private $sessionService;
    private $assignService;
    private $messageService;

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

    /**
     * 处理结束会话
     */
    public function onSessionEnd($ws, $event)
    {
        $fd = $ws->getSender();
        $tableFd = app('swoole.table.fd');
        $fdInfo = $tableFd->get((string)$fd);

        if (!$fdInfo || !in_array($fdInfo['mode'], ['chat_user', 'chat_agent'])) {
            return;
        }

        $sessionId = (int)($event['sessionId'] ?? 0);
        $session = ChatSession::find($sessionId);

        if (!$session) {
            $ws->emit('chat.session.ended', [
                'success' => false,
                'error' => 'session_not_found'
            ]);
            return;
        }

        // 验证权限
        $operatorId = $fdInfo['user_id'];
        if ($fdInfo['mode'] === 'chat_user' && $session['user_id'] != $operatorId) {
            $ws->emit('chat.session.ended', [
                'success' => false,
                'error' => 'permission_denied'
            ]);
            return;
        }
        if ($fdInfo['mode'] === 'chat_agent' && $session['admin_id'] != $operatorId) {
            $ws->emit('chat.session.ended', [
                'success' => false,
                'error' => 'permission_denied'
            ]);
            return;
        }

        // 结束会话
        $result = $this->sessionService->endSession($sessionId, $operatorId);

        if ($result) {
            // 通知双方
            $ws->emit('chat.session.ended', [
                'success' => true,
                'sessionId' => $sessionId
            ]);

            // 通知对方
            if ($fdInfo['mode'] === 'chat_user' && $session['admin_id']) {
                $ws->to('chat_agent_' . $session['admin_id'])->emit('chat.session.ended', [
                    'sessionId' => $sessionId,
                    'endedBy' => 'user'
                ]);
            } elseif ($fdInfo['mode'] === 'chat_agent') {
                $ws->to('chat_user_' . $session['user_id'])->emit('chat.session.ended', [
                    'sessionId' => $sessionId,
                    'endedBy' => 'agent'
                ]);
            }
        }
    }

    /**
     * 处理会话评价
     */
    public function onSessionRate($ws, $event)
    {
        $fd = $ws->getSender();
        $tableFd = app('swoole.table.fd');
        $fdInfo = $tableFd->get((string)$fd);

        // 只有用户可以评价
        if (!$fdInfo || $fdInfo['mode'] !== 'chat_user') {
            return;
        }

        $sessionId = (int)($event['sessionId'] ?? 0);
        $rating = (int)($event['rating'] ?? 0);
        $content = $event['content'] ?? null;

        $session = ChatSession::find($sessionId);
        if (!$session || $session['user_id'] != $fdInfo['user_id']) {
            $ws->emit('chat.session.rated', [
                'success' => false,
                'error' => 'invalid_session'
            ]);
            return;
        }

        $result = $this->sessionService->rateSession($sessionId, $rating, $content);

        $ws->emit('chat.session.rated', [
            'success' => $result,
            'sessionId' => $sessionId
        ]);
    }

    /**
     * 处理客服上线
     */
    public function onAgentOnline($ws, $event)
    {
        $fd = $ws->getSender();
        $tableFd = app('swoole.table.fd');
        $fdInfo = $tableFd->get((string)$fd);

        if (!$fdInfo || $fdInfo['mode'] !== 'chat_agent') {
            return;
        }

        $adminId = $fdInfo['user_id'];
        $maxSessions = (int)($event['maxSessions'] ?? 10);

        // 设置在线状态
        $this->assignService->setAgentOnline($adminId);

        // 处理离线队列
        $processed = $this->assignService->processOfflineQueue($adminId);

        // 获取当前会话列表
        $sessions = $this->sessionService->getAgentSessions($adminId);

        $ws->emit('chat.agent.online_success', [
            'sessions' => $sessions,
            'processedFromQueue' => count($processed),
        ]);

        // 通知被分配的用户
        foreach ($processed as $item) {
            $this->notifyUserAssigned($ws, $item['userId'], $item['sessionId'], $adminId);
        }
    }

    /**
     * 处理客服下线
     */
    public function onAgentOffline($ws, $event)
    {
        $fd = $ws->getSender();
        $tableFd = app('swoole.table.fd');
        $fdInfo = $tableFd->get((string)$fd);

        if (!$fdInfo || $fdInfo['mode'] !== 'chat_agent') {
            return;
        }

        $adminId = $fdInfo['user_id'];

        // 设置离线状态
        $this->assignService->setAgentOffline($adminId);

        // 获取该客服的活跃会话
        $sessions = ChatSession::getActiveByAdminId($adminId);

        // 通知用户客服已离线
        foreach ($sessions as $session) {
            $ws->to('chat_user_' . $session['user_id'])->emit('chat.offline_notice', [
                'sessionId' => $session['id'],
                'message' => '客服已离线，请稍后再试'
            ]);
        }

        $ws->emit('chat.agent.offline_success', [
            'success' => true
        ]);
    }

    /**
     * 处理会话转接
     */
    public function onSessionTransfer($ws, $event)
    {
        $fd = $ws->getSender();
        $tableFd = app('swoole.table.fd');
        $fdInfo = $tableFd->get((string)$fd);

        if (!$fdInfo || $fdInfo['mode'] !== 'chat_agent') {
            return;
        }

        $sessionId = (int)($event['sessionId'] ?? 0);
        $targetAdminId = (int)($event['targetAdminId'] ?? 0);

        $session = ChatSession::find($sessionId);
        if (!$session || $session['admin_id'] != $fdInfo['user_id']) {
            $ws->emit('chat.session.transferred', [
                'success' => false,
                'error' => 'invalid_session'
            ]);
            return;
        }

        // 检查目标客服是否在线
        $onlineAgents = $this->assignService->getOnlineAgents();
        if (!in_array($targetAdminId, $onlineAgents)) {
            $ws->emit('chat.session.transferred', [
                'success' => false,
                'error' => 'target_agent_offline'
            ]);
            return;
        }

        // 执行转接
        $result = $this->sessionService->transferSession($sessionId, $targetAdminId);

        if ($result) {
            $targetAdmin = Db::name('admin')->where('id', $targetAdminId)->find();

            // 通知原客服
            $ws->emit('chat.session.transferred', [
                'success' => true,
                'sessionId' => $sessionId
            ]);

            // 通知新客服
            $sessionDetail = $this->sessionService->getSessionDetail($sessionId);
            $ws->to('chat_agent_' . $targetAdminId)->emit('chat.session.new', [
                'session' => $sessionDetail,
                'transferredFrom' => $fdInfo['user_id']
            ]);

            // 通知用户
            $ws->to('chat_user_' . $session['user_id'])->emit('chat.session.assigned', [
                'sessionId' => $sessionId,
                'agentInfo' => [
                    'id' => $targetAdmin['id'],
                    'nickname' => $targetAdmin['nickname'] ?? $targetAdmin['username'] ?? '客服',
                ],
                'transferred' => true
            ]);
        } else {
            $ws->emit('chat.session.transferred', [
                'success' => false,
                'error' => 'transfer_failed'
            ]);
        }
    }

    /**
     * 获取待处理队列列表 (客服端)
     */
    public function onQueueList($ws, $event)
    {
        $fd = $ws->getSender();
        $tableFd = app('swoole.table.fd');
        $fdInfo = $tableFd->get((string)$fd);

        if (!$fdInfo || $fdInfo['mode'] !== 'chat_agent') {
            return;
        }

        $pendingSessions = $this->sessionService->getPendingSessions();

        $ws->emit('chat.queue.list', [
            'sessions' => $pendingSessions
        ]);
    }

    /**
     * 通知用户会话已分配
     */
    private function notifyUserAssigned($ws, $userId, $sessionId, $adminId)
    {
        $admin = Db::name('admin')->where('id', $adminId)->find();

        $ws->to('chat_user_' . $userId)->emit('chat.session.assigned', [
            'sessionId' => $sessionId,
            'agentInfo' => [
                'id' => $admin['id'],
                'nickname' => $admin['nickname'] ?? $admin['username'] ?? '客服',
            ],
        ]);
    }
}
