<?php

declare(strict_types=1);

/*
 * This file is part of the Ferienpass package.
 *
 * (c) Richard Henkenjohann <richard@ferienpass.online>
 *
 * For more information visit the project website <https://ferienpass.online>
 * or the documentation under <https://docs.ferienpass.online>.
 */

namespace Ferienpass\AdminBundle\Controller\Page;

use Doctrine\ORM\EntityManagerInterface;
use Ferienpass\AdminBundle\Breadcrumb\Breadcrumb;
use Ferienpass\AdminBundle\Form\BrevoSmsConfigType;
use Ferienpass\AdminBundle\Form\EditAccessCodesType;
use Ferienpass\AdminBundle\Form\OfferCategoryType;
use Ferienpass\AdminBundle\Form\OpenAiConfigType;
use Ferienpass\AdminBundle\Form\PmPaymentConfigType;
use Ferienpass\AdminBundle\Routing\Base58;
use Ferienpass\CoreBundle\Entity\AccessCodeStrategy;
use Ferienpass\CoreBundle\Entity\OfferCategory;
use Ferienpass\CoreBundle\Entity\User;
use Ferienpass\CoreBundle\Facade\EraseDataFacade;
use Ferienpass\CoreBundle\Repository\AccessCodeStrategyRepository;
use Ferienpass\CoreBundle\Repository\HostConsentRepository;
use Ferienpass\CoreBundle\Repository\MessengerLogRepository;
use Ferienpass\CoreBundle\Repository\OfferCategoryRepository;
use Ferienpass\CoreBundle\Session\Flash;
use Ferienpass\CoreBundle\Settings\IntegrationsManager;
use Ferienpass\CoreBundle\Settings\PageConfigManager;
use FOS\HttpCacheBundle\Configuration\InvalidatePath;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\Form\Extension\Core\Type\FormType;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Routing\Requirement\Requirement;
use Symfony\Component\Security\Http\Attribute\CurrentUser;
use Symfony\Component\Security\Http\Attribute\IsGranted;
use Symfony\Component\String\Slugger\SluggerInterface;
use Symfony\Component\Uid\Uuid;
use Symfony\UX\Turbo\TurboBundle;

final class ToolsController extends AbstractController
{
    public function __construct(
        private readonly PageConfigManager $pageConfigManager,
        private readonly IntegrationsManager $integrationsManager,
    ) {
    }

    #[IsGranted('ROLE_ADMIN')]
    #[Route('/export', name: 'admin_export_index')]
    public function export(Breadcrumb $breadcrumb): Response
    {
        return $this->render('@FerienpassAdmin/page/tools/export.html.twig', [
            'breadcrumb' => $breadcrumb->generate('tools.title', 'export.title'),
        ]);
    }

