<?php

namespace App\Controller;

use App\Manager\FileSystemManager;
use App\Repository\ChapterRepository;
use App\Repository\MangaRepository;
use App\Service\CbrToCbzConverter;
use App\Service\CbzService;
use App\Service\MangaImportService;
use App\Service\NotificationService;
use Exception;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\File\Exception\FileException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\String\Slugger\SluggerInterface;

class ImportController extends AbstractController
{
    public function __construct(
        private readonly FileSystemManager   $fileSystemManager,
        private readonly CbzService          $cbzService,
        private readonly MangaImportService  $mangaImportService,
        private readonly NotificationService $notificationService,
        private readonly MangaRepository     $mangaRepository,
        private readonly CbrToCbzConverter   $cbrToCbzConverter
    ) {

    }

    #[Route('/manga/import', name: 'app_manga_import')]
    public function index(Request $request, SessionInterface $session): Response
    {
        if ($request->isMethod('POST')) {
            $files = $request->files->get('files');
            if ($files) {
                $importFiles = [];
                foreach ($files as $file) {
                    if ($file && in_array($file->getClientOriginalExtension(), ['cbz', 'cbr'])) {
                        $originalFileName = $file->getClientOriginalName();

                        try {
                            $tmpPath = $this->fileSystemManager->moveUploadedFile(
                                $file->getPathname(),
                                $this->fileSystemManager->getUploadsDirectory(),
                                $file->getClientOriginalName()
                            );
                            $importFiles[] = [
                                'id' => uniqid(),
                                'path' => $tmpPath,
                                'original_name' => $originalFileName,
                            ];
                        } catch (FileException $e) {
                            $this->notificationService->sendUpdate([
                                'status' => 'error',
                                'message' => 'Une erreur est survenue lors de l\'import du fichier ' . $originalFileName,
                            ]);
                        }
                    } else {
                        $this->notificationService->sendUpdate([
                            'status' => 'error',
                            'message' => 'Le fichier ' . $file->getClientOriginalName() . ' doit être au format CBZ ou CBR.',
                        ]);
                    }
                }

                if (!empty($importFiles)) {
                    $session->set('import_files', $importFiles);
                    return $this->redirectToRoute('import_match');
                }
            } else {
                $this->notificationService->sendUpdate([
                    'status' => 'error',
                    'message' => 'Aucun fichier n\'a été sélectionné.',
                ]);
            }
        }

        return $this->render('import/index.html.twig');
    }

    /**
     * @throws Exception
     */
    #[Route('/import/match', name: 'import_match')]
    public function match(SessionInterface $session): Response
    {
        $files = $session->get('import_files', []);
        if (empty($files)) {
            return $this->redirectToRoute('app_manga_import');
        }

        $processedFiles = [];
        foreach ($files as $fileId => $fileInfo) {
            $filePath = $fileInfo['path'];
            $originalFileName = $fileInfo['original_name'];

            $fileExtension = pathinfo($filePath, PATHINFO_EXTENSION);
            if (strtolower($fileExtension) === 'cbr') {
                $cbzPath = $this->cbrToCbzConverter->convert($filePath);
                $filePath = $cbzPath;
                $originalFileName = pathinfo($originalFileName, PATHINFO_FILENAME) . '.cbz';
                $files[$fileId]['path'] = $filePath;
                $files[$fileId]['original_name'] = $originalFileName;
            }

            $metadata = $this->cbzService->extractMetadata($filePath, $originalFileName);
            $mangas = $this->mangaRepository->findBySlug($metadata['title']);

            $mangaOptions = [];
            foreach ($mangas as $manga) {
                $mangaOptions[] = [
                    'slug' => $manga->getSlug(),
                    'title' => $manga->getTitle(),
                    'author' => $manga->getAuthor(),
                    'publicationYear' => $manga->getPublicationYear(),
                    'genres' => $manga->getGenres(),
                    'description' => $manga->getDescription()
                ];
            }

            $processedFiles[] = [
                'id' => $fileId,
                'originalFileName' => $originalFileName,
                'fileSize' => $this->formatBytes(filesize($filePath)),
                'metadata' => $metadata,
                'mangaOptions' => $mangaOptions
            ];
        }

        $session->set('import_files', $files);

        return $this->render('import/match.html.twig', [
            'files' => $processedFiles
        ]);
    }

    private function formatBytes($bytes, $precision = 2)
    {
        $units = ['B', 'KB', 'MB', 'GB', 'TB'];
        $bytes = max($bytes, 0);
        $pow = floor(($bytes ? log($bytes) : 0) / log(1024));
        $pow = min($pow, count($units) - 1);
        $bytes /= (1 << (10 * $pow));
        return round($bytes, $precision) . ' ' . $units[$pow];
    }

    #[Route('/import/confirm', name: 'import_confirm', methods: ['POST'])]
    public function confirm(Request $request, SessionInterface $session): Response
    {
        $files = $session->get('import_files', []);
        $selectedFiles = $request->request->all('selected');
        $mangaSlugs = $request->request->all('manga_slug');
        $volumes = $request->request->all('volume');
        $chapters = $request->request->all('chapter');

        $importedFiles = [];
        $errors = [];

        foreach ($selectedFiles as $fileId) {
            if (!isset($files[$fileId])) {
                continue;
            }

            $file = $files[$fileId];
            $mangaSlug = $mangaSlugs[$fileId] ?? null;
            $volume = $volumes[$fileId] ?? null;
            $chapter = $chapters[$fileId] ?? null;

            try {
                $manga = $this->mangaRepository->findOneBy(['slug' => $mangaSlug]);
                if (!$manga) {
                    throw new \Exception('Manga non trouvé.');
                }

                if (!is_null($chapter)) {
                    $chapter = $manga->getChapterByNumber($chapter);
                    if (!$chapter) {
                        throw new \Exception('Chapitre non trouvé.');
                    }
                }

                $importedFiles[] = $file['original_name'];
                $this->mangaImportService->importFile($manga, $volume, $chapter, $file['path']);
            } catch (\Exception $e) {
                $errors[] = "Erreur lors de l'import de {$file['original_name']} : " . $e->getMessage();
            }
        }

        // Nettoyer les fichiers temporaires non importés
        foreach ($files as $file) {
            $this->fileSystemManager->deleteFile($file['path']);
        }

        // Nettoyer la session
        $session->remove('import_files');

        // Préparer le message de notification
        if (!empty($importedFiles)) {
            $successMessage = 'Fichiers importés avec succès : ' . implode(', ', $importedFiles);
            $this->notificationService->sendUpdate([
                'status' => 'success',
                'message' => $successMessage
            ]);
        }

        if (!empty($errors)) {
            $errorMessage = implode("\n", $errors);
            $this->notificationService->sendUpdate([
                'status' => 'error',
                'message' => $errorMessage
            ]);
        }

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