<?php

namespace App\Controller;

use App\Entity\CaseDocument;
use App\Entity\CaseLocation;
use App\Entity\CompanyDocument;
use App\Entity\Location;
use App\Entity\Member;
use App\Entity\MemberCase;
use App\Entity\MemberDocument;
use App\Entity\ReferralSource;
use App\Entity\User;
use App\Entity\UserCase;
use App\Factory\MessageFactory;
use App\Form\CaseDocumentFormType;
use App\Form\LocationFormType;
use App\Form\MemberCaseFormType;
use App\Form\UserCaseFormType;
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\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\Security\Http\Attribute\CurrentUser;

class CaseController extends AbstractController
{
    public function __construct(
        private EntityManagerInterface $entityManager,
        private array $navLinks = []
    ) {
        $this->navLinks = NavList::LIST;
        $this->navLinks['case_list'] = NavList::PRESENT_LINK;
    }

    #[Route('/my-cases', name: 'app_my_cases')]
    public function myCases(#[CurrentUser()] User $user, Request $request): Response
    {
        if (!$this->isGranted('IS_AUTHENTICATED_FULLY')) {
            return $this->redirectToRoute('app_login');
        }

        $this->navLinks['my_cases'] = NavList::PRESENT_LINK;
        $this->navLinks['case_list'] = NavList::DEFAULT;

        $ucs = $this->entityManager->getRepository(UserCase::class)->findBy(['user' => $user]);
        
        $cases = [];
        foreach ($ucs as $uc) {
            /** @var UserCase $uc */
            $cases[] = $uc->getMemberCase();
        }

        return $this->render(
            'internal/cases/my-cases.html.twig',
            array_merge(
                $this->navLinks,
                [
                    'breadcrumbs' => [
                        (
                            strpos($request->server->get('HTTP_REFERER'), 'list-cases') !== false
                                ? new Breadcrumb($this->generateUrl('app_list_cases'), 'Cases')
                                : new Breadcrumb($this->generateUrl('app_my_cases'), 'My Cases')
                        ),
                    ],
                    'notifications' => Libs::getMessages($user, $this->entityManager),
                    'cases' => $cases,
                ]
            )
        );
    }

    #[Route('/list-cases', name: 'app_list_cases')]
    public function listCases(#[CurrentUser()] User $user): Response
    {
        $this->denyAccessUnlessGranted('ROLE_ADMIN');

        $cases = $this->entityManager->getRepository(MemberCase::class)->findAll();
        $workers = $this->entityManager->getRepository(User::class)->getCaseWorkers();

        return $this->render(
            'internal/admin/cases/list-cases.html.twig',
            array_merge(
                $this->navLinks,
                [
                    'breadcrumbs' => [
                        new Breadcrumb($this->generateUrl('app_list_cases'), 'List Cases')
                    ],
                    'notifications' => Libs::getMessages($user, $this->entityManager),
                    'cases' => $cases,
                    'workers' => $workers,
                ]
            )
        );
    }

    #[Route('/case/{caseId}', name: 'app_view_case')]
    public function showCase(Request $request, #[CurrentUser()] User $user, string $caseId): Response
    {
        if (!$this->isGranted('IS_AUTHENTICATED_FULLY')) {
            return $this->redirectToRoute('app_login');
        }

        $case = $this->entityManager->getRepository(MemberCase::class)->find($caseId);

        /** @todo validate user has access to case, check for admin, case manager of case worker */
        if (!Libs::checkPermissions($user, $case, $this->entityManager)) {
            throw new AccessDeniedException();
        }

        $sources = $this->entityManager->getRepository(ReferralSource::class)->findAll();

        return $this->render(
            'internal/cases/view-case.html.twig',
            array_merge(
                $this->navLinks,
                [
                    'case' => $case,
                    'sources' => $sources,
                    'breadcrumbs' => [
                        new Breadcrumb($this->generateUrl('app_list_cases'), 'Cases'),
                        new Breadcrumb($this->generateUrl('app_view_case', ['caseId' => $case->getId()]), 'View Case')
                    ],
                    'notifications' => Libs::getMessages($user, $this->entityManager),
                ]
            )
        );
    }

    #[Route('/add-case', name: 'app_add_case')]
    public function addCase(Request $request, #[CurrentUser()] User $admin): Response
    {
        $this->denyAccessUnlessGranted('ROLE_ADMIN');

        $case = new MemberCase();
        $form = $this->createForm(MemberCaseFormType::class);

        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $case = $form->getData();

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

            $this->addFlash('success', 'Case added successfully');

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

        return $this->render(
            'internal/admin/cases/add-case.html.twig',
            array_merge(
                $this->navLinks,
                [
                    'title' => 'Add Case',
                    'breadcrumbs' => [
                        new Breadcrumb($this->generateUrl('app_list_cases'), 'List Cases'),
                        new Breadcrumb($this->generateUrl('app_add_case'), 'Add Case')
                    ],
                    'notifications' => Libs::getMessages($admin, $this->entityManager),
                    'form' => $form,
                    'sources' => $this->entityManager->getRepository(ReferralSource::class)->retrieveOrderedList(),
                ]
            )
        );
    }

    #[Route('/edit-case/{id}', name: 'app_edit_case')]
    public function editCase(Request $request, #[CurrentUser()] User $admin, string $id): Response
    {
        $this->denyAccessUnlessGranted('ROLE_ADMIN');

        $case = $this->entityManager->getRepository(MemberCase::class)->find($id);
        $form = $this->createForm(MemberCaseFormType::class, $case);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $case = $form->getData();

            $this->entityManager->flush();

            $this->addFlash('success', 'Case updated successfully');

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

        return $this->render(
            'internal/admin/cases/edit-case.html.twig',
            array_merge(
                $this->navLinks,
                [
                    'title' => 'Edit Case',
                    'breadcrumbs' => [
                        new Breadcrumb($this->generateUrl('app_list_cases'), 'List Cases'),
                        new Breadcrumb($this->generateUrl('app_edit_case', ['id' => $id]), 'Edit Case')
                    ],
                    'notifications' => Libs::getMessages($admin, $this->entityManager),
                    'form' => $form,
                    'case' => $case,
                    'sources' => $this->entityManager->getRepository(ReferralSource::class)->retrieveOrderedList(),
                ]
            )
        );
    }

    #[Route('/assign-case/{id}', name: 'app_assign_case')]
    public function assignCase(string $id, Request $request, #[CurrentUser()] User $admin): Response
    {
        $this->denyAccessUnlessGranted('ROLE_ADMIN');

        $caseWorkers = $this->entityManager->getRepository(User::class)->getCaseWorkers();
        $case = $this->entityManager->getRepository(MemberCase::class)->find($id);
        $prevUc = $this->entityManager->getRepository(UserCase::class)->findBy(['memberCase' => $case]);

        $uc = new UserCase();
        $form = $this->createForm(UserCaseFormType::class, $uc);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $user = $form->get('user')->getData();
            $uc = $form->getData();
            $uc->setMemberCase($case);
            $uc->setUser($user);

            if (count($prevUc) > 0) {
                $this->entityManager->remove($prevUc[0]);
                $this->entityManager->flush();
            }

            $msg = MessageFactory::createNewCase(
                $admin,
                $user,
                $this->generateUrl('app_view_case', ['caseId' => $case->getId()->toString()])
            );

            $this->entityManager->persist($uc);
            $this->entityManager->persist($msg);
            $this->entityManager->flush();

            $this->addFlash('success', 'Case assigned successfully');

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

        return $this->render(
            'internal/admin/cases/assign-case.html.twig',
            array_merge(
                $this->navLinks,
                [
                    'title' => 'Assign Case',
                    'breadcrumbs' => [
                        new Breadcrumb($this->generateUrl('app_list_cases'), 'List Cases'),
                        new Breadcrumb($this->generateUrl('app_assign_case', ['id' => $id]), 'Assign User')
                    ],
                    'notifications' => Libs::getMessages($admin, $this->entityManager),
                    'case' => $case,
                    'form' => $form,
                    'id' => $id,
                    'caseWorkers' => $caseWorkers,
                    'assignedWorkerId' => (count($case->getUserCases()) > 0 ? $case->getUserCases()->first()->getUser()->getId() : null),
                ]
            )
        );
    }

    #[Route('/addresses/list', name: 'app_list_case_addresses')]
    public function listCaseAddresses(Request $request, #[CurrentUser()] User $user): Response
    {
        $this->navLinks['case_itinerary'] = NavList::PRESENT_LINK;
        $this->navLinks['case_list'] = 'nav-link text-dark';

        $addresses = $this->entityManager->getRepository(Location::class)->getUserLocations($user);
        
        $ucs = $this->entityManager->getRepository(UserCase::class)->findBy(['user' => $user]);
        $cases = [];
        foreach ($ucs as $uc) {
            /** @var UserCase $uc */
            $cases[] = $uc->getMemberCase();
        }

        return $this->render(
            'internal/cases/addresses/list-case-addresses.html.twig',
            array_merge(
                $this->navLinks,
                [
                    'title' => 'List Case Addresses',
                    'breadcrumbs' => [
                        new Breadcrumb($this->generateUrl('app_my_cases'), 'My Cases'),
                        new Breadcrumb($this->generateUrl('app_list_case_addresses'), 'List Case Addresses')
                    ],
                    'notifications' => Libs::getMessages($user, $this->entityManager),
                    'addresses' => $addresses,
                    'cases' => $cases,
                ]
            )
        );
    }

    #[Route('/addresses/add', name: 'app_case_add_address')]
    public function addCaseAddress(Request $request, #[CurrentUser()] User $user): Response
    {
        $this->navLinks['case_itinerary'] = NavList::PRESENT_LINK;
        $this->navLinks['case_list'] = 'nav-link text-dark';

        $ucs = $this->entityManager->getRepository(UserCase::class)->findBy(['user' => $user]);

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

        $address = new Location();
        $form = $this->createForm(LocationFormType::class, $address);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            /** @var Location $address */
            $address = $form->getData();

            foreach ($request->get('cases') as $caseId) {
                $case = $this->entityManager->getRepository(MemberCase::class)->find($caseId);

                $cl = new CaseLocation();
                $cl->setMemberCase($case)
                   ->setLocation($address);

                $this->entityManager->persist($cl);
            }

            list($lat, $lon) = Libs::getLatLonFromGeoapify((string) $address);
            $address->setLat($lat)
                    ->setLon($lon);

            //dd($address);
            $this->entityManager->persist($address);
            $this->entityManager->flush();

            $this->addFlash('success', 'Address added successfully');

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

        return $this->render(
            'internal/cases/addresses/add-case-address.html.twig',
            array_merge(
                $this->navLinks,
                [
                    'title' => 'Add Case Address',
                    'breadcrumbs' => [
                        new Breadcrumb($this->generateUrl('app_list_case_addresses'), 'List Addresses'),
                        new Breadcrumb($this->generateUrl('app_case_add_address'), 'Add Case Address')
                    ],
                    'notifications' => Libs::getMessages($user, $this->entityManager),
                    'form' => $form,
                    'cases' => $cases,
                ]
            )
        );
    }

    #[Route('/addresses/edit/{id}', name: 'app_case_edit_address')]
    public function editCaseAddress(Request $request, string $id, #[CurrentUser()] User $user): Response
    {
        $this->navLinks['case_itinerary'] = NavList::PRESENT_LINK;
        $this->navLinks['case_list'] = 'nav-link text-dark';

        $ucs = $this->entityManager->getRepository(UserCase::class)->findBy(['user' => $this->getUser()]);
        $lcs = $this->entityManager->getRepository(CaseLocation::class)->findBy(['location' => $id]);

        $inCases = [];
        foreach ($lcs as $lc) {
            $inCases[] = $lc->getMemberCase()->getId()->toString();
        }

        $cases = [];
        foreach ($ucs as $uc) {
            /** @var UserCase $uc */
            $cases[] = $uc->getMemberCase();
        }
        $location = $this->entityManager->getRepository(Location::class)->find($id);
        $form = $this->createForm(LocationFormType::class, $location);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            list($lat, $lon) = Libs::getLatLonFromGeoapify((string) $location);
            $location->setLat($lat)
                     ->setLon($lon);

            $this->entityManager->flush();

            $this->addFlash('success', 'Address updated successfully');

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

        return $this->render(
            'internal/cases/addresses/edit-case-address.html.twig',
            array_merge(
                $this->navLinks,
                [
                    'title' => 'Edit Case Address',
                    'breadcrumbs' => [
                        new Breadcrumb($this->generateUrl('app_list_case_addresses'), 'List Case Addresses'),
                        new Breadcrumb($this->generateUrl('app_case_edit_address', ['id' => $id]), 'Edit Case Address')
                    ],
                    'location' => $location,
                    'cases' => $cases,
                    'inCases' => $inCases,
                    'form' => $form,
                    'notifications' => Libs::getMessages($user, $this->entityManager),
                ]
            )
        );
    }

    #[Route('/assign-case-doc/{caseId}/{memberId}', name: 'app_assign_case_documents')]
    public function assignCaseDocument(string $caseId, string $memberId, Request $request, #[CurrentUser()] User $user): Response
    {
        $case = $this->entityManager->getRepository(MemberCase::class)->find($caseId);
        $member = $this->entityManager->getRepository(Member::class)->find($memberId);
        $companyDocs = $this->entityManager->getRepository(CompanyDocument::class)->findBy(['company' => $user->getCompany()]);

        $form = $this->createForm(CaseDocumentFormType::class, null, ['docs' => $companyDocs]);

        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $docs = $form['document']->getData();
            dd($docs);

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

            $this->redirectToRoute('app_case_members', ['id' => $caseId]);
        }

        return $this->render(
            'internal/cases/members/assign-document.html.twig',
            array_merge(
                $this->navLinks,
                [
                    'notifications' => Libs::getMessages($user, $this->entityManager),
                    'breadcrumbs' => [
                        new Breadcrumb($this->generateUrl('app_dashboard'), 'Dashboard'),
                        new Breadcrumb($this->generateUrl('app_list_cases'), 'List Cases'),
                        new Breadcrumb($this->generateUrl('app_case_members', ['id' => $caseId]), 'Case Members')
                    ],
                    'form' => $form,
                    'case' => $case,
                    'member' => $member,
                    'docs' => $companyDocs,
                ]
            )
        );
    }
}
