<?php

namespace App\Http\Controllers\System;

use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use App\Http\Controllers\Controller;
use App\Services\WebSocket\WebSocketService;

/**
 * WebSocket Controller
 *
 * Provides API endpoints for WebSocket operations
 */
class WebSocket extends Controller
{
    /**
     * @var WebSocketService
     */
    protected $webSocketService;

    /**
     * WebSocket constructor
     */
    public function __construct()
    {
        $this->webSocketService = app(WebSocketService::class);
    }

    /**
     * Get online user count
     *
     * @return JsonResponse
     */
    public function getOnlineCount(): JsonResponse
    {
        $count = $this->webSocketService->getOnlineUserCount();

        return response()->json([
            'code' => 200,
            'message' => 'success',
            'data' => [
                'online_count' => $count
            ]
        ]);
    }

    /**
     * Get online user IDs
     *
     * @return JsonResponse
     */
    public function getOnlineUsers(): JsonResponse
    {
        $userIds = $this->webSocketService->getOnlineUserIds();

        return response()->json([
            'code' => 200,
            'message' => 'success',
            'data' => [
                'user_ids' => $userIds,
                'count' => count($userIds)
            ]
        ]);
    }

    /**
     * Check if a user is online
     *
     * @param Request $request
     * @return JsonResponse
     */
    public function checkOnline(Request $request): JsonResponse
    {
        $request->validate([
            'user_id' => 'required|integer'
        ]);

        $userId = $request->input('user_id');
        $isOnline = $this->webSocketService->isUserOnline($userId);

        return response()->json([
            'code' => 200,
            'message' => 'success',
            'data' => [
                'user_id' => $userId,
                'is_online' => $isOnline
            ]
        ]);
    }

    /**
     * Send message to a specific user
     *
     * @param Request $request
     * @return JsonResponse
     */
    public function sendToUser(Request $request): JsonResponse
    {
        $request->validate([
            'user_id' => 'required|integer',
            'type' => 'required|string',
            'data' => 'required|array'
        ]);

        $userId = $request->input('user_id');
        $type = $request->input('type');
        $data = $request->input('data');

        $message = [
            'type' => $type,
            'data' => $data
        ];

        $sent = $this->webSocketService->sendToUser($userId, $message);

        return response()->json([
            'code' => $sent ? 200 : 404,
            'message' => $sent ? 'Message sent successfully' : 'User is not online',
            'data' => [
                'user_id' => $userId,
                'sent' => $sent
            ]
        ], $sent ? 200 : 404);
    }

    /**
     * Send message to multiple users
     *
     * @param Request $request
     * @return JsonResponse
     */
    public function sendToUsers(Request $request): JsonResponse
    {
        $request->validate([
            'user_ids' => 'required|array',
            'user_ids.*' => 'integer',
            'type' => 'required|string',
            'data' => 'required|array'
        ]);

        $userIds = $request->input('user_ids');
        $type = $request->input('type');
        $data = $request->input('data');

        $message = [
            'type' => $type,
            'data' => $data
        ];

        $sentTo = $this->webSocketService->sendToUsers($userIds, $message);

        return response()->json([
            'code' => 200,
            'message' => 'success',
            'data' => [
                'total_users' => count($userIds),
                'sent_to' => $sentTo,
                'failed' => count($userIds) - count($sentTo)
            ]
        ]);
    }

    /**
     * Broadcast message to all users
     *
     * @param Request $request
     * @return JsonResponse
     */
    public function broadcast(Request $request): JsonResponse
    {
        $request->validate([
            'type' => 'required|string',
            'data' => 'required|array',
            'exclude_user_id' => 'nullable|integer'
        ]);

        $type = $request->input('type');
        $data = $request->input('data');
        $excludeUserId = $request->input('exclude_user_id');

        $message = [
            'type' => $type,
            'data' => $data
        ];

        $count = $this->webSocketService->broadcast($message, $excludeUserId);

        return response()->json([
            'code' => 200,
            'message' => 'Broadcast sent successfully',
            'data' => [
                'sent_to' => $count,
                'exclude_user_id' => $excludeUserId
            ]
        ]);
    }

    /**
     * Send message to a channel
     *
     * @param Request $request
     * @return JsonResponse
     */
    public function sendToChannel(Request $request): JsonResponse
    {
        $request->validate([
            'channel' => 'required|string',
            'type' => 'required|string',
            'data' => 'required|array'
        ]);

        $channel = $request->input('channel');
        $type = $request->input('type');
        $data = $request->input('data');

        $message = [
            'type' => $type,
            'data' => $data
        ];

        $count = $this->webSocketService->sendToChannel($channel, $message);

        return response()->json([
            'code' => 200,
            'message' => 'Message sent to channel successfully',
            'data' => [
                'channel' => $channel,
                'sent_to' => $count
            ]
        ]);
    }

