<?php

namespace App\Controller\Blog;

use App\Core\Controller\Admin\Crud\CrudController;
use App\Core\Crud\CrudConfiguration;
use App\Core\Crud\Field\DatetimeField;
use App\Core\Crud\Field\TextField;
use App\Core\Form\FileUploadHandler;
use App\Core\Manager\EntityManager;
use App\Entity\Blog\Post as Entity;
use App\Factory\Blog\PostFactory as EntityFactory;
use App\Form\Blog\Filter\PostFilterType;
use App\Form\Blog\PostType;
use App\Form\Blog\PostType as EntityType;
use App\Repository\Blog\PostRepositoryQuery as RepositoryQuery;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Form\Form;
use App\Core\Entity\EntityInterface;
use App\Entity\Blog\Post;
use App\Analytic\DateRangeAnalytic;
use App\Core\Repository\Site\NodeRepository;

/**
 * @Route("/admin/blog/post")
 */
class PostAdminController extends CrudController
{
    public function getConfiguration(): CrudConfiguration
    {
        return CrudConfiguration::create()
            ->setPageTitle('index', 'Articles')
            ->setPageTitle('new', 'Nouvel article')
            ->setPageTitle('edit', '{title}')
            ->setPageTitle('show', '{title}')

            ->setPageRoute('index', 'admin_blog_post_index')
            ->setPageRoute('edit', 'admin_blog_post_edit')
            ->setPageRoute('new', 'admin_blog_post_new')
            ->setPageRoute('show', 'admin_blog_post_show')
            ->setPageRoute('delete', 'admin_blog_post_delete')
            ->setPageRoute('filter', 'admin_blog_post_filter')
            ->setPageRoute('batch', 'admin_blog_post_batch')
            ->setPageRoute('fetch_quick_data', 'admin_blog_post_fetch_quick_data')
            ->setPageRoute('analytic_stats', 'admin_blog_post_analytic_stats')

            ->setForm('new', PostType::class, [])
            ->setForm('edit', PostType::class, [])
            ->setForm('filter', PostFilterType::class, [])

            ->setView('show_entity', 'blog/post_admin/_show.html.twig')
            ->setView('form', 'blog/post_admin/_form.html.twig')
            ->setView('edit', 'blog/post_admin/edit.html.twig')
            ->setView('show', 'blog/post_admin/show.html.twig')
            ->setView('index', 'blog/post_admin/index.html.twig')

            ->setDefaultSort('index', 'id', 'desc')
            ->setField('index', 'Titre', TextField::class, [
                'view' => 'blog/post_admin/field/title.html.twig',
                'sort' => ['title', '.title'],
                'attr' => ['class' => 'miw-400'],
            ])
            ->setField('index', 'ID', TextField::class, [
                'property_builder' => function(EntityInterface $entity) {
                    return sprintf('#%d', $entity->getId());
                },
                'sort' => ['id', '.id'],
                'attr' => ['class' => 'miw-90'],
            ])
            ->setField('index', 'Mise à jour', DatetimeField::class, [
                'property' => 'updatedAt',
                'format' => 'd/m/Y H:i',
                'sort' => ['updatedAt', '.updatedAt'],
                'attr' => ['class' => 'miw-200'],
            ])
            ->setField('index', 'Publié le', DatetimeField::class, [
                'property' => 'publishedAt',
                'format' => 'd/m/Y H:i',
                'sort' => ['publishedAt', '.publishedAt'],
                'attr' => ['class' => 'miw-200'],
            ])
            ->setField('index', 'Status', TextField::class, [
                'view' => 'blog/post_admin/field/status.html.twig',
                'sort' => ['status', '.status'],
                'attr' => ['class' => 'miw-100'],
            ])
            ->setBatchAction('index', 'delete', 'Delete', function(EntityInterface $entity, EntityManager $manager) {
                $manager->delete($entity);
            })
            ->setBatchAction('index', 'draft', 'Statut : publier', function(EntityInterface $entity, EntityManager $manager) {
                $manager->update($entity->setStatus(Post::PUBLISHED));
            })
            ->setBatchAction('index', 'publish', 'Statut : brouillon', function(EntityInterface $entity, EntityManager $manager) {
                $manager->update($entity->setStatus(Post::DRAFT));
            })
        ;
    }

    /**
     * @Route("/{page}", name="admin_blog_post_index", requirements={"page": "\d+"})
     */
    public function index(RepositoryQuery $query, Request $request, Session $session, int $page = 1): Response
    {
        return $this->doIndex($page, $query, $request, $session);
    }

