<?php

namespace App\Libs\Upload;

use App\Enums\BookUploadKeyEnum;
use App\Enums\DocumentTypeEnum;
use App\Enums\GameUploadKeyEnum;
use App\Enums\MovieUploadKeyEnum;
use App\Enums\MusicUploadKeyEnum;
use App\Exceptions\InvalidProductStateException;
use App\Models\Book;
use App\Models\Game;
use App\Models\Movie;
use App\Models\Music;
use App\Models\MusicAlbum;
use App\Models\Product;
use App\Models\ProductAttachment;
use App\Models\SeriesSeason;
use Illuminate\Http\UploadedFile;

class UploadProductAttachments
{
    /**
     * Upload all product attachments
     *
     * @param UploadedFile $uploadedFile
     * @param Product $product
     * @return string|null
     */
    public static function uploadAttachments(UploadedFile $uploadedFile, Product $product): ?string
    {
        $business = $product->{'business'};
        $basePath = sprintf(config('torryme.paths.docs'), $business->buildProductDir($product->{'id'}));

        $resultPath = upload_file_system(
            DocumentTypeEnum::productAttachment->value,
            $basePath,
            $uploadedFile,
        );

        if(filled($resultPath)) {
            ProductAttachment::store(array(
                'path' => $resultPath,
                'type' => upload_file_type($uploadedFile),
                'product_id' => $product->{'id'}
            ));
        }

        return $resultPath;
    }

    /**
     * Upload library product attachments
     *
     * @param UploadedFile $uploadedFile
     * @param Product $product
     * @param string $uploadKey
     * @return string|null
     */
    public static function uploadAttachmentForLibrary(UploadedFile $uploadedFile, Product $product, string $uploadKey): ?string
    {
        $resultPath = null;

        /** @var Book $book */
        $book = $product->{'book'};

        $business = $product->{'business'};
        $basePath = sprintf(config('torryme.paths.docs'), $business->buildProductDir($product->{'id'}));

        if($uploadKey === BookUploadKeyEnum::cover->value) {
            if($book === null) {
                $book = Book::createBookWithCover($product, $basePath, $uploadedFile);
            } else {
                $book = $book->addBookCover($uploadedFile, $basePath);
            }

            $resultPath = $book?->{'cover'};
        } else {
            if($uploadKey === BookUploadKeyEnum::bookFile->value) {
                if($book === null) {
                    $book = Book::createBookWithFile($product, $basePath, $uploadedFile);
                } else {
                    $book = $book->addBookFile($uploadedFile, $basePath);
                }

                $resultPath = $book?->{'file_path'};
            }
        }

        return $resultPath;
    }

    /**
     * Upload movie attachments
     *
     * @param UploadedFile $uploadedFile
     * @param Product $product
     * @param string $uploadKey
     * @return string|null
     */
    public static function uploadAttachmentForMovie(UploadedFile $uploadedFile, Product $product, string $uploadKey): ?string
    {
        $resultPath = null;

        /** @var Movie $movie */
        $movie = $product->{'movie'};

        $business = $product->{'business'};
        $basePath = sprintf(config('torryme.paths.docs'), $business->buildProductDir($product->{'id'}));

        if($uploadKey === MovieUploadKeyEnum::poster->value) {
            if($movie === null) {
                $movie = Movie::createMovieWithCover($product, $basePath, $uploadedFile);
            } else {
                $movie = $movie->addMoviePoster($uploadedFile, $basePath);
            }

            $resultPath = $movie?->{'cover'};
        } else {
            if($uploadKey === MovieUploadKeyEnum::movieFile->value) {
                if($movie === null) {
                    $movie = $movie::createMovieWithFile($product, $basePath, $uploadedFile);
                } else {
                    $movie = $movie->addMovieFile($uploadedFile, $basePath);
                }

                $resultPath = $movie?->{'file_path'};
            }
        }

        return $resultPath;
    }

