<?php

namespace App\Controller\Admin;

use App\Entity\Tenant\Author;
use App\Entity\Tenant\Category;
use App\Entity\Tenant\News;
use App\Entity\Tenant\Tag;
use App\Service\LicenseEnforcementService;
use Doctrine\ORM\EntityManagerInterface;
use Knp\Component\Pager\PaginatorInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\String\Slugger\SluggerInterface;

class NewsController extends AbstractController
{
    public function __construct(
        private readonly EntityManagerInterface $entityManager,
        private readonly PaginatorInterface $paginator,
        private readonly SluggerInterface $slugger,
        private readonly LicenseEnforcementService $enforcementService,
    ) {}

    #[Route('/news', name: 'admin_news_index')]
    public function index(Request $request): Response
    {
        $qb = $this->entityManager->getRepository(News::class)
            ->createQueryBuilder('n')
            ->leftJoin('n.category', 'c')
            ->addSelect('c')
            ->leftJoin('n.author', 'a')
            ->addSelect('a')
            ->orderBy('n.createdAt', 'DESC');

        $status = $request->query->get('status');
        if ($status) {
            $qb->andWhere('n.status = :status')->setParameter('status', $status);
        }

        $search = $request->query->get('q');
        if ($search) {
            $qb->andWhere('n.title LIKE :search')->setParameter('search', '%' . $search . '%');
        }

        $pagination = $this->paginator->paginate(
            $qb,
            $request->query->getInt('page', 1),
            20
        );

        // Get news limit info for the list page header
        $newsLimit = $this->enforcementService->checkNewsLimit();

        return $this->render('admin/news/index.html.twig', [
            'pagination' => $pagination,
            'currentStatus' => $status,
            'searchQuery' => $search,
            'newsLimit' => $newsLimit,
        ]);
    }

    #[Route('/news/create', name: 'admin_news_create', methods: ['GET', 'POST'])]
    public function create(Request $request): Response
    {
        // Check news limit before showing the form or processing
        $newsLimit = $this->enforcementService->checkNewsLimit();

        if ($request->isMethod('POST')) {
            // Re-check limit on POST
            if (!$newsLimit->allowed) {
                $this->addFlash('error', $newsLimit->message);
                return $this->redirectToRoute('admin_news_index');
            }

            if (!$this->isCsrfTokenValid('news_form', $request->request->get('_token'))) {
                $this->addFlash('error', 'Gecersiz CSRF token. Lutfen tekrar deneyin.');
                return $this->redirectToRoute('admin_news_create');
            }

            $news = new News();
            $this->handleFormData($news, $request);

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

            $this->addFlash('success', 'Haber basariyla olusturuldu.');
            return $this->redirectToRoute('admin_news_index');
        }

        // If limit reached, redirect with warning on GET request
        if (!$newsLimit->allowed) {
            $this->addFlash('error', $newsLimit->message);
            return $this->redirectToRoute('admin_news_index');
        }

        $categories = $this->entityManager->getRepository(Category::class)
            ->findBy(['status' => 'active'], ['title' => 'ASC']);

        $authors = $this->entityManager->getRepository(Author::class)
            ->findBy(['isActive' => true], ['name' => 'ASC']);

        return $this->render('admin/news/form.html.twig', [
            'news' => null,
            'categories' => $categories,
            'authors' => $authors,
            'newsLimit' => $newsLimit,
        ]);
    }

    #[Route('/news/{id}/edit', name: 'admin_news_edit', methods: ['GET', 'POST'])]
    public function edit(int $id, Request $request): Response
    {
        $news = $this->entityManager->getRepository(News::class)->find($id);
        if (!$news) {
            throw $this->createNotFoundException('Haber bulunamadi.');
        }

        if ($request->isMethod('POST')) {
            if (!$this->isCsrfTokenValid('news_form', $request->request->get('_token'))) {
                $this->addFlash('error', 'Gecersiz CSRF token. Lutfen tekrar deneyin.');
                return $this->redirectToRoute('admin_news_edit', ['id' => $id]);
            }

            $this->handleFormData($news, $request);
            $this->entityManager->flush();

            $this->addFlash('success', 'Haber basariyla guncellendi.');
            return $this->redirectToRoute('admin_news_index');
        }

        $categories = $this->entityManager->getRepository(Category::class)
            ->findBy(['status' => 'active'], ['title' => 'ASC']);

        $authors = $this->entityManager->getRepository(Author::class)
            ->findBy(['isActive' => true], ['name' => 'ASC']);

        $newsLimit = $this->enforcementService->checkNewsLimit();

        return $this->render('admin/news/form.html.twig', [
            'news' => $news,
            'categories' => $categories,
            'authors' => $authors,
            'newsLimit' => $newsLimit,
        ]);
    }

