<?php

namespace App\Services;

use App\Enums\SongStorageType;
use App\Models\Song;
use App\Models\SongZipArchive;
use App\Services\SongStorages\CloudStorageFactory;
use App\Services\SongStorages\SftpStorage;
use App\Values\Downloadable;
use App\Values\Podcast\EpisodePlayable;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\File;

class DownloadService
{
    /**
     * @param Collection<Song>|array<array-key, Song> $songs
     */
    public function getDownloadable(Collection $songs): ?Downloadable
    {
        if ($songs->count() === 1) {
            return optional(
                $this->getLocalPathOrDownloadableUrl($songs->first()), // @phpstan-ignore-line
                static fn (string $url) => Downloadable::make($url)
            );
        }

        return Downloadable::make(
            (new SongZipArchive())
            ->addSongs($songs)
            ->finish()
            ->getPath()
        );
    }

    public function getLocalPathOrDownloadableUrl(Song $song): ?string
    {
        if (!$song->storage->supported()) {
            return null;
        }

        if ($song->isEpisode()) {
            // If the song is an episode, get the episode's media URL ("path").
            return $song->path;
        }

        if ($song->storage === SongStorageType::LOCAL) {
            return $song->path;
        }

        if ($song->storage === SongStorageType::SFTP) {
            return app(SftpStorage::class)->copyToLocal($song);
        }

        return CloudStorageFactory::make($song->storage)->getPresignedUrl($song->storage_metadata->getPath());
    }

    public function getLocalPath(Song $song): ?string
    {
        if (!$song->storage->supported()) {
            return null;
        }

        if ($song->isEpisode()) {
            return EpisodePlayable::getForEpisode($song)->path;
        }

        $location = $song->storage_metadata->getPath();

        if ($song->storage === SongStorageType::LOCAL) {
            return File::exists($location) ? $location : null;
        }

        if ($song->storage === SongStorageType::SFTP) {
            /** @var SftpStorage $storage */
            $storage = app(SftpStorage::class);

            return $storage->copyToLocal($location);
        }

        return CloudStorageFactory::make($song->storage)->copyToLocal($location);
    }
}