    /**
     * Upload new series season and episodes
     *
     * @param array $data
     * @param UploadedFile $uploadedFile
     * @param Product $product
     * @return string|null
     * @throws InvalidProductStateException
     * @throws \Exception
     */
    public static function uploadAttachmentForSeriesSeason(array $data, UploadedFile $uploadedFile, Product $product): ?string
    {
        try {
            // Get data ...
            $series = $product->{'series'};

            if($series === null) {
                throw new InvalidProductStateException();
            }

            /** @var SeriesSeason $season */
            $season = SeriesSeason::findByOccurrence($data['season_occurrence'], $series->{'id'});

            if($season === null) {
                //  Create series season
                /** @var SeriesSeason $season */
                $season = SeriesSeason::createSeason($data, $series);
            }

            $episode = $season->addEpisode($uploadedFile, $data);
            $resultPath = $episode?->{'file_path'};
        } catch (\Exception $exception) {
            log_debug(exception: $exception,  prefix: 'UploadProductAttachments::uploadAttachmentForSeriesSeason');

            throw $exception;
        }

        return $resultPath;
    }

    /**
     * Upload music attachments
     *
     * @param UploadedFile $uploadedFile
     * @param Product $product
     * @param string $uploadKey
     * @return string|null
     */
    public static function uploadAttachmentForMusic(UploadedFile $uploadedFile, Product $product, string $uploadKey): ?string
    {
        $resultPath = null;

        /** @var Music $music */
        $music = $product->{'music'};

        $business = $product->{'business'};
        $basePath = sprintf(config('torryme.paths.docs'), $business->buildProductDir($product->{'id'}));

        if($uploadKey === MusicUploadKeyEnum::musicPoster->value) {
            if($music === null) {
                $music = Music::createMusicWithCover($product, $basePath, $uploadedFile);
            } else {
                $music = $music->addMusicPoster($uploadedFile, $basePath);
            }

            $resultPath = $music?->{'cover'};
        } else {
            if($uploadKey === MusicUploadKeyEnum::musicFile->value) {
                if($music === null) {
                    $music = $music::createMusicWithFile($product, $basePath, $uploadedFile);
                } else {
                    $music = $music->addMusicFile($uploadedFile, $basePath);
                }

                $resultPath = $music?->{'file_path'};
            }
        }

        return $resultPath;
    }

    /**
     * Upload new music album
     *
     * @param array $data
     * @param UploadedFile $uploadedFile
     * @param Product $product
     * @return string|null
     * @throws InvalidProductStateException
     * @throws \Exception
     */
    public static function uploadAttachmentForMusicAlbum(array $data, UploadedFile $uploadedFile, Product $product): ?string
    {
        try {
            // Get data ...
            /** @var MusicAlbum $musicAlbum */
            $musicAlbum = $product->{'musicAlbum'};

            if($musicAlbum === null) {
                throw new InvalidProductStateException();
            }

            $music = $musicAlbum->addMusicSingle($uploadedFile, $data);
            $resultPath = $music?->{'file_path'};
        } catch (\Exception $exception) {
            log_debug(exception: $exception,  prefix: 'UploadProductAttachments::uploadAttachmentForMusicAlbum');
            throw $exception;
        }

        return $resultPath;
    }

    /**
     * Upload game attachments
     *
     * @param UploadedFile $uploadedFile
     * @param Product $product
     * @param string $uploadKey
     * @return string|null
     */
    public static function uploadAttachmentForGame(UploadedFile $uploadedFile, Product $product, string $uploadKey): ?string
    {
        $resultPath = null;

        /** @var Game $game */
        $game = $product->{'game'};

        $business = $product->{'business'};
        $basePath = sprintf(config('torryme.paths.docs'), $business->buildProductDir($product->{'id'}));

        if($uploadKey === GameUploadKeyEnum::gameCover->value) {
            if($game === null) {
                $game = Game::createGameWithCover($product, $basePath, $uploadedFile);
            } else {
                $game = $game->addGameCover($uploadedFile, $basePath);
            }

            $resultPath = $game?->{'cover'};
        } else {
            if($uploadKey === GameUploadKeyEnum::gameFile->value) {
                if($game === null) {
                    $game = Game::createGameWithFile($product, $basePath, $uploadedFile);
                } else {
                    $game = $game->addGameFile($uploadedFile, $basePath);
                }

                $resultPath = $game?->{'file_path'};
            }
        }

        return $resultPath;
    }
}
