<?php

namespace App\Repositories\Admin;

use App\Models\Movie;
use App\Models\MovieFile;
use App\Models\TvShow;
use App\Repositories\Interfaces\Admin\MovieInterface;
use Carbon\Carbon;
use App\Traits\ImageTrait;
use Illuminate\Http\UploadedFile;

use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;
use App\Jobs\ProcessVideoConversion;
use Illuminate\Support\Facades\Storage;

class MovieRepository implements MovieInterface
{
    use ImageTrait;

    public function all()
    {
        return Movie::get();
    }

    public function store($request)
    {
        try {
            if (isset($request['thumbnail']) && $request['thumbnail'] instanceof UploadedFile) {
                $requestImage = $request['thumbnail'];
                $response = $this->saveImage($requestImage, '_movie_');
                $thumbnail = $response['images'];
            }
            if (isset($request['poster']) && $request['poster'] instanceof UploadedFile) {
                $requestImage = $request['poster'];
                $response = $this->saveImage($requestImage, '_movie_');
                $poster = $response['images'];
            }

            $data = [
                'title' => $request['title'],
                'slug' => $request['slug'],
                'seo_title' => $request['seo_title'],
                'description' => $request['description'],
                'stars' => json_encode($request['actor']),
                'director' => json_encode($request['director']),
                'writer' => json_encode($request['writer']),
                'rating' => $request['imdb_rating'],
                'release' => $request['date'],
                'country' => json_encode($request['country']),
                'genre' => json_encode($request['genre']),
                'language' => json_encode($request['language']),
                'video_type' => $request['video_type'],
                'runtime' => $request['runtime'],
                'video_quality' => $request['video_quality'],
                'is_trending' => $request['is_trending'],
                'is_featured' => $request['is_featured'],
                'is_recommended' => $request['is_recommended'],
                'is_original' => $request['is_original'],
                'is_blockbuster' => $request['is_blockbuster'],
                'is_real_life_story' => $request['is_real_life_story'],
                'status' => $request['status'],
                'trailer' => $request['trailer_youtube_source'] ? 1 : 0,
                'trailler_youtube_source' => $request['trailer_youtube_source'],
                'enable_download' => $request['enable_download'],
                'focus_keyword' => $request['focus_keyword'],
                'meta_description' => $request['meta_description'],
                'tags' => $request['tags'],
                'imdb_rating' => $request['imdb_rating'],
                'is_tvseries' => 0,
                'total_rating' => 0,
                'today_view' => 0,
                'weekly_view' => 0,
                'monthly_view' => 0,
                'total_view' => 0,
                'last_ep_added' => Carbon::now(),
                'imdbid' => 0,
                'tmdb_id' => 0,
                'thumbnail' => isset($thumbnail) ? json_encode($thumbnail) : '',
                'poster' => isset($poster) ? json_encode($poster) : '',

                'is_free' => (int)$request['is_free'],
                'is_rental' => (int)$request['is_rental'],

                'rental_price'      => isset($request['rental_price']) ? (int)$request['rental_price'] : 0,
                'rental_duration'   => isset($request['rental_duration']) ? (int)$request['rental_duration'] : 0,
                'rental_type'   => isset($request['rental_type']) ? $request['rental_type'] : null,

                'created_at' => Carbon::now(),
                'updated_at' => Carbon::now(),
            ];
            return Movie::create($data);
        } catch (\Exception $e) {
            throw $e;
        }
    }

