<?php

namespace App\Domain\Manga\Infrastructure\Service;

use App\Domain\Manga\Domain\Contract\Service\FileServiceInterface;
use App\Domain\Manga\Domain\Exception\CbzFileNotFoundException;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;

readonly class FileService implements FileServiceInterface
{
    public function __construct(
        private string $cbzStoragePath = '/app/public/cbz'
    ) {
    }

    public function downloadCbz(string $filePath, string $filename): Response
    {
        if (!$this->cbzExists($filePath)) {
            throw new CbzFileNotFoundException($filePath);
        }

        $response = new BinaryFileResponse($filePath);
        $response->setContentDisposition(
            ResponseHeaderBag::DISPOSITION_ATTACHMENT,
            $filename
        );
        $response->headers->set('Content-Type', 'application/x-cbz');

        return $response;
    }

    public function createVolumeCbz(array $cbzPaths, string $volumeName): Response
    {
        $tempCbzPath = sys_get_temp_dir() . '/' . $volumeName . '.cbz';

        $cbz = new \ZipArchive();
        if ($cbz->open($tempCbzPath, \ZipArchive::CREATE) !== true) {
            throw new \RuntimeException('Cannot create CBZ file');
        }

        $imageCounter = 1;

        foreach ($cbzPaths as $cbzPath) {
            if (!$this->cbzExists($cbzPath)) {
                continue;
            }

            $sourceCbz = new \ZipArchive();
            if ($sourceCbz->open($cbzPath) !== true) {
                continue; // Skip if we can't open the CBZ
            }

            // Extract all images from the current CBZ
            for ($i = 0; $i < $sourceCbz->numFiles; $i++) {
                $fileName = $sourceCbz->getNameIndex($i);
                $fileInfo = $sourceCbz->statIndex($i);

                // Skip directories and non-image files
                if ($fileInfo['size'] === 0 || !$this->isImageFile($fileName)) {
                    continue;
                }

                // Get the file content
                $imageContent = $sourceCbz->getFromIndex($i);
                if ($imageContent === false) {
                    continue;
                }

                // Get file extension
                $extension = pathinfo($fileName, PATHINFO_EXTENSION);

                // Create a new filename with proper ordering
                $newFileName = sprintf('%04d.%s', $imageCounter, $extension);

                // Add the image to the volume CBZ
                $cbz->addFromString($newFileName, $imageContent);

                $imageCounter++;
            }

            $sourceCbz->close();
        }

        $cbz->close();

        $response = new BinaryFileResponse($tempCbzPath);
        $response->setContentDisposition(
            ResponseHeaderBag::DISPOSITION_ATTACHMENT,
            $volumeName . '.cbz'
        );
        $response->headers->set('Content-Type', 'application/x-cbz');

        // Clean up temp file after sending
        $response->deleteFileAfterSend();

        return $response;
    }

    private function isImageFile(string $fileName): bool
    {
        $imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'];
        $extension = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));

        return in_array($extension, $imageExtensions);
    }

    public function deleteCbzFile(string $filePath): bool
    {
        if (!$this->cbzExists($filePath)) {
            return false;
        }

        return unlink($filePath);
    }

    public function cbzExists(string $filePath): bool
    {
        return file_exists($filePath) && is_readable($filePath);
    }
}
