<?php

declare(strict_types=1);

namespace App\Controller\OgAgent\Webhook;

use App\Entity\Client;
use App\Model\ClientStatus;
use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Attribute\AsController;
use Symfony\Component\Routing\Annotation\Route;

#[AsController]
class AgentSessionController extends AbstractController
{
    public function __construct(
        protected readonly EntityManagerInterface $entityManager,
        protected readonly LoggerInterface $logger
    )
    {
    }

    #[Route('/opengnsys/rest/ogagent/started', methods: ['POST'])]
    public function agentStarted(Request $request): JsonResponse
    {
        $data = $request->toArray();
        $requiredFields = ['mac', 'ip', 'secret', 'ostype', 'osversion', 'agent_version'];

        foreach ($requiredFields as $field) {
            if (!isset($data[$field])) {
                return new JsonResponse(['message' => "Missing parameter: $field"], Response::HTTP_BAD_REQUEST);
            }
        }

        $client = $this->entityManager->getRepository(Client::class)->findOneBy(['mac' => $data['mac']]);
        if (!$client) {
            return new JsonResponse(['message' => 'Client not found'], Response::HTTP_NOT_FOUND);
        }

        switch ($data['ostype']) {
            case 'Linux':
                $client->setStatus(ClientStatus::LINUX);
                break;
            case 'Windows':
                $client->setStatus(ClientStatus::WINDOWS);
                break;
            case 'MacOS':
                $client->setStatus(ClientStatus::MACOS);
                break;

            default:
                return new JsonResponse(['message' => 'Invalid status'], Response::HTTP_BAD_REQUEST);
        }

        $client->setToken($data['secret'] ?? null);

        $this->entityManager->persist($client);
        $this->entityManager->flush();

        $this->logger->info('Client started', [
            'mac' => $data['mac'],
            'ip' => $data['ip'],
            'ostype' => $data['ostype'],
            'osversion' => $data['osversion'],
            'agent_version' => $data['agent_version'],
        ]);

        return new JsonResponse([], Response::HTTP_OK);
    }

    #[Route('/opengnsys/rest/ogagent/stopped', methods: ['POST'])]
    public function agentStopped(Request $request): JsonResponse
    {
        $data = $request->toArray();
        $requiredFields = ['mac', 'ip', 'ostype', 'osversion'];

        foreach ($requiredFields as $field) {
            if (!isset($data[$field])) {
                return new JsonResponse(['message' => "Missing parameter: $field"], Response::HTTP_BAD_REQUEST);
            }
        }

        $client = $this->entityManager->getRepository(Client::class)->findOneBy(['mac' => $data['mac']]);
        if (!$client) {
            return new JsonResponse(['message' => 'Client not found'], Response::HTTP_NOT_FOUND);
        }

        $client->setStatus(ClientStatus::OFF);
        $this->entityManager->persist($client);
        $this->entityManager->flush();

        $this->logger->info('Client stopped', [
            'mac' => $data['mac'],
            'ip' => $data['ip'],
            'ostype' => $data['ostype'],
            'osversion' => $data['osversion'],
        ]);

        return new JsonResponse([], Response::HTTP_OK);
    }

    #[Route('/opengnsys/rest/ogagent/loggedin', methods: ['POST'])]
    public function agentLoggedIn(Request $request): JsonResponse
    {
        $data = $request->toArray();
        $requiredFields = ['ip', 'user', 'language', 'session', 'ostype', 'osversion'];

        foreach ($requiredFields as $field) {
            if (!isset($data[$field])) {
                return new JsonResponse(['message' => "Missing parameter: $field"], Response::HTTP_BAD_REQUEST);
            }
        }

        $client = $this->entityManager->getRepository(Client::class)->findOneBy(['ip' => $data['ip']]);
        if (!$client) {
            return new JsonResponse(['message' => 'Client not found'], Response::HTTP_NOT_FOUND);
        }

        switch ($data['ostype']) {
            case 'Linux':
                $client->setStatus(ClientStatus::LINUX_SESSION);
                break;
            case 'Windows':
                $client->setStatus(ClientStatus::WINDOWS_SESSION);
                break;
            case 'MacOS':
                $client->setStatus(ClientStatus::MACOS_SESSION);
                break;

            default:
                return new JsonResponse(['message' => 'Invalid status'], Response::HTTP_BAD_REQUEST);
        }

        $this->entityManager->persist($client);
        $this->entityManager->flush();

        $this->logger->info('Client logged in', [
            'ip' => $data['ip'],
            'user' => $data['user'],
            'language' => $data['language'],
            'session' => $data['session'],
            'ostype' => $data['ostype'],
            'osversion' => $data['osversion'],
        ]);

        return new JsonResponse([], Response::HTTP_OK);
    }

    #[Route('/opengnsys/rest/ogagent/loggedout', methods: ['POST'])]
    public function agentLoggedOut(Request $request): JsonResponse
    {
        $data = $request->toArray();
        $requiredFields = ['ip', 'user'];

        foreach ($requiredFields as $field) {
            if (!isset($data[$field])) {
                return new JsonResponse(['message' => "Missing parameter: $field"], Response::HTTP_BAD_REQUEST);
            }
        }

        $client = $this->entityManager->getRepository(Client::class)->findOneBy(['ip' => $data['ip']]);
        if (!$client) {
            return new JsonResponse(['message' => 'Client not found'], Response::HTTP_NOT_FOUND);
        }

        $status = $client->getStatus();

        switch ($status) {
            case ClientStatus::LINUX_SESSION:
                $client->setStatus(ClientStatus::LINUX);
                break;
            case ClientStatus::WINDOWS_SESSION:
                $client->setStatus(ClientStatus::WINDOWS);
                break;
            case ClientStatus::MACOS_SESSION:
                $client->setStatus(ClientStatus::MACOS);
                break;

            default:
                return new JsonResponse(['message' => 'Invalid status'], Response::HTTP_BAD_REQUEST);
        }

        $this->entityManager->persist($client);
        $this->entityManager->flush();

        $this->logger->info('Client logged out', [
            'ip' => $data['ip'],
            'user' => $data['user'],
            'status' => $status,
        ]);

        return new JsonResponse([], Response::HTTP_OK);
    }
}