    public function update($request, $id)
    {
        try {
            $movie = Movie::where('id', $id)->first();

            if (isset($request['thumbnail']) && $request['thumbnail'] instanceof UploadedFile) {
                $this->imageDelete($id, 'movie', 'thumbnail');
                $requestImage = $request['thumbnail'];
                $response = $this->saveImage($requestImage, '_movie_');
                $request['thumbnail'] = $response['images'];
            }

            if (isset($request['poster']) && $request['poster'] instanceof UploadedFile) {
                $this->imageDelete($id, 'movie', 'poster');
                $requestImage = $request['poster'];
                $response = $this->saveImage($requestImage, '_movie_');
                $request['poster'] = $response['images'];
            }

            $data = [
                'title' => $request['title'],
                'slug' => $request['slug'],
                'seo_title' => $request['seo_title'],
                'description' => $request['description'],
                'stars' => $request['actor'],
                'director' => $request['director'],
                'writer' => $request['writer'],
                'rating' => $request['imdb_rating'],
                'release' => $request['date'],
                'country' => json_encode($request['country']),
                'genre' => json_encode($request['genre']),
                'language' => json_encode($request['language']),
                'video_type' => $request['video_type'],
                'runtime' => $request['runtime'],
                'video_quality' => $request['video_quality'],
                'is_trending' => $request['is_trending'],
                'is_featured' => $request['is_featured'],
                'is_recommended' => $request['is_recommended'],
                'is_original' => $request['is_original'],
                'is_blockbuster' => $request['is_blockbuster'],
                'is_real_life_story' => $request['is_real_life_story'],
                'status' => $request['status'],
                'trailer' => $request['trailer_youtube_source'] ? 1 : 0,
                'trailler_youtube_source' => $request['trailer_youtube_source'],
                'enable_download' => $request['enable_download'],
                'focus_keyword' => $request['focus_keyword'],
                'meta_description' => $request['meta_description'],
                'tags' => $request['tags'],
                'imdb_rating' => $request['imdb_rating'],
                'is_tvseries' => 0,
                'total_rating' => 0,
                'today_view' => 0,
                'weekly_view' => 0,
                'monthly_view' => 0,
                'total_view' => 0,
                'last_ep_added' => Carbon::now(),
                'imdbid' => 0,
                'tmdb_id' => 0,
                'thumbnail' => isset($request['thumbnail']) ? json_encode($request['thumbnail']) : $movie->thumbnail,
                'poster' => isset($request['poster']) ? json_encode($request['poster']) : $movie->poster,
                'updated_at' => Carbon::now(),

                'is_free' => (int)$request['is_free'],
                'is_rental' => (int)$request['is_rental'],
                'rental_price'      => $request['is_rental'] ? (int)$request['rental_price'] : 0,
                'rental_duration'   => $request['is_rental'] ? (int)$request['rental_duration'] : 0,
                'rental_type'   => $request['is_rental'] ? $request['rental_type'] : null,
            ];
            return Movie::where('id', $id)->update($data);
        } catch (\Exception $e) {
            return false;
        }
    }