    /**
     * @Route("/new", name="admin_blog_post_new")
     */
    public function new(EntityFactory $factory, EntityManager $entityManager, FileUploadHandler $fileUpload, Request $request): Response
    {
        return $this->doNew(
            $factory->create($this->getUser()),
            $entityManager,
            $request,
            function(Entity $entity, Form $form, Request $request) use ($fileUpload) {
                $directory = 'uploads/post/'.date('Y');

                $fileUpload->handleForm(
                    $form->get('image')->getData(),
                    $directory,
                    function ($filename) use ($entity, $directory) {
                        $entity->setImage($directory.'/'.$filename);
                    }
                );
            }
        );
    }

    /**
     * @Route("/edit/{entity}", name="admin_blog_post_edit")
     */
    public function edit(Entity $entity, EntityManager $entityManager, FileUploadHandler $fileUpload, Request $request): Response
    {
        return $this->doEdit(
            $entity,
            $entityManager,
            $request,
            function(Entity $entity, Form $form, Request $request) use ($fileUpload) {
                $directory = 'uploads/post/'.date('Y');

                $fileUpload->handleForm(
                    $form->get('image')->getData(),
                    $directory,
                    function ($filename) use ($entity, $directory) {
                        $entity->setImage($directory.'/'.$filename);
                    }
                );
            }
        );
    }

    /**
     * @Route("/show/{entity}", name="admin_blog_post_show")
     */
    public function show(Entity $entity): Response
    {
        return $this->doShow($entity);
    }

    /**
     * @Route("/admin/blog_post/batch/{page}", name="admin_blog_post_batch", methods={"POST"}, requirements={"page":"\d+"})
     */
    public function batch(RepositoryQuery $query, EntityManager $entityManager, Request $request, Session $session, int $page = 1): Response
    {
        return $this->doBatch($page, $query, $entityManager, $request, $session);
    }

    /**
     * @Route("/fetch_quick_data/{entity}", name="admin_blog_post_fetch_quick_data")
     */
    public function fetchQuickData(Entity $entity, EntityManager $entityManager): Response
    {
        $configuration = $this->getConfiguration();

        if (!$entity->getIsQuick()) {
            $this->addFlash('warning', 'L\'article n\'est pas Quick');
        } else {
            try {
                $query = '?'.http_build_query(['url' => $entity->getQuickUrl()]);

                $apiOpengraph = 'https://api-page.deblan.org/do/opengraph'.$query;
                $apiGraby = 'https://api-page.deblan.org/do/graby'.$query;

                $opengraph = json_decode(file_get_contents($apiOpengraph), true);
                $graby = json_decode(file_get_contents($apiGraby), true);

                if (!$entity->getTitle()) {
                    $entity->setTitle($opengraph['title'] ?? $graby['title'] ?? null);
                }

                if (!$entity->getContent()) {
                    $entity->setContent($opengraph['description'] ?? $graby['summary'] ?? null);
                }

                $entity
                    ->setQuickImage($opengraph['images'][0]['url'] ?? $graby['image'] ?? null)
                    ->setQuickVideo($opengraph['videos'][0]['url'] ?? null)
                    ->setQuickVideoWidth($opengraph['videos'][0]['width'] ?? null)
                    ->setQuickVideoHeight($opengraph['videos'][0]['height'] ?? null)
                ;

                $entityManager->update($entity);

                $this->addFlash('success', 'The data has been saved.');
            } catch (\Exception $e) {
                $this->addFlash('error', 'Une erreur s\'est produite');
            }
        }

        return $this->redirectToRoute($configuration->getPageRoute('edit'), [
            'entity' => $entity->getId(),
        ]);
    }

    /**
     * @Route("/filters", name="admin_blog_post_filter")
     */
    public function filter(Session $session): Response
    {
        return $this->doFilter($session);
    }

    /**
     * @Route("/delete/{entity}", name="admin_blog_post_delete", methods={"DELETE"})
     */
    public function delete(Entity $entity, EntityManager $entityManager, Request $request): Response
    {
        return $this->doDelete($entity, $entityManager, $request);
    }

    /**
     * @Route("/analytic_stats/{entity}/{range}", name="admin_blog_post_analytic_stats")
     */
    public function stats(
        Entity $entity,
        DateRangeAnalytic $analytic,
        NodeRepository $nodeRepository,
        string $range = '7days'
    ): Response
    {
        if (!in_array($range, ['7days', '30days', '90days', '1year'])) {
            throw $this->createNotFoundException();
        }

        $node = $nodeRepository->findOneBy([
            'code' => 'post',
        ]);

        $analytic
            ->setDateRange(new \DateTime('now - '.$range), new \DateTime())
            ->setPath($this->generateUrl('blog_menu_post', [
                'post' => $entity->getId(),
                'slug' => '-',
            ]))
            ->setNode($node)
        ;

        return $this->render('blog/post_admin/stats.html.twig', [
            'range' => $range,
            'views' => $analytic->getViews(),
            'pathViews' => $analytic->getPathViews(),
            'node' => $node,
            'entity' => $entity,
        ]);
    }

    public function getSection(): string
    {
        return 'blog_post';
    }
}
