<?php

declare(strict_types=1);

namespace App\Controller\Admin;

use App\Entity\TagRebuildJob;
use App\Service\Admin\DocumentTagAdminService;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;

#[Route('/admin/documents')]
final class DocumentTagController extends AbstractController
{
    #[Route('/{id}/tags', name: 'admin_document_tags_edit', methods: ['GET'])]
    public function edit(string $id, DocumentTagAdminService $svc): Response
    {
        $id = trim($id);

        try {
            $data = $svc->getEditData($id);
        } catch (\Throwable $e) {
            $this->addFlash('danger', $this->buildSafeErrorMessage($e, 'Dokument-Tags konnten nicht geladen werden.'));

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

        return $this->render('admin/document_tags/edit.html.twig', [
            ...$data,
            ...$this->buildJobStatusViewData(),
        ]);
    }

    #[Route('/{id}/tags/save', name: 'admin_document_tags_save', methods: ['POST'])]
    public function save(string $id, Request $request, DocumentTagAdminService $svc): RedirectResponse
    {
        $id = trim($id);

        if (!$this->isCsrfTokenValid('admin_document_tags_save_' . $id, (string) $request->request->get('_token'))) {
            $this->addFlash('danger', 'Ungültiges CSRF-Token.');

            return $this->redirectToRoute('admin_document_tags_edit', ['id' => $id]);
        }

        try {
            $svc->saveTags($id, $this->normalizeStringList($request->request->all('tag_ids')));
            $this->addFlash('success', 'Tags wurden aktualisiert. Rebuild läuft im Hintergrund.');
        } catch (\Throwable $e) {
            $this->addFlash('danger', $this->buildSafeErrorMessage($e, 'Tags konnten nicht aktualisiert werden.'));
        }

        return $this->redirectToRoute('admin_document_tags_edit', ['id' => $id]);
    }

    #[Route('/tags/status', name: 'admin_tags_status', methods: ['GET'])]
    public function status(DocumentTagAdminService $svc): JsonResponse
    {
        $status = $svc->getLatestRebuildStatus();

        return $this->json([
            'status' => $status,
            'hasActiveJob' => $status === TagRebuildJob::STATUS_RUNNING
                || $status === TagRebuildJob::STATUS_QUEUED,
        ]);
    }

    /**
     * @param mixed $values
     * @return list<string>
     */
    private function normalizeStringList(mixed $values): array
    {
        if (!is_array($values)) {
            return [];
        }

        $normalized = [];

        foreach ($values as $value) {
            $value = trim((string) $value);

            if ($value === '') {
                continue;
            }

            $normalized[] = $value;
        }

        return array_values(array_unique($normalized));
    }

    /**
     * @return array<string, string>
     */
    private function buildJobStatusViewData(): array
    {
        return [
            'statusRunning' => TagRebuildJob::STATUS_RUNNING,
            'statusQueued' => TagRebuildJob::STATUS_QUEUED,
            'statusCompleted' => TagRebuildJob::STATUS_COMPLETED,
            'statusFailed' => TagRebuildJob::STATUS_FAILED,
        ];
    }

    private function buildSafeErrorMessage(\Throwable $e, string $fallback): string
    {
        $message = trim($e->getMessage());

        return $message !== '' ? $message : $fallback;
    }
}