    public function file_store($request)
    {
        try {
            if ($request['source'] == 'local') {
                $defaultStorage = setting('default_storage') ?: 'local';
                $cloudDisk = storage_disk_for_setting($defaultStorage);

                if ($cloudDisk !== null && isset($request['video_file'])) {
                    $file = $request['video_file'];
                    $filename = uniqid() . '_' . time() . '.' . $file->getClientOriginalExtension();
                    $path = "videos/{$filename}";
                    Storage::disk($cloudDisk)->put($path, file_get_contents($file->getRealPath()), ['visibility' => 'public']);
                    $fileUrl = Storage::disk($cloudDisk)->url($path);
                    $srcType = match ($defaultStorage) {
                        'aws_s3' => 's3',
                        default => $defaultStorage,
                    };

                    $movieFile = MovieFile::create([
                        'video_id' => $request['video_id'],
                        'label' => $request['label'],
                        'file_source' => $srcType,
                        'source_type' => $srcType,
                        'file_url' => $fileUrl,
                        'order' => $request['order'],
                        'stream_key' => Str::uuid(),
                        'created_at' => Carbon::now(),
                        'updated_at' => Carbon::now(),
                    ]);

                    return true;
                }

                $file = $request['video_file'];
                $filename = uniqid() . '_' . time() . '.' . $file->getClientOriginalExtension();
                $destinationPath = public_path('uploads/videos');

                if (!File::exists($destinationPath)) {
                    File::makeDirectory($destinationPath, 0775, true);
                }

                $file->move($destinationPath, $filename);
                $relativePath = 'uploads/videos/' . $filename;

                $movieFile = MovieFile::create([
                    'video_id' => $request['video_id'],
                    'label' => $request['label'],
                    'file_source' => $request['source'],
                    'source_type' => $request['source'],
                    'file_url' => $relativePath,
                    'order' => $request['order'],
                    'stream_key' => Str::uuid(),
                    'created_at' => Carbon::now(),
                    'updated_at' => Carbon::now(),
                ]);

                // Dispatch background job for video conversion
                dispatch(new ProcessVideoConversion(
                    $movieFile,
                    public_path($relativePath),
                    $file->getClientOriginalExtension()
                ));

                return response()->json([
                    'status' => true,
                    'message' => 'Video uploaded and queued for conversion successfully.',
                    'data' => $movieFile
                ]);
            } elseif (isset($request['video_file']) && $request['source'] == 'wasabi' || $request['source'] == 's3' || $request['source'] == 'do') {
                $file = $request['video_file'];
                $disk = $request['source']; // "wasabi" or "s3"
                $filename = uniqid() . '_' . time() . '.' . $file->getClientOriginalExtension();
                $path = "videos/{$filename}";

                if (isset($request['video_file'])) {
                    Storage::disk($disk)->put($path, file_get_contents($file));
                    Storage::disk($disk)->setVisibility($path, 'public');
                    $fileUrl = Storage::disk($disk)->url($path);
                }
                $movieFile = MovieFile::create([
                    'video_id'    => $request['video_id'],
                    'label'       => $request['label'],
                    'file_source' => $disk,
                    'source_type' => $disk,
                    'file_url'    => $fileUrl,
                    'order'       => $request['order'],
                    'stream_key'  => Str::uuid(),
                    'created_at'  => Carbon::now(),
                    'updated_at'  => Carbon::now(),
                ]);

                return true;
            } else {
                $movieFile = MovieFile::create([
                    'video_id' => $request['video_id'],
                    'label' => $request['label'],
                    'file_source' => $request['source'],
                    'source_type' => $request['source'],
                    'file_url' => $request['file_url'],
                    'order' => $request['order'],
                    'stream_key' => Str::uuid(),
                    'created_at' => Carbon::now(),
                    'updated_at' => Carbon::now(),
                ]);
                return $movieFile;
            }
        } catch (\Exception $e) {
            logger()->error('Video upload or conversion queue failed', [
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
            ]);

            return false;
        }
    }



