<?php

namespace App\Services;

use App\Enums\DocumentTypeEnum;
use App\Models\Movie;
use App\Models\Product;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\DB;

trait MovieService
{
    /**
     * Store new record
     *
     * @param array $data
     * @return Builder|Model
     */
    public static function store(array $data): Model|Builder
    {
        return Movie::query()->create($data);
    }

    /**
     * Update existing record
     *
     * @param array $data
     * @return mixed
     */
    public function updateService(array $data): mixed
    {
        return tap($this)->update($data);
    }

    /**
     * Find by id
     *
     * @param int $id
     * @return Builder|Builder[]|Collection|Model|null
     */
    public static function findById(int $id): Model|Collection|Builder|array|null
    {
        return Movie::query()->find($id);
    }

    /**
     * Try to add or update movie poster
     *
     * @param UploadedFile $uploadedFile
     * @param string $basePath
     * @return Movie
     */
    public function addMoviePoster(UploadedFile $uploadedFile, string $basePath): Movie
    {
        // Try to upload ...
        $resultPath = upload_file_system(DocumentTypeEnum::poster->value, $basePath, $uploadedFile);

        if(filled($resultPath)) {
            $this->updateService(array(
                "cover" => $resultPath,
            ));
        }

        return $this->refresh();
    }

    /**
     * Try to add or update associated Movie file
     *
     * @param UploadedFile $uploadedFile
     * @param string $basePath
     * @return Movie
     */
    public function addMovieFile(UploadedFile $uploadedFile, string $basePath): Movie
    {
        // Try to upload ...
        $resultPath = upload_file_system(DocumentTypeEnum::movieFile->value, $basePath, $uploadedFile);

        if(filled($resultPath)) {
            $this->updateService(array(
                "file_path" => $resultPath,
            ));
        }

        return $this->refresh();
    }

    /**
     * Create new Movie with cover file
     *
     * @param Product $product
     * @param string $basePath
     * @param UploadedFile $cover
     * @return Model|Builder|null
     */
    public static function createMovieWithCover(Product $product, string $basePath, UploadedFile $cover): Model|Builder|null
    {
        $movie = null;
        DB::beginTransaction();

        try {
            // Try to upload ...
            $resultPath = upload_file_system(DocumentTypeEnum::poster->value, $basePath, $cover);
            if(filled($resultPath)) {
                $movie = Movie::store(array(
                    "cover" => $resultPath,
                    'designation' => $product->{'designation'},
                    'description' => $product->{'description'},
                    'price_currency_id' => $product->{'price_currency_id'},
                    'price' => $product->{'price'},
                ));
            }

            if($movie !== null) {
                $product->updateService([
                    "movie_id" => $movie->{'id'},
                ]);

                DB::commit();
                return $movie->refresh();
            }

            DB::rollBack();
        } catch (\Exception $exception) {
            log_debug(exception: $exception,  prefix: 'MovieService::createMovieWithCover');

            DB::rollBack();
        }

        return $movie;
    }

    /**
     * Create new Movie with file
     *
     * @param Product $product
     * @param string $basePath
     * @param UploadedFile $movieFile
     * @return Model|Builder|null
     */
    public static function createMovieWithFile(Product $product, string $basePath, UploadedFile $movieFile): Model|Builder|null
    {
        $movie = null;
        DB::beginTransaction();

        try {
            // Try to upload ...
            $resultPath = upload_file_system(DocumentTypeEnum::movieFile->value, $basePath, $movieFile);
            if(filled($resultPath)) {
                $movie = Movie::store(array(
                    "file_path" => $resultPath,
                    'designation' => $product->{'designation'},
                    'description' => $product->{'description'},
                    'price_currency_id' => $product->{'price_currency_id'},
                    'price' => $product->{'price'},
                ));
            }

            if($movie !== null) {
                $product->updateService([
                    "movie_id" => $movie->{'id'},
                ]);

                DB::commit();
                return $movie->refresh();
            }

            DB::rollBack();
        } catch (\Exception $exception) {
            log_debug(exception: $exception,  prefix: 'MovieService::createMovieWithFile');

            DB::rollBack();
        }

        return $movie;
    }
}
