<?php

namespace App\Controller;

use App\Entity\CaseItinerary;
use App\Entity\User;
use App\Libs\Breadcrumb;
use App\Libs\Libs;
use App\Libs\NavList;
use DateInterval;
use DateTime;
use DateTimeInterface;
use DateTimeZone;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TelType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Attribute\CurrentUser;
use Symfony\Component\String\Slugger\SluggerInterface;

class DefaultController extends AbstractController
{
    public function __construct(
        private readonly EntityManagerInterface $entityManager,
        private readonly UserPasswordHasherInterface $userPasswordHasher,
        private array $navLinks = []
    ) {
        $this->navLinks = NavList::LIST;
    }

    #[Route('/dashboard', name: 'app_dashboard')]
    public function dashboard(Request $request, #[CurrentUser()] ?User $user): Response
    {
        $this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY');
        
        if (!$user->getCompany()) {
            return $this->redirectToRoute('app_register_step', ['step' => RegistrationController::REGISTER_STEP_TWO]);
        }

        $oldPasswordDate = new DateTime('now', new DateTimeZone($_ENV['COMPANY_TIMEZONE']));
        $oldPasswordDate->sub(DateInterval::createFromDateString('120 days'));

        if (is_a($user->getPasswordChanged(), DateTimeInterface::class) && $user->getPasswordChanged() < $oldPasswordDate) {
            $this->addFlash('danger', 'You must change your password');
            return $this->redirectToRoute('app_profile');
        }

        if($_SERVER['HTTP_REFERER'] == "{$_SERVER['HTTP_X_FORWARDED_PROTO']}://{$_SERVER['HTTP_HOST']}/") {
            $this->entityManager->getRepository(User::class)->updateLastLogin($user);
        }

        $ytdtravel = $this->entityManager->getRepository(CaseItinerary::class)->getYTDTravel($user);
        $last30days = $this->entityManager->getRepository(CaseItinerary::class)->getTravelLast30Days($user);
        $ytdMiles = 0;
        $milesTravelled30Days = 0;
        $caseMileageYTD = 0;
        $caseMileage30Days = 0;
        $totalTimeTravelledYTD = new DateInterval('PT0S');
        $totalTimeTravelled30Days = new DateInterval('PT0S');

        if ($ytdtravel) {
            $timeTravelled = new DateTime('00:00:00');
            $timeTravelYTDStart = new DateTime('00:00:00');
            foreach ($ytdtravel as $travel) {
                /** @var CaseItinerary $travel */
                $ytdMiles += $travel->getDistance();
                $timeTravelled->add($travel->getDuration());

                if ($travel->isCaseMileage()) {
                    $caseMileageYTD += $travel->getDistance();
                }
            }

            $totalTimeTravelledYTD = $timeTravelled->diff($timeTravelYTDStart);
        }

        if ($last30days) {
            $timeTravelled30Days = new DateTime('00:00:00');
            $timeTravel30DaysStart = new DateTime('00:00:00');
            foreach ($last30days as $travel) {
                /** @var CaseItinerary $travel */
                $milesTravelled30Days += $travel->getDistance();
                $timeTravelled30Days->add($travel->getDuration());

                if ($travel->isCaseMileage()) {
                    $caseMileage30Days += $travel->getDistance();
                }
            }

            $totalTimeTravelled30Days = $timeTravelled30Days->diff($timeTravel30DaysStart);
        }

        $activeCases = 0;
        $totalCases = 0;
        foreach ($user->getUserCases() as $uc) {
            $totalCases++;
            if (!$uc->getMemberCase()->getCloseDate()) {
                $activeCases++;
            }
        }

        $this->navLinks['user_dashboard'] = NavList::PRESENT_LINK;

        return $this->render(
            'internal/dashboard.html.twig',
            array_merge(
                $this->navLinks,
                [
                    'breadcrumbs' => [
                        new Breadcrumb('', 'Dashboard')
                    ],
                    'notifications' => Libs::getMessages($user, $this->entityManager),
                    'milesTravelledYTD' => $ytdMiles,
                    'milesTravelled30Days' => $milesTravelled30Days,
                    'totalTimeTravelledYTD' => $totalTimeTravelledYTD,
                    'totalTimeTravelled30Days' => $totalTimeTravelled30Days,
                    'activeCases' => $activeCases,
                    'totalCases' => $totalCases,
                    'caseMileageYTD' => $caseMileageYTD,
                    'caseMileage30Days' => $caseMileage30Days,
                ]
            )
        );
    }

    #[Route('/profile', name: 'app_profile')]
    public function profile(
        Request $request,
        #[CurrentUser()] User $user,
        SluggerInterface $slugger
    ): Response {
        $this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY');
        
        $this->navLinks['profile'] = NavList::PRESENT_LINK;

        $form = $this->createFormBuilder($user)
            ->add('name', TextType::class, [
                'label' => 'Name',
                'label_attr' => ['class' => 'form-label'],
                'attr' => ['class' => 'form-control'],
            ])
            ->add('email', EmailType::class, [
                'label' => 'Email',
                'label_attr' => ['class' => 'form-label'],
                'attr' => ['class' => 'form-control'],
            ])
            ->add('password', RepeatedType::class, [
                'type' => PasswordType::class,
                'invalid_message' => 'The password fields must match.',
                'required' => false,
                'mapped' => false,
                'first_options'  => ['label' => 'Password', 'label_attr' => ['class' => 'form-label']],
                'second_options' => ['label' => 'Repeat Password', 'label_attr' => ['class' => 'form-label']],
            ])
            ->add('personalPhone', TelType::class, [
                'label' => 'Personal Phone',
            ])
            ->add('workPhone', TelType::class, [
                'label' => 'Work Phone',
            ])
            ->add('imageName', FileType::class, [
                'label' => 'Profile Picture',
                'required' => false,
                'mapped' => false
            ])
            ->add('signature', HiddenType::class)
            ->add('submit', SubmitType::class, [
                'label' => 'Save Profile',
                'attr' => ['class' => 'btn btn-lg bg-gradient-dark btn-lg w-100 mt-4 mb-0']
            ])
            ->getForm()
        ;

        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            if ($form->get('signature')->getData()) {
                $signature = $form->get('signature')->getData();
                $user->setSignature($signature);
            }

            $firstPassword = $form->get('password')['first']->getData();
            $secondPassword = $form->get('password')['second']->getData();

            if ($firstPassword !== $secondPassword) {
                $this->addFlash('danger', 'The password fields must match.');
                return $this->redirectToRoute('app_profile');
            }

            $plainPassword = $form->get('password')['first']->getData();

            if ($plainPassword) {
                $user->setPassword(
                    $this->userPasswordHasher->hashPassword(
                        $user,
                        $plainPassword
                    )
                );
                $user->setPasswordChanged(new DateTime('now', new DateTimeZone($_ENV['COMPANY_TIMEZONE'])));
            }

            if ($form['imageName']->getData()) {
                /** @var \Symfony\Component\HttpFoundation\File\UploadedFile $file */
                $file = $form['imageName']->getData();
                $destination = $this->getParameter('kernel.project_dir').'/public/uploads/user_images/';

                if (!file_exists($destination)) {
                    mkdir($destination, 0775);
                }

                $originalFilename = pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME);
                $newFilename = $slugger->slug($originalFilename).'-'.uniqid().'.'.$file->guessExtension();
                $file->move(
                    $destination,
                    $newFilename
                );

                $user->setImageName($newFilename);
            }

            if ($form['personalPhone']->getData()) {
                $phone = Libs::Phone($form['personalPhone']->getData());
                $user->setPersonalPhone($phone);
            }

            if ($form['workPhone']->getData()) {
                $phone = Libs::Phone($form['workPhone']->getData());
                $user->setWorkPhone($phone);
            }

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

            return $this->redirectToRoute('app_dashboard');
        } elseif ($form->isSubmitted() && !$form->isValid()) {
            $this->addFlash('danger', 'The form contains errors.');
        }

        return $this->render(
            'internal/profile.html.twig',
            array_merge(
                $this->navLinks,
                [
                    'breadcrumbs' => [
                        new Breadcrumb('', 'Profile')
                    ],
                    'notifications' => Libs::getMessages($user, $this->entityManager),
                    'currentUser' => $user,
                    'signaturePresent' => ($user->getSignature() ? true : false),
                    'signature' => $user->getSignature(),
                    'form' => $form->createView(),
                ]
            )
        );
    }

    #[Route('/uploads/user_images/{imageName}', name: 'app_user_profile_image')]
    public function displayUserImage(string $imageName): Response
    {
        return new BinaryFileResponse("{$this->getParameter('kernel.project_dir')}/public/{$_ENV['USER_IMAGE_PATH']}/{$imageName}");
    }

    #[Route('/uploads/company_images/{companyLogo}', name: 'app_company_logo')]
    public function displayCompanyLogo(string $companyLogo): Response
    {
        return new BinaryFileResponse("{$this->getParameter('kernel.project_dir')}/public/{$_ENV['COMPANY_IMAGE_PATH']}/{$companyLogo}");
    }
}
