<?php

namespace App\Controller\Admin;

use App\Entity\Service;
use App\Entity\ServiceCategory;
use App\Entity\ServiceMessage;
use App\Entity\User;
use App\Repository\ServiceCategoryRepository;
use App\Repository\ServiceRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;
use Symfony\Component\String\Slugger\SluggerInterface;

#[Route('/admin/status', name: 'app_admin_status_')]
#[IsGranted('ROLE_ROOT')]
class StatusController extends AbstractController
{
    #[Route('', name: 'index')]
    public function index(ServiceCategoryRepository $categoryRepository, ServiceRepository $serviceRepository, EntityManagerInterface $em): Response
    {
        $categories = $categoryRepository->findBy([], ['position' => 'ASC']);

        $servicesData = [];
        foreach ($categories as $category) {
            $categoryData = [
                'category' => $category,
                'services' => [],
            ];

            foreach ($category->getServices() as $service) {
                $history = $serviceRepository->getHistoryForDays($service, 30);
                $dailyStatus = $serviceRepository->getDailyStatus($service, 30);
                $uptime = $service->computeUptimeRatio($history, 30);

                $categoryData['services'][] = [
                    'service' => $service,
                    'uptime' => $uptime,
                    'dailyStatus' => $dailyStatus,
                ];
            }

            $servicesData[] = $categoryData;
        }

        $activeMessages = $em->getRepository(ServiceMessage::class)->findBy(
            ['isActive' => true],
            ['createdAt' => 'DESC'],
        );

        $allServices = $serviceRepository->findBy([], ['name' => 'ASC']);

        return $this->render('admin/status/index.html.twig', [
            'servicesData' => $servicesData,
            'activeMessages' => $activeMessages,
            'allServices' => $allServices,
        ]);
    }

    #[Route('/manage', name: 'manage')]
    public function manage(ServiceCategoryRepository $categoryRepository): Response
    {
        $categories = $categoryRepository->findBy([], ['position' => 'ASC']);

        return $this->render('admin/status/manage.html.twig', [
            'categories' => $categories,
        ]);
    }

    #[Route('/category/create', name: 'category_create', methods: ['POST'])]
    public function categoryCreate(Request $request, EntityManagerInterface $em, SluggerInterface $slugger): Response
    {
        $name = trim($request->request->getString('name'));

        if ('' === $name) {
            $this->addFlash('error', 'Le nom de la categorie est requis.');

            return $this->redirectToRoute('app_admin_status_manage');
        }

        $slug = strtolower($slugger->slug($name)->toString());
        $category = new ServiceCategory($name, $slug);
        $category->setPosition($request->request->getInt('position', 0));

        $em->persist($category);
        $em->flush();

        $this->addFlash('success', 'Categorie "'.$name.'" creee.');

        return $this->redirectToRoute('app_admin_status_manage');
    }

    #[Route('/category/{id}/delete', name: 'category_delete', methods: ['POST'])]
    public function categoryDelete(ServiceCategory $category, EntityManagerInterface $em): Response
    {
        $name = $category->getName();
        $em->remove($category);
        $em->flush();

        $this->addFlash('success', 'Categorie "'.$name.'" supprimee.');

        return $this->redirectToRoute('app_admin_status_manage');
    }

    #[Route('/service/create', name: 'service_create', methods: ['POST'])]
    public function serviceCreate(Request $request, EntityManagerInterface $em, ServiceCategoryRepository $categoryRepository, SluggerInterface $slugger): Response
    {
        $name = trim($request->request->getString('name'));
        $url = trim($request->request->getString('url'));
        $categoryId = $request->request->getInt('category_id');

        if ('' === $name || 0 === $categoryId) {
            $this->addFlash('error', 'Le nom et la categorie sont requis.');

            return $this->redirectToRoute('app_admin_status_manage');
        }

        $category = $categoryRepository->find($categoryId);
        if (null === $category) {
            $this->addFlash('error', 'Categorie introuvable.');

            return $this->redirectToRoute('app_admin_status_manage');
        }

        $externalType = trim($request->request->getString('external_type'));

        $slug = strtolower($slugger->slug($name)->toString());
        $service = new Service($name, $slug, $category);

        if ('' !== $url) {
            $service->setUrl($url);
        }

        if ('' !== $externalType) {
            $service->setIsExternal(true);
            $service->setExternalType($externalType);
        }

        $service->setPosition($request->request->getInt('position', 0));

        $em->persist($service);
        $em->flush();

        $this->addFlash('success', 'Service "'.$name.'" cree.');

        return $this->redirectToRoute('app_admin_status_manage');
    }

    #[Route('/service/{id}/delete', name: 'service_delete', methods: ['POST'])]
    public function serviceDelete(Service $service, EntityManagerInterface $em): Response
    {
        $name = $service->getName();
        $em->remove($service);
        $em->flush();

        $this->addFlash('success', 'Service "'.$name.'" supprime.');

        return $this->redirectToRoute('app_admin_status_manage');
    }

    #[Route('/{id}/update', name: 'update', methods: ['POST'])]
    public function update(Service $service, Request $request, EntityManagerInterface $em): Response
    {
        $status = $request->request->getString('status');
        $message = trim($request->request->getString('message'));

        if (!\in_array($status, Service::STATUSES, true)) {
            $this->addFlash('error', 'Statut invalide.');

            return $this->redirectToRoute('app_admin_status_index');
        }

        $service->setStatus($status, '' !== $message ? $message : null);
        $em->flush();

        $this->addFlash('success', 'Statut de "'.$service->getName().'" mis a jour.');

        return $this->redirectToRoute('app_admin_status_index');
    }

    #[Route('/message/create', name: 'message_create', methods: ['POST'])]
    public function messageCreate(Request $request, EntityManagerInterface $em, ServiceRepository $serviceRepository): Response
    {
        $serviceId = $request->request->getInt('service_id');
        $title = trim($request->request->getString('title'));
        $content = trim($request->request->getString('content'));
        $severity = $request->request->getString('severity', 'info');

        if (0 === $serviceId || '' === $title || '' === $content) {
            $this->addFlash('error', 'Tous les champs sont requis.');

            return $this->redirectToRoute('app_admin_status_index');
        }

        $service = $serviceRepository->find($serviceId);
        if (null === $service) {
            $this->addFlash('error', 'Service introuvable.');

            return $this->redirectToRoute('app_admin_status_index');
        }

        $user = $this->getUser();
        if (!$user instanceof User) {
            $user = null;
        }

        $message = new ServiceMessage($service, $title, $content, $severity, $user);
        $em->persist($message);
        $em->flush();

        $this->addFlash('success', 'Message ajoute sur "'.$service->getName().'".');

        return $this->redirectToRoute('app_admin_status_index');
    }

    #[Route('/message/{id}/resolve', name: 'message_resolve', methods: ['POST'])]
    public function messageResolve(ServiceMessage $message, EntityManagerInterface $em): Response
    {
        $message->resolve();
        $em->flush();

        $this->addFlash('success', 'Message resolu.');

        return $this->redirectToRoute('app_admin_status_index');
    }

    #[Route('/api/{id}/daily', name: 'api_daily', methods: ['GET'])]
    public function apiDaily(Service $service, ServiceRepository $serviceRepository): JsonResponse
    {
        return new JsonResponse($serviceRepository->getDailyStatus($service, 30));
    }
}