    #[Route('/news/{id}/delete', name: 'admin_news_delete', methods: ['POST'])]
    public function delete(int $id, Request $request): Response
    {
        $news = $this->entityManager->getRepository(News::class)->find($id);
        if (!$news) {
            throw $this->createNotFoundException('Haber bulunamadi.');
        }

        if ($this->isCsrfTokenValid('delete_news_' . $id, $request->request->get('_token'))) {
            $this->entityManager->remove($news);
            $this->entityManager->flush();
            $this->addFlash('success', 'Haber basariyla silindi.');
        } else {
            $this->addFlash('error', 'Gecersiz CSRF token. Silme islemi gerceklestirilemedi.');
        }

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

    #[Route('/news/{id}/toggle-highlight', name: 'admin_news_toggle_highlight', methods: ['POST'])]
    public function toggleHighlight(int $id, Request $request): JsonResponse
    {
        $news = $this->entityManager->getRepository(News::class)->find($id);
        if (!$news) {
            return new JsonResponse(['success' => false, 'error' => 'Haber bulunamadi.'], 404);
        }

        $field = $request->request->get('field');
        $allowedFields = ['isBreaking', 'isFeatured', 'isHeadline', 'isEditorsPick'];

        if (!in_array($field, $allowedFields, true)) {
            return new JsonResponse(['success' => false, 'error' => 'Gecersiz alan.'], 400);
        }

        $getter = $field === 'isBreaking' ? 'isBreaking' : ($field === 'isFeatured' ? 'isFeatured' : ($field === 'isHeadline' ? 'isHeadline' : 'isEditorsPick'));
        $setter = 'set' . ucfirst($field);

        $currentValue = $news->$getter();
        $news->$setter(!$currentValue);

        $this->entityManager->flush();

        return new JsonResponse([
            'success' => true,
            'field' => $field,
            'value' => !$currentValue,
        ]);
    }

    private function handleFormData(News $news, Request $request): void
    {
        $data = $request->request;

        $title = trim((string) $data->get('title', ''));
        $news->setTitle($title);

        $slug = trim((string) $data->get('slug', ''));
        if ($slug === '') {
            $slug = (string) $this->slugger->slug($title)->lower();
        }
        $news->setSlug($slug);

        $news->setSpot($data->get('spot') ?: null);
        $news->setContent($data->get('content') ?: null);

        // Dosya yukleme kontrolu
        /** @var UploadedFile|null $uploadedFile */
        $uploadedFile = $request->files->get('featured_image_file');
        if ($uploadedFile && $uploadedFile->isValid()) {
            $uploadDir = $this->getParameter('kernel.project_dir') . '/public/uploads/news';
            if (!is_dir($uploadDir)) {
                mkdir($uploadDir, 0777, true);
            }
            $filename = time() . '_' . $this->slugger->slug(pathinfo($uploadedFile->getClientOriginalName(), PATHINFO_FILENAME))->lower() . '.' . $uploadedFile->guessExtension();
            $uploadedFile->move($uploadDir, $filename);
            $news->setFeaturedImage('/uploads/news/' . $filename);
        } else {
            $featuredImage = $data->get('featured_image') ?: null;
            // Mevcut gorseli silme - bos birakildiysa ve onceki deger varsa koruyalim
            if ($featuredImage !== null) {
                $news->setFeaturedImage($featuredImage);
            }
        }
        $news->setImageCaption($data->get('image_caption') ?: null);
        $news->setVideoUrl($data->get('video_url') ?: null);
        $news->setVideoEmbed($data->get('video_embed') ?: null);

        $categoryId = $data->get('category_id');
        if ($categoryId) {
            $category = $this->entityManager->getRepository(Category::class)->find((int) $categoryId);
            $news->setCategory($category);
        } else {
            $news->setCategory(null);
        }

        $authorId = $data->get('author_id');
        if ($authorId) {
            $author = $this->entityManager->getRepository(Author::class)->find((int) $authorId);
            $news->setAuthor($author);
        } else {
            $news->setAuthor(null);
        }

        $this->handleTags($news, (string) $data->get('tags', ''));

        $news->setSource($data->get('source') ?: null);
        $news->setSourceUrl($data->get('source_url') ?: null);

        $previousStatus = $news->getId() ? $news->getStatus() : 'draft';
        $newStatus = $data->get('status', 'draft');
        $news->setStatus($newStatus);

        if ($newStatus === 'published' && $previousStatus !== 'published' && $news->getPublishedAt() === null) {
            $news->setPublishedAt(new \DateTimeImmutable());
        }

        $scheduledAtStr = $data->get('scheduled_at');
        if ($scheduledAtStr) {
            try {
                $news->setScheduledAt(new \DateTimeImmutable($scheduledAtStr));
            } catch (\Exception) {
                $news->setScheduledAt(null);
            }
        } else {
            $news->setScheduledAt(null);
        }

        $news->setIsBreaking((bool) $data->get('is_breaking', false));
        $news->setIsFeatured((bool) $data->get('is_featured', false));
        $news->setIsHeadline((bool) $data->get('is_headline', false));
        $news->setIsEditorsPick((bool) $data->get('is_editors_pick', false));
        $news->setAllowComments((bool) $data->get('allow_comments', false));
        $news->setShowInAmp((bool) $data->get('show_in_amp', false));

        $news->setSeoTitle($data->get('seo_title') ?: null);
        $news->setSeoDescription($data->get('seo_description') ?: null);
        $news->setFocusKeyword($data->get('focus_keyword') ?: null);
        $news->setSeoScore((int) $data->get('seo_score', 0));
        $news->setCanonicalUrl($data->get('canonical_url') ?: null);
        $news->setRobotsMeta($data->get('robots_meta', 'index,follow') ?: 'index,follow');
    }

    private function handleTags(News $news, string $tagsString): void
    {
        foreach ($news->getTags()->toArray() as $existingTag) {
            $news->removeTag($existingTag);
        }

        if (trim($tagsString) === '') {
            return;
        }

        $tagNames = array_filter(array_map('trim', explode(',', $tagsString)));
        $tagRepo = $this->entityManager->getRepository(Tag::class);

        foreach ($tagNames as $tagName) {
            if ($tagName === '') {
                continue;
            }

            $tag = $tagRepo->findOneBy(['name' => $tagName]);

            if (!$tag) {
                $tag = new Tag();
                $tag->setName($tagName);
                $tag->setSlug((string) $this->slugger->slug($tagName)->lower());
                $this->entityManager->persist($tag);
            }

            $news->addTag($tag);
        }
    }
}
