<?php

namespace App\Domain\Shared\Infrastructure\Service;

use App\Domain\Shared\Domain\Contract\ImageStorageInterface;
use ZipArchive;

class ImageStorageManager implements ImageStorageInterface
{
    public function __construct(private string $storagePath)
    {
    }

    public function storeChapterImages(string $targetId, array $localImagePaths): string
    {
        $targetDir = $this->storagePath . '/pages/' . $targetId;

        if (!is_dir($targetDir)) {
            mkdir($targetDir, 0755, true);
        }

        sort($localImagePaths);

        foreach ($localImagePaths as $index => $localPath) {
            $extension = pathinfo($localPath, PATHINFO_EXTENSION) ?: 'jpg';
            $targetFile = sprintf('%s/%03d.%s', $targetDir, $index + 1, $extension);
            copy($localPath, $targetFile);
        }

        return $targetDir;
    }

    public function extractFromCbz(string $targetId, string $cbzBinary): string
    {
        $targetDir = $this->storagePath . '/pages/' . $targetId;

        if (!is_dir($targetDir)) {
            mkdir($targetDir, 0755, true);
        }

        $tmpFile = tempnam(sys_get_temp_dir(), 'cbz_');
        file_put_contents($tmpFile, $cbzBinary);

        $zip = new ZipArchive();
        if ($zip->open($tmpFile) !== true) {
            unlink($tmpFile);
            throw new \RuntimeException('Failed to open CBZ file as ZIP archive');
        }

        $imageEntries = [];
        for ($i = 0; $i < $zip->numFiles; $i++) {
            $name = $zip->getNameIndex($i);
            if (preg_match('/\.(jpg|jpeg|png|webp|gif)$/i', $name)) {
                $imageEntries[] = ['index' => $i, 'name' => $name];
            }
        }

        usort($imageEntries, fn ($a, $b) => strcmp($a['name'], $b['name']));

        foreach ($imageEntries as $seq => $entry) {
            $extension = strtolower(pathinfo($entry['name'], PATHINFO_EXTENSION)) ?: 'jpg';
            $targetFile = sprintf('%s/%03d.%s', $targetDir, $seq + 1, $extension);
            $content = $zip->getFromIndex($entry['index']);
            file_put_contents($targetFile, $content);
        }

        $zip->close();
        unlink($tmpFile);

        return $targetDir;
    }

    public function countCbzImages(string $cbzBinary): int
    {
        $tmpFile = tempnam(sys_get_temp_dir(), 'cbz_');
        file_put_contents($tmpFile, $cbzBinary);

        $zip = new ZipArchive();
        if ($zip->open($tmpFile) !== true) {
            unlink($tmpFile);
            throw new \RuntimeException('Failed to open CBZ file as ZIP archive');
        }

        $count = 0;
        for ($i = 0; $i < $zip->numFiles; $i++) {
            $name = $zip->getNameIndex($i);
            if (preg_match('/\.(jpg|jpeg|png|webp|gif)$/i', $name)) {
                $count++;
            }
        }

        $zip->close();
        unlink($tmpFile);

        return $count;
    }
}
