<?php

namespace App\Library\Action\Handler;

use App\Base\Service\MediaFiles;
use App\Library\Action\Command\LibrarySearchCommand;
use App\Library\Action\Result\LibrarySearchResult;
use App\Library\Dto\MediaFileDto;
use App\Base\Util\PTN;
use OneToMany\RichBundle\Contract\CommandInterface;
use OneToMany\RichBundle\Contract\HandlerInterface;
use OneToMany\RichBundle\Contract\ResultInterface;

/**
 * @implements HandlerInterface<LibrarySearchCommand,LibrarySearchHandler>
 */
class LibrarySearchHandler implements HandlerInterface
{
    private array $searchTypes = [
        'episode_by_title' => 'episodeByTitle',
        'movie_by_title' => 'movieByTitle',
    ];

    public function __construct(
        private readonly MediaFiles $mediaFiles,
    ) {}

    public function handle(CommandInterface $command): ResultInterface
    {
        $searchType = $this->getSearchType($command);
        $function   = $this->searchTypes[$searchType];
        return $this->$function($command);
    }

    private function getSearchType(CommandInterface $command): ?string
    {
        if (!is_null($command->title) &&
            is_null($command->imdbId) &&
            is_null($command->season) &&
            is_null($command->episode)
        ) {
            return 'movie_by_title';
        }

        if ((!is_null($command->title) || is_null($command->imdbId)) &&
            !is_null($command->season) &&
            !is_null($command->episode)
        ) {
            return 'episode_by_title';
        }
        return null;
    }

    private function episodeByTitle(CommandInterface $command): ?LibrarySearchResult
    {
        $result = $this->mediaFiles->episodeExists(
            $command->title,
            (int) $command->season,
            (int) $command->episode,
        );
        $exists =  $result instanceof \SplFileInfo;

        return new LibrarySearchResult(
            input: $command,
            exists: $exists,
            file: true === $exists ? MediaFileDto::fromSplFileInfo($result) : null,
            ptn: true === $exists ? (object) new PTN()->parse($result->getFilename()) : null,
        );
    }

    private function movieByTitle(CommandInterface $command): ?LibrarySearchResult
    {
        $result = $this->mediaFiles->movieExists($command->title);
        $exists =  $result instanceof \SplFileInfo;

        return new LibrarySearchResult(
            input: $command,
            exists: $exists,
            file: true === $exists ? MediaFileDto::fromSplFileInfo($result) : null,
            ptn: true === $exists ? (object) new PTN()->parse($result->getFilename()) : null,
        );
    }
}