    /**
     * Send system notification
     *
     * @param Request $request
     * @return JsonResponse
     */
    public function sendNotification(Request $request): JsonResponse
    {
        $request->validate([
            'title' => 'required|string|max:255',
            'message' => 'required|string|max:1000',
            'type' => 'nullable|string|in:info,success,warning,error',
            'extra_data' => 'nullable|array'
        ]);

        $title = $request->input('title');
        $message = $request->input('message');
        $type = $request->input('type', 'info');
        $extraData = $request->input('extra_data', []);

        $count = $this->webSocketService->sendSystemNotification($title, $message, $type, $extraData);

        return response()->json([
            'code' => 200,
            'message' => 'Notification sent successfully',
            'data' => [
                'sent_to' => $count
            ]
        ]);
    }

    /**
     * Send notification to specific users
     *
     * @param Request $request
     * @return JsonResponse
     */
    public function sendNotificationToUsers(Request $request): JsonResponse
    {
        $request->validate([
            'user_ids' => 'required|array',
            'user_ids.*' => 'integer',
            'title' => 'required|string|max:255',
            'message' => 'required|string|max:1000',
            'type' => 'nullable|string|in:info,success,warning,error',
            'extra_data' => 'nullable|array'
        ]);

        $userIds = $request->input('user_ids');
        $title = $request->input('title');
        $message = $request->input('message');
        $type = $request->input('type', 'info');
        $extraData = $request->input('extra_data', []);

        $sentTo = $this->webSocketService->sendNotificationToUsers($userIds, $title, $message, $type, $extraData);

        return response()->json([
            'code' => 200,
            'message' => 'Notification sent successfully',
            'data' => [
                'total_users' => count($userIds),
                'sent_to' => $sentTo,
                'failed' => count($userIds) - count($sentTo)
            ]
        ]);
    }

    /**
     * Push data update
     *
     * @param Request $request
     * @return JsonResponse
     */
    public function pushDataUpdate(Request $request): JsonResponse
    {
        $request->validate([
            'user_ids' => 'required|array',
            'user_ids.*' => 'integer',
            'resource_type' => 'required|string',
            'action' => 'required|string|in:create,update,delete',
            'data' => 'required|array'
        ]);

        $userIds = $request->input('user_ids');
        $resourceType = $request->input('resource_type');
        $action = $request->input('action');
        $data = $request->input('data');

        $sentTo = $this->webSocketService->pushDataUpdate($userIds, $resourceType, $action, $data);

        return response()->json([
            'code' => 200,
            'message' => 'Data update pushed successfully',
            'data' => [
                'resource_type' => $resourceType,
                'action' => $action,
                'total_users' => count($userIds),
                'sent_to' => $sentTo,
                'failed' => count($userIds) - count($sentTo)
            ]
        ]);
    }

    /**
     * Push data update to channel
     *
     * @param Request $request
     * @return JsonResponse
     */
    public function pushDataUpdateToChannel(Request $request): JsonResponse
    {
        $request->validate([
            'channel' => 'required|string',
            'resource_type' => 'required|string',
            'action' => 'required|string|in:create,update,delete',
            'data' => 'required|array'
        ]);

        $channel = $request->input('channel');
        $resourceType = $request->input('resource_type');
        $action = $request->input('action');
        $data = $request->input('data');

        $count = $this->webSocketService->pushDataUpdateToChannel($channel, $resourceType, $action, $data);

        return response()->json([
            'code' => 200,
            'message' => 'Data update pushed to channel successfully',
            'data' => [
                'channel' => $channel,
                'resource_type' => $resourceType,
                'action' => $action,
                'sent_to' => $count
            ]
        ]);
    }

    /**
     * Disconnect a user from WebSocket
     *
     * @param Request $request
     * @return JsonResponse
     */
    public function disconnectUser(Request $request): JsonResponse
    {
        $request->validate([
            'user_id' => 'required|integer'
        ]);

        $userId = $request->input('user_id');
        $disconnected = $this->webSocketService->disconnectUser($userId);

        return response()->json([
            'code' => $disconnected ? 200 : 404,
            'message' => $disconnected ? 'User disconnected successfully' : 'User is not online',
            'data' => [
                'user_id' => $userId,
                'disconnected' => $disconnected
            ]
        ], $disconnected ? 200 : 404);
    }
}