    #[Route('/rundmail', name: 'admin_tools_mailing')]
    public function mailing(#[CurrentUser] User $user, Breadcrumb $breadcrumb, HostConsentRepository $consents, #[Autowire(param: 'ferienpass_admin.privacy_consent_text')] string $consentText): Response
    {
        if ('' !== $consentText && !$consents->findValid($user) instanceof \Ferienpass\CoreBundle\Entity\HostConsent) {
            return $this->render('@FerienpassAdmin/page/missing_privacy_statement.html.twig', [
                'breadcrumb' => $breadcrumb->generate('tools.title', 'mailing.title'),
            ]);
        }

        return $this->render('@FerienpassAdmin/page/tools/mailing.html.twig', [
            'breadcrumb' => $breadcrumb->generate('tools.title', 'mailing.title'),
        ]);
    }

    #[Route('/versand/{uuid}', name: 'admin_tools_dispatch', requirements: ['uuid' => Base58::UUID])]
    #[Route('/versand/{uuid}', name: 'admin_tools_dispatch_legacy', requirements: ['uuid' => Requirement::UUID])]
    public function dispatch(Uuid $uuid, MessengerLogRepository $messengerLogRepository, Breadcrumb $breadcrumb): Response
    {
        $log = $messengerLogRepository->findOneBy(['uuid' => $uuid]);
        if (null === $log) {
            throw $this->createNotFoundException();
        }

        return $this->render('@FerienpassAdmin/page/tools/dispatch.html.twig', [
            'log' => $log,
            'breadcrumb' => $breadcrumb->generate('dispatch.title'),
        ]);
    }

    #[Route('/betroffenenrechte', name: 'admin_tools_subjectrights')]
    #[IsGranted('ROLE_SUPER_ADMIN')]
    public function subjectRights(Breadcrumb $breadcrumb): Response
    {
        return $this->render('@FerienpassAdmin/page/tools/noop.html.twig', [
            'breadcrumb' => $breadcrumb->generate('tools.title', 'subjectrichts.title'),
        ]);
    }

    #[Route('/system', name: 'admin_tools_settings')]
    #[IsGranted('ROLE_SUPER_ADMIN')]
    public function settings(): Response
    {
        return $this->redirectToRoute('admin_tools_settings_general');
    }

    #[Route('/system/allgemein', name: 'admin_tools_settings_general')]
    #[IsGranted('ROLE_SUPER_ADMIN')]
    public function settingsGeneral(Breadcrumb $breadcrumb, OfferCategoryRepository $repository): Response
    {
        return $this->render('@FerienpassAdmin/page/tools/settings_general.html.twig', [
            'config' => $this->pageConfigManager->getPageConfig(),
            'categories' => $repository->findAll(),
            'breadcrumb' => $breadcrumb->generate('tools.title', 'settings.title', 'general.title'),
        ]);
    }

    #[Route('/system/angebotskategorien', name: 'admin_tools_settings_categories')]
    #[IsGranted('ROLE_SUPER_ADMIN')]
    public function settingsCategories(): Response
    {
        return $this->redirectToRoute('admin_tools_settings_general');
    }

    #[Route('/system/angebotskategorien/neu', name: 'admin_tools_settings_category_create')]
    #[Route('/system/angebotskategorien/{uuid}/bearbeiten', name: 'admin_tools_settings_category_edit', requirements: ['uuid' => Base58::UUID])]
    #[Route('/system/angebotskategorien/{uuid}/bearbeiten', name: 'admin_tools_settings_category_edit_legacy', requirements: ['uuid' => Requirement::UUID])]
    #[IsGranted('ROLE_SUPER_ADMIN')]
    public function settingsCategoryEdit(?Uuid $uuid, Request $request, EntityManagerInterface $entityManager, SluggerInterface $slugger, OfferCategoryRepository $offerCategoryRepository): Response
    {
        $category = null !== $uuid ? $offerCategoryRepository->findOneBy(['uuid' => $uuid]) : null;
        $isNew = null === $category;
        $category ??= new OfferCategory();
        $form = $this->createForm(OfferCategoryType::class, $category);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $category->generateAlias($slugger);
            $entityManager->persist($category);
            $entityManager->flush();

            if (TurboBundle::STREAM_FORMAT === $request->getPreferredFormat()) {
                $request->setRequestFormat(TurboBundle::STREAM_FORMAT);

                return $this->renderBlock('@FerienpassAdmin/page/tools/settings_category_edit.html.twig', 'category_saved_stream', [
                    'category' => $category,
                    'is_new' => $isNew,
                ]);
            }

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

        return $this->render('@FerienpassAdmin/page/tools/settings_category_edit.html.twig', [
            'form' => $form,
            'category' => $category,
        ]);
    }

    #[Route('/system/integrationen/{integration}/konfigurieren', name: 'admin_tools_settings_integration_configure')]
    #[IsGranted('ROLE_SUPER_ADMIN')]
    public function settingsIntegrationConfigure(string $integration, Request $request): Response
    {
        $config = $this->integrationsManager->getIntegrationConfig($integration) ?? [];

        $formType = match ($integration) {
            'PmPaymentProvider' => PmPaymentConfigType::class,
            'gpt_image_generation' => OpenAiConfigType::class,
            'brevo_sms' => BrevoSmsConfigType::class,
            default => throw $this->createNotFoundException(),
        };

        $formOptions = [];
        if ('gpt_image_generation' === $integration) {
            $formOptions['readonly_api_key'] = $this->integrationsManager->isOpenAiApiKeyFromEnv();
            $formOptions['has_api_key'] = isset($config['OPENAI_API_KEY']) && '' !== $config['OPENAI_API_KEY'];

            // Do not show the secret in the form
            if ($formOptions['has_api_key'] && !$formOptions['readonly_api_key']) {
                $config['OPENAI_API_KEY'] = '';
            }
        }

        if ('brevo_sms' === $integration) {
            // We don't have an env override for BREVO_API_KEY for SMS specifically in the manager yet,
            // but the user said "Brevo SMS (an api key)".
            $formOptions['readonly_api_key'] = false; // Add env check if needed later
            $formOptions['has_api_key'] = isset($config['BREVO_API_KEY']) && '' !== $config['BREVO_API_KEY'];

            if ($formOptions['has_api_key'] && !$formOptions['readonly_api_key']) {
                $config['BREVO_API_KEY'] = '';
            }
        }

        $form = $this->createForm($formType, $config, $formOptions);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $data = $form->getData();
            if ('gpt_image_generation' === $integration) {
                // Only save if a new key was provided
                if (isset($data['OPENAI_API_KEY']) && '' === $data['OPENAI_API_KEY']) {
                    unset($data['OPENAI_API_KEY']);
                }
            }
            if ('brevo_sms' === $integration) {
                if (isset($data['BREVO_API_KEY']) && '' === $data['BREVO_API_KEY']) {
                    unset($data['BREVO_API_KEY']);
                }
            }

            $this->integrationsManager->saveIntegrationConfig($integration, $data);

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

        return $this->render('@FerienpassAdmin/page/tools/settings_integration_configure.html.twig', [
            'form' => $form,
            'integration' => $integration,
        ]);
    }

    #[IsGranted('ROLE_SUPER_ADMIN')]
    #[Route('/postausgang', name: 'admin_outbox')]
    public function outbox(Breadcrumb $breadcrumb): Response
    {
        return $this->render('@FerienpassAdmin/page/tools/outbox.html.twig', [
            'breadcrumb' => $breadcrumb->generate('tools.title', 'outbox.title'),
        ]);
    }

    #[IsGranted('ROLE_SUPER_ADMIN')]
    #[Route('/daten-löschen', name: 'admin_erase_data')]
    public function eraseData(EraseDataFacade $eraseDataFacade, Breadcrumb $breadcrumb, Request $request): Response
    {
        $participants = $eraseDataFacade->expiredParticipants();

        $form = $this->createFormBuilder()->getForm();
        $form->handleRequest($request);
        if ($form->isSubmitted() && $form->isValid()) {
            $eraseDataFacade->eraseData();

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

        return $this->render('@FerienpassAdmin/page/tools/erase_data.html.twig', [
            'form' => $form,
            'participants' => $participants,
            'breadcrumb' => $breadcrumb->generate('tools.title', 'eraseData.title'),
        ]);
    }

    #[Route('/system/zugangscodes', name: 'admin_accessCodes_index')]
    public function accessCodes(Breadcrumb $breadcrumb, AccessCodeStrategyRepository $repository): Response
    {
        $qb = $repository->createQueryBuilder('i');

        $qb->addOrderBy('i.name', 'ASC');

        return $this->render('@FerienpassAdmin/page/tools/access_codes.html.twig', [
            'qb' => $qb,
            'createUrl' => $this->generateUrl('admin_accessCodes_create'),
            'breadcrumb' => $breadcrumb->generate('tools.title', 'settings.title', 'accessCodes.title'),
        ]);
    }

    #[Route('/einstellungen/zugangscodes/neu', name: 'admin_accessCodes_create')]
    #[Route('/einstellungen/zugangscodes/{uuid}/bearbeiten', name: 'admin_accessCodes_edit', requirements: ['uuid' => Base58::UUID])]
    #[Route('/einstellungen/zugangscodes/{uuid}/bearbeiten', name: 'admin_accessCodes_edit_legacy', requirements: ['uuid' => Requirement::UUID])]
    #[InvalidatePath('/admin/tools/einstellungen/zugangscodes')]
    public function edit(?Uuid $uuid, Request $request, EntityManagerInterface $em, Breadcrumb $breadcrumb, Flash $flash, FormScreenFactory $forms, AccessCodeStrategyRepository $accessCodeStrategyRepository): Response
    {
        $accessCodeStrategy = null !== $uuid ? $accessCodeStrategyRepository->findOneBy(['uuid' => $uuid]) : null;
        $accessCodeStrategy ??= new AccessCodeStrategy();
        $em->persist($accessCodeStrategy);

        $form = $this->createForm(EditAccessCodesType::class, $accessCodeStrategy);

        $form->handleRequest($request);
        if ($form->isSubmitted() && $form->isValid()) {
            $em->flush();

            $this->addFlash('success', 'Die Änderungen wurden erfolgreich übernommen.');

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

        $breadcrumbTitle = $accessCodeStrategy ? $accessCodeStrategy->getName().' (bearbeiten)' : 'accessCodes.new';

        /** @noinspection FormViewTemplate `createView()` messes ups error handling/redirect */
        return $this->render('@FerienpassAdmin/page/tools/access_codes_edit.html.twig', [
            'item' => $accessCodeStrategy,
            'form' => $form,
            'section' => $request->get('section', 'base'),
            'formOptions' => ['display_section' => $request->get('section', 'base')],
            'formScreen' => $forms->screen(EditAccessCodesType::class, $accessCodeStrategy),
            'breadcrumb' => $breadcrumb->generate('tools.title', 'settings.title', 'accessCodes.title', $breadcrumbTitle),
        ]);
    }

    #[Route('/einstellungen/zugangscodes/{uuid}/löschen', name: 'admin_accessCodes_delete', requirements: ['uuid' => Base58::UUID])]
    #[Route('/einstellungen/zugangscodes/{uuid}/löschen', name: 'admin_accessCodes_delete_legacy', requirements: ['uuid' => Requirement::UUID])]
    #[InvalidatePath('/admin/tools/einstellungen/zugangscodes')]
    public function delete(Uuid $uuid, Request $request, EntityManagerInterface $entityManager, AccessCodeStrategyRepository $accessCodeStrategyRepository): Response
    {
        $item = $accessCodeStrategyRepository->findOneBy(['uuid' => $uuid]);
        if (null === $item) {
            throw $this->createNotFoundException();
        }

        $this->denyAccessUnlessGranted('delete', $item);

        $form = $this->createForm(FormType::class, options: [
            'action' => $this->generateUrl('admin_accessCodes_delete', ['uuid' => $item->getUuid()->toBase58()]),
        ]);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $deletedId = $item->getId();

            $entityManager->remove($item);
            $entityManager->flush();

            if (TurboBundle::STREAM_FORMAT === $request->getPreferredFormat()) {
                // If the request comes from Turbo, set the content type as text/vnd.turbo-stream.html and only send the HTML to update
                $request->setRequestFormat(TurboBundle::STREAM_FORMAT);

                return $this->renderBlock('@FerienpassAdmin/page/tools/access_codes.html.twig', 'deleted_stream', ['id' => $deletedId]);
            }

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

        return $this->render('@FerienpassAdmin/page/tools/access_codes_delete.html.twig', [
            'item' => $item,
            'form' => $form,
        ]);
    }

    #[Route('/tools/problem-melden', name: 'admin_tools_issue')]
    #[IsGranted('ROLE_ADMIN')]
    public function createIssue(Breadcrumb $breadcrumb): Response
    {
        return $this->render('@FerienpassAdmin/page/tools/create_issue.html.twig', [
            'breadcrumb' => $breadcrumb->generate('tools.title', 'Ticket erstellen'),
        ]);
    }

    #[Route('/webstatistik', name: 'admin_webstats')]
    #[IsGranted('ROLE_ADMIN')]
    public function webstats(Breadcrumb $breadcrumb, #[Autowire(param: 'ferienpass_admin.plausible_shared_link')] string $plausibleSharedLink): Response
    {
        $iframeSrc = null;
        $embedScriptSrc = null;

        if ('' !== $plausibleSharedLink) {
            $iframeSrc = $plausibleSharedLink.(str_contains($plausibleSharedLink, '?') ? '&' : '?').'embed=true&theme=system&background=transparent';

            $host = parse_url($plausibleSharedLink, \PHP_URL_SCHEME).'://'.parse_url($plausibleSharedLink, \PHP_URL_HOST);
            $embedScriptSrc = $host.'/js/embed.host.js';
        }

        return $this->render('@FerienpassAdmin/page/tools/webstats.html.twig', [
            'breadcrumb' => $breadcrumb->generate('tools.title', 'Webstatistik'),
            'iframeSrc' => $iframeSrc,
            'embedScriptSrc' => $embedScriptSrc,
        ]);
    }

    #[Route('/unsaved-changes-modal', name: 'admin_unsaved_changes_modal')]
    public function unsavedChangesModal(Request $request): Response
    {
        $request->setRequestFormat(TurboBundle::STREAM_FORMAT);

        return $this->renderBlock('@FerienpassAdmin/layout/edit.html.twig', 'unsaved_changes_stream');
    }
}