    public function file_update($request, $id)
    {
        try {
            $movieFile = MovieFile::findOrFail($id);
            $disk = $request['source']; // local, s3, wasabi
            $file = isset($request['video_file']) ? $request['video_file'] : null;
            // Handle local upload
            if ($request['source'] === 'local' && isset($request['video_file'])) {
                $defaultStorage = setting('default_storage') ?: 'local';
                $cloudDisk = storage_disk_for_setting($defaultStorage);

                if ($cloudDisk !== null) {
                    delete_stored_movie_file($movieFile->file_source, $movieFile->file_url);

                    $file = $request['video_file'];
                    $filename = uniqid() . '_' . time() . '.' . $file->getClientOriginalExtension();
                    $path = "videos/{$filename}";
                    Storage::disk($cloudDisk)->put($path, file_get_contents($file->getRealPath()), ['visibility' => 'public']);
                    $fileUrl = Storage::disk($cloudDisk)->url($path);
                    $srcType = match ($defaultStorage) {
                        'aws_s3' => 's3',
                        default => $defaultStorage,
                    };

                    MovieFile::where('id', $id)->update([
                        'label' => $request['label'],
                        'file_source' => $srcType,
                        'source_type' => $srcType,
                        'file_url' => $fileUrl,
                        'order' => $request['order'],
                        'updated_at' => Carbon::now(),
                    ]);

                    return true;
                }

                // Delete previous file if exists
                $oldFilePath = public_path($movieFile->file_url);
                if ($movieFile->file_source === 'local' && file_exists($oldFilePath)) {
                    @unlink($oldFilePath);
                }

                // Upload original file to temp folder
                $file = $request['video_file'];
                $filename = uniqid() . '_' . time() . '.' . $file->getClientOriginalExtension();
                $destinationPath = public_path('uploads/videos');

                if (!File::exists($destinationPath)) {
                    File::makeDirectory($destinationPath, 0775, true);
                }

                $file->move($destinationPath, $filename);
                $relativePath = 'uploads/videos/' . $filename;

                MovieFile::where('id', $id)->update([
                    'label' => $request['label'],
                    'file_source' => $request['source'],
                    'source_type' => $request['source'],
                    'file_url' => $relativePath,
                    'order' => $request['order'],
                    'updated_at' => Carbon::now(),
                ]);

                // Dispatch conversion job
                dispatch(new ProcessVideoConversion(
                    $movieFile,
                    public_path($relativePath),
                    $file->getClientOriginalExtension()
                ));

                return response()->json([
                    'status' => true,
                    'message' => 'Video uploaded and queued for conversion successfully.',
                    'data' => $movieFile
                ]);
            } elseif (in_array($disk, ['s3', 'wasabi', 'do'])) {

                if (isset($request['video_file'])) {
                    delete_stored_movie_file($movieFile->file_source, $movieFile->file_url);

                    $filename = uniqid() . '_' . time() . '.' . $file->getClientOriginalExtension();
                    $path = "videos/{$filename}";
                    Storage::disk($disk)->put($path, file_get_contents($file->getRealPath()), ['visibility' => 'public']);
                    $fileUrl = Storage::disk($disk)->url($path);
                } else {
                    $fileUrl = $movieFile->file_url;
                }

                MovieFile::where('id', $id)->update([
                    'label'       => $request['label'],
                    'file_source' => $disk,
                    'source_type' => $disk,
                    'file_url'    => $fileUrl,
                    'order'       => $request['order'],
                    'updated_at'  => Carbon::now(),
                ]);

                return true;
            } else {
                $movieFile = MovieFile::where('id', $id)->update([
                    'label' => $request['label'],
                    'file_source' => $request['source'],
                    'source_type' => $request['source'],
                    'file_url' => $request['file_url'],
                    'order' => $request['order'],
                    'updated_at' => Carbon::now(),
                ]);
                return true;
            }
        } catch (\Exception $e) {
            logger()->error('File update failed', [
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
            ]);
            return false;
        }
    }

    public function file_delete($id)
    {
        try {
            $movieFile = MovieFile::find($id);

            if (!$movieFile) {
                return [
                    'title' => __('error'),
                    'status' => false,
                    'message' => __('movie_file_not_found'),
                    'is_reload' => false,
                ];
            }

            if ($movieFile->file_source && $movieFile->file_url) {
                delete_stored_movie_file($movieFile->file_source, $movieFile->file_url);
            }

            // Delete converted video folder (only for local processing)
            $convertedPath = public_path("uploads/videos/{$movieFile->id}");
            if (File::exists($convertedPath)) {
                File::deleteDirectory($convertedPath);
            }

            // Delete the database record
            $movieFile->delete();

            return [
                'title' => __('success'),
                'status' => true,
                'message' => __('movie_file_deleted'),
                'is_reload' => true,
            ];
        } catch (\Exception $e) {
            return [
                'title' => __('error'),
                'status' => false,
                'message' => $e->getMessage(),
                'is_reload' => false,
            ];
        }
    }


    public function make_rental_store($request, $id = null)
    {
        try {
            $data = [
                'price' => $request['price'],
                'hours' => $request['hours'],
                'note' => $request['note'],
                'updated_at' => Carbon::now(),
            ];
            if ($request['type'] === 'movie') {
                return Movie::where('id', $request['id'])->update($data);
            } elseif ($request['type'] === 'tv_show') {
                return TvShow::where('id', $request['id'])->update($data);
            }
        } catch (\Exception $e) {
            return $e->getMessage();
        }
    }
}
