<?php

namespace App\Controller;

use App\Entity\MemberCase;
use App\Entity\Messages;
use App\Entity\StaffNote;
use App\Entity\Supervision;
use App\Entity\User;
use App\Entity\UserCase;
use App\Factory\MessageFactory;
use App\Form\StaffNoteFormType;
use App\Form\SupervisorStaffNoteFormType;
use App\Libs\Breadcrumb;
use App\Libs\Libs;
use App\Libs\NavList;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Attribute\CurrentUser;

class StaffController extends AbstractController
{
    /**
     * Variable to store unread notification messages
     *
     * @var array <int, Message>
     */
    private array $msgs;

    public function __construct(
        private readonly EntityManagerInterface $entityManager,
        private array $navLinks = []
    ) {
        $this->navLinks = NavList::LIST;
        $this->navLinks['staff_dashboard'] = NavList::PRESENT_LINK;
    }

    #[Route('/staff-dashboard', name: 'app_staff_dashboard')]
    public function staffDashboard(#[CurrentUser()] User $user): Response
    {
        $this->msgs = Libs::getMessages($user, $this->entityManager);

        $sups = $this->entityManager->getRepository(Supervision::class)->findBy(['supervisor' => $user]);
        $staff = [];

        foreach ($sups as $sup) {
            $staff[] = $sup->getWorker();
        }

        return $this->render(
            'internal/staff/staff-dashboard.html.twig',
            array_merge(
                $this->navLinks,
                [
                    'staff' => $staff,
                    'breadcrumbs' => [
                        new Breadcrumb('', 'Staff Dashboard')
                    ],
                    'notifications' => $this->msgs,
                ]
            )
        );
    }

    #[Route('/staff/my-cases', name:'app_staff_my_cases')]
    public function staffMyCases(#[CurrentUser()] User $user): Response
    {
        if (!$this->isGranted('IS_AUTHENTICATED_FULLY')) {
            return $this->redirectToRoute('app_login');
        }
        $this->navLinks['staff_dashboard'] = NavList::DEFAULT;
        $this->navLinks['staff_notes'] = NavList::PRESENT_LINK;
        $this->msgs = Libs::getMessages($user, $this->entityManager);

        $sup = $this->entityManager->getRepository(Supervision::class)->findOneBy(['worker' => $user]);
        $ucs = $this->entityManager->getRepository(UserCase::class)->findBy(['user' => $user]);
        $cases = [];
        $this->navLinks['staff_dashboard'] = 'nav-link text-dark';
        $this->navLinks['staff_notes'] = NavList::PRESENT_LINK;

        foreach ($ucs as $uc) {
            $cases[] = $uc->getMemberCase();
        }

        return $this->render(
            'internal/staff/cases/my-cases.html.twig',
            array_merge(
                $this->navLinks,
                [
                    'cases' => $cases,
                    'user' => $user,
                    'supervisor' => $sup->getSupervisor(),
                    'breadcrumbs' => [
                        new Breadcrumb($this->generateUrl('app_staff_dashboard'), 'Staff Dashboard'),
                        new Breadcrumb('', 'Staff Cases')
                    ],
                    'notifications' => $this->msgs,
                ]
            )
        );
    }

    #[Route('/staff/{staffId}', name: 'app_staff_cases')]
    public function staffCases(string $staffId, #[CurrentUser()] User $user): Response
    {
        if (!$this->isGranted('IS_AUTHENTICATED_FULLY')) {
            return $this->redirectToRoute('app_login');
        }
        $this->msgs = Libs::getMessages($user, $this->entityManager);

        $staff = $this->entityManager->getRepository(User::class)->find($staffId);
        $ucs = $this->entityManager->getRepository(UserCase::class)->findBy(['user' => $staff]);
        $cases = [];

        foreach ($ucs as $case) {
            /** @var UserCase $case */
            $cases[] = $case->getMemberCase();
        }

        return $this->render(
            'internal/staff/cases/staff-cases.html.twig',
            array_merge(
                $this->navLinks,
                [
                    'staffId' => $staffId,
                    'cases' => $cases,
                    'breadcrumbs' => [
                        new Breadcrumb($this->generateUrl('app_staff_dashboard'), 'Staff Dashboard'),
                        new Breadcrumb('', 'Staff Cases')
                    ],
                    'notifications' => $this->msgs,
                ]
            )
        );
    }

    #[Route('/staff/{staffId}/case/{caseId}/list-notes', name: 'app_staff_list_notes')]
    public function staffListNotes(string $staffId, string $caseId, #[CurrentUser()] User $user): Response
    {
        if (!$this->isGranted('IS_AUTHENTICATED_FULLY')) {
            return $this->redirectToRoute('app_login');
        }
        $this->msgs = Libs::getMessages($user, $this->entityManager);
        $this->navLinks['staff_dashboard'] = NavList::DEFAULT;
        $this->navLinks['staff_notes'] = NavList::PRESENT_LINK;

        $isWorker = ($staffId == $user->getId()->toString());
        $staff = $this->entityManager->getRepository(User::class)->find($staffId);
        $case = $this->entityManager->getRepository(MemberCase::class)->find($caseId);
        $staffNotes = $this->entityManager->getRepository(StaffNote::class)->getOrderedNotes($case);

        return $this->render(
            'internal/staff/notes/list-notes.html.twig',
            array_merge(
                $this->navLinks,
                [
                    'isWorker' => $isWorker,
                    'staffId' => $staffId,
                    'staff' => $staff,
                    'case' => $case,
                    'staffNotes' => $staffNotes,
                    'breadcrumbs' => [
                        new Breadcrumb($this->generateUrl('app_staff_dashboard'), 'Staff Dashboard'),
                        new Breadcrumb(
                            $this->generateUrl(
                                ($staffId == $user->getId()->toHex() ? 'app_staff_my_cases' : 'app_staff_cases'),
                                ['staffId' => $staffId]
                            ),
                            ($staffId == $user->getId()->toHex() ? 'My Cases' : 'Staff Cases')
                        ),
                        new Breadcrumb('', 'List Notes')
                    ],
                    'notifications' => $this->msgs,
                ]
            )
        );
    }

    #[Route('/staff/add-note/{caseId}', name: 'app_staff_add_note')]
    public function addNote(string $caseId, #[CurrentUser()] User $user, Request $request): Response
    {
        if (!$this->isGranted('IS_AUTHENTICATED_FULLY')) {
            return $this->redirectToRoute('app_login');
        }
        $this->msgs = Libs::getMessages($user, $this->entityManager);
        $this->navLinks['staff_dashboard'] = NavList::DEFAULT;
        $this->navLinks['staff_notes'] = NavList::PRESENT_LINK;

        $case = $this->entityManager->getRepository(MemberCase::class)->find($caseId);
        $form = $this->createForm(StaffNoteFormType::class);
        $this->navLinks['staff_dashboard'] = 'nav-link text-dark';
        $this->navLinks['staff_notes'] = NavList::PRESENT_LINK;

        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            /** @var StaffNote $note */
            $note = $form->getData();
            $note->setMemberCase($case);

            /** @var Supervision $sup */
            $sup = $this->entityManager->getRepository(Supervision::class)->findOneBy(['worker' => $user]);

            $msg = MessageFactory::createStaffing($user, $sup->getSupervisor());
            $this->entityManager->persist($note);
            $this->entityManager->persist($msg);
            $this->entityManager->flush();

            $msg->setLink("/staff/sup-sign-note/" . $note->getId());
            $this->entityManager->persist($msg);
            $this->entityManager->flush();

            $this->addFlash('info', 'Staff note added');

            return $this->redirectToRoute(
                'app_staff_list_notes',
                [
                    'staffId' => $user->getId()->toString(),
                    'caseId' => $caseId
                ]
            );
        }

        return $this->render(
            'internal/staff/notes/add-note.html.twig',
            array_merge(
                $this->navLinks,
                [
                    'case' => $case,
                    'form' => $form,
                    'breadcrumbs' => [
                        new Breadcrumb($this->generateUrl('app_staff_dashboard'), 'Staff Dashboard'),
                        new Breadcrumb($this->generateUrl('app_staff_list_notes', ['staffId' => $user->getId()->toHex(), 'caseId' => $caseId]), 'My Cases'),
                        new Breadcrumb('', 'Add Note'),
                    ],
                    'notifications' => $this->msgs,
                ]
            )
        );
    }

    #[Route('/staff/edit-note/{noteId}', name: 'app_staff_edit_note')]
    public function editNote(string $noteId, #[CurrentUser()] User $user, Request $request): Response
    {
        if (!$this->isGranted('IS_AUTHENTICATED_FULLY')) {
            return $this->redirectToRoute('app_login');
        }
        $this->msgs = Libs::getMessages($user, $this->entityManager);
        $this->navLinks['staff_dashboard'] = NavList::DEFAULT;
        $this->navLinks['staff_notes'] = NavList::PRESENT_LINK;

        $note = $this->entityManager->getRepository(StaffNote::class)->find($noteId);
        $case = $note->getMemberCase();

        if ($note->getSupervisorSignDateTime() || $note->getWorkerSignDateTime()) {
            $this->addFlash('error', 'This note has already been signed');
            return $this->redirectToRoute('app_staff_view_note', ['noteId' => $noteId]);
        }

        $form = $this->createForm(StaffNoteFormType::class, $note);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $this->entityManager->flush();

            $this->addFlash('info', 'Staff notes updated');

            $this->redirectToRoute('app_staff_list_notes', ['staffId' => $user->getId()->toString(), 'caseId' => $case->getId()->toString()]);
        }

        return $this->render(
            'internal/staff/notes/edit-note.html.twig',
            array_merge(
                $this->navLinks,
                [
                    'form' => $form,
                    'note' => $note,
                    'breadcrumbs' => [
                        new Breadcrumb($this->generateUrl('app_staff_my_cases'), 'My Cases'),
                        new Breadcrumb($this->generateUrl('app_staff_list_notes', ['staffId' => $user->getId()->toString(), 'caseId' => $case->getId()->toString()]), 'Case Notes'),
                        new Breadcrumb('', 'Edit Note'),
                    ],
                    'notifications' => $this->msgs,
                ]
            )
        );
    }

    #[Route('/staff/sign-my-note/{noteId}', name: 'app_staff_sign_my_note')]
    public function signNote(string $noteId, #[CurrentUser()] User $user, Request $request): Response
    {
        if (!$this->isGranted('IS_AUTHENTICATED_FULLY')) {
            return $this->redirectToRoute('app_login');
        }
        $this->msgs = Libs::getMessages($user, $this->entityManager);
        $this->navLinks['staff_dashboard'] = NavList::DEFAULT;
        $this->navLinks['staff_notes'] = NavList::PRESENT_LINK;

        $note = $this->entityManager->getRepository(StaffNote::class)->find($noteId);
        $case = $note->getMemberCase();

        if (!$note->getSupervisorSignDateTime()) {
            $this->addFlash('error', 'Your supervisor has not signed this note');

            return $this->redirectToRoute('app_staff_list_notes', ['staffId' => $user->getId()->toString(), 'caseId' => $case->getId()->toString()]);
        }

        $form = $this->createForm(StaffNoteFormType::class, $note);

        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $note->setWorkerSignDateTime(new \DateTimeImmutable());

            $this->entityManager->flush();

            $this->addFlash('info', 'Staff notes signed and saved');

            $this->redirectToRoute('app_staff_list_notes', ['staffId' => $user->getId()->toString(), 'caseId' => $case->getId()->toString()]);
        }

        return $this->render(
            'internal/staff/notes/sign-note.html.twig',
            array_merge(
                $this->navLinks,
                [
                    'form' => $form,
                    'note' => $note,
                    'breadcrumbs' => [
                        new Breadcrumb($this->generateUrl('app_staff_my_cases'), 'My Cases'),
                        new Breadcrumb($this->generateUrl('app_staff_list_notes', ['staffId' => $user->getId()->toString(), 'caseId' => $case->getId()->toString()]), 'Case Notes'),
                        new Breadcrumb('', 'Sign Note'),
                    ],
                    'notifications' => $this->msgs,
                ]
            )
        );
    }

    #[Route('/staff/sup-sign-note/{noteId}', name: 'app_staff_sign_worker_note')]
    public function supSignNote(string $noteId, #[CurrentUser()] User $user, Request $request): Response
    {
        if (!$this->isGranted('IS_AUTHENTICATED_FULLY')) {
            return $this->redirectToRoute('app_login');
        }
        $this->msgs = Libs::getMessages($user, $this->entityManager);

        $note = $this->entityManager->getRepository(StaffNote::class)->find($noteId);
        $case = $note->getMemberCase();

        $form = $this->createForm(SupervisorStaffNoteFormType::class, $note);

        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $note->setSupervisorSignDateTime(new \DateTimeImmutable());

            /** @var UserCase $uc */
            $uc = $this->entityManager->getRepository(UserCase::class)->findOneBy(['memberCase' => $case]);

            $msg = MessageFactory::createSupervisorSignStaffNote($user, $uc->getUser(), $case);
            $msg->setLink('/staff/sign-my-note/' . $note->getId());
            $this->entityManager->persist($msg);
            $this->entityManager->flush();

            $this->addFlash('info', 'Staff notes signed and saved');

            $this->redirectToRoute('app_staff_list_notes', ['staffId' => $user->getId()->toString(), 'caseId' => $case->getId()->toString()]);
        }

        return $this->render(
            'internal/staff/notes/sup-sign-note.html.twig',
            array_merge(
                $this->navLinks,
                [
                    'form' => $form,
                    'note' => $note,
                    'breadcrumbs' => [
                        new Breadcrumb($this->generateUrl('app_staff_my_cases'), 'Staff Dashboard'),
                        new Breadcrumb($this->generateUrl('app_staff_cases', ['staffId' => $user->getId()->toString()]), 'Cases'),
                        new Breadcrumb($this->generateUrl('app_staff_list_notes', ['staffId' => $user->getId()->toString(), 'caseId' => $case->getId()->toString()]), 'Case Notes'),
                        new Breadcrumb('', 'Sign Note'),
                    ],
                    'notifications' => $this->msgs,
                ]
            )
        );
    }

    #[Route('/staff/view/{noteId}', name: 'app_staff_view_note')]
    public function viewNote(string $noteId, #[CurrentUser()] User $user): Response
    {
        if (!$this->isGranted('IS_AUTHENTICATED_FULLY')) {
            return $this->redirectToRoute('app_login');
        }
        $this->msgs = Libs::getMessages($user, $this->entityManager);
        $this->navLinks['staff_dashboard'] = NavList::DEFAULT;
        $this->navLinks['staff_notes'] = NavList::PRESENT_LINK;

        $note = $this->entityManager->getRepository(StaffNote::class)->find($noteId);

        return $this->render(
            'internal/staff/notes/view-note.html.twig',
            array_merge(
                $this->navLinks,
                [
                    'note' => $note,
                    'breadcrumbs' => [
                        new Breadcrumb($this->generateUrl('app_staff_my_cases'), 'My Cases'),
                        new Breadcrumb($this->generateUrl('app_staff_list_notes', ['staffId' => $user->getId()->toString(), 'caseId' => $note->getMemberCase()->getId()->toString()]), 'Case Notes'),
                        new Breadcrumb('', 'View Note'),
                    ],
                    'notifications' => $this->msgs,
                ]
            )
        );
    }
}
