<?php

declare(strict_types=1);

/*
 * Chill is a software for social workers
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */

namespace Chill\DocStoreBundle\Service;

use Chill\DocStoreBundle\Entity\StoredObject;
use Chill\DocStoreBundle\Entity\StoredObjectPointInTime;
use Chill\DocStoreBundle\Entity\StoredObjectPointInTimeReasonEnum;
use Chill\DocStoreBundle\Entity\StoredObjectVersion;
use Chill\DocStoreBundle\Exception\ConversionWithSameMimeTypeException;
use Chill\DocStoreBundle\Exception\StoredObjectManagerException;
use Chill\WopiBundle\Service\WopiConverter;
use Symfony\Component\Mime\MimeTypesInterface;

/**
 * Class StoredObjectToPdfConverter.
 *
 * Converts stored objects to PDF or other specified formats using WopiConverter.
 */
class StoredObjectToPdfConverter
{
    public function __construct(
        private readonly StoredObjectManagerInterface $storedObjectManager,
        private readonly WopiConverter $wopiConverter,
        private readonly MimeTypesInterface $mimeTypes,
    ) {}

    /**
     * Converts the given stored object to a specified format and stores the new version.
     *
     * @param StoredObject $storedObject the stored object to be converted
     * @param string       $lang         the language for the conversion context
     * @param string       $convertTo    The target format for the conversion. Default is 'pdf'.
     *
     * @return array{0: StoredObjectPointInTime, 1: StoredObjectVersion, 2?: string} contains the point in time before conversion and the new version of the stored object. The converted content is included in the response if $includeConvertedContent is true
     *
     * @throws \UnexpectedValueException           if the preferred mime type for the conversion is not found
     * @throws \RuntimeException                   if the conversion or storage of the new version fails
     * @throws StoredObjectManagerException
     * @throws ConversionWithSameMimeTypeException if the document has already the same mime type79*
     */
    public function addConvertedVersion(StoredObject $storedObject, string $lang, $convertTo = 'pdf', bool $includeConvertedContent = false): array
    {
        $newMimeType = $this->mimeTypes->getMimeTypes($convertTo)[0] ?? null;

        if (null === $newMimeType) {
            throw new \UnexpectedValueException(sprintf('could not find a preferred mime type for conversion to %s', $convertTo));
        }

        $currentVersion = $storedObject->getCurrentVersion();

        if ($currentVersion->getType() === $newMimeType) {
            throw new ConversionWithSameMimeTypeException($newMimeType);
        }

        $content = $this->storedObjectManager->read($currentVersion);

        try {
            $converted = $this->wopiConverter->convert($lang, $content, $newMimeType, $convertTo);
        } catch (\RuntimeException $e) {
            throw new \RuntimeException('could not store a new version for document', previous: $e);
        }

        $pointInTime = new StoredObjectPointInTime($currentVersion, StoredObjectPointInTimeReasonEnum::KEEP_BEFORE_CONVERSION);
        $version = $this->storedObjectManager->write($storedObject, $converted, $newMimeType);

        if (!$includeConvertedContent) {
            return [$pointInTime, $version];
        }

        return [$pointInTime, $version, $converted];

    }
}
