<?php

namespace App\Repositories\Admin;

use App\Models\Episode;
use App\Models\EpisodeDownload;
use App\Models\Season;
use App\Repositories\Interfaces\Admin\EpisodeInterface;
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 EpisodeRepository implements EpisodeInterface
{
    use ImageTrait;
    public function all()
    {
        return Episode::get();
    }

    public function store($request)
    {
        try {
            if (isset($request['poster']) && $request['poster'] instanceof UploadedFile) {
                $requestImage = $request['poster'];
                $response = $this->saveImage($requestImage, '_episode_');
                $poster = $response['images'];
            }
            if (isset($request['season_id'])) {
                $season = Season::find($request['season_id']);
                if (!$season) {
                    return false; // Season not found
                } else {
                    $season_ids = json_decode($season->tv_show_id, true) ?? [];
                    if (!in_array($request['tv_series_id'], $season_ids)) {
                        $season_ids[] = $request['tv_series_id'];
                    }
                    $season->tv_show_id = json_encode($season_ids);
                    $season->save();
                }
            }
            $baseSlug = slugify($request['episode_name']);
            $slug = $baseSlug;
            $counter = 1;
            // Step 2: Check for duplicates and increment until unique
            while (Episode::where('slug', $slug)->exists()) {
                $slug = $baseSlug . '-' . $counter;
                $counter++;
            }

            if (isset($request['file']) && $request['source_type'] == 'video') {
                $defaultStorage = setting('default_storage') ?: 'local';
                $cloudDisk = storage_disk_for_setting($defaultStorage);

                if ($cloudDisk !== null) {
                    $file = $request['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 = Episode::create([
                        'season_id' => $request['season_id'],
                        'series_id' => $request['tv_series_id'],
                        'episode_name' => $request['episode_name'],
                        'slug' => $slug,
                        'description' => $request['description'],
                        'order' => $request['order'],
                        'file_url' => $fileUrl,
                        'runtime' => $request['runtime'],
                        'source_type' => $srcType,
                        'poster' => isset($poster) ? json_encode($poster) : '',
                        'created_at' => Carbon::now(),
                        'updated_at' => Carbon::now(),
                    ]);

                    return true;
                }

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

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

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

                $movieFile = Episode::create([
                    'season_id' => $request['season_id'],
                    'series_id' => $request['tv_series_id'],
                    'episode_name' => $request['episode_name'],
                    'slug' => $slug,
                    'description' => $request['description'],
                    'order' => $request['order'],
                    'file_url' => $relativePath,
                    'runtime' => $request['runtime'],
                    'source_type' => $request['source_type'],
                    'poster' => isset($poster) ? json_encode($poster) : '',
                    'created_at' => Carbon::now(),
                    'updated_at' => Carbon::now(),
                ]);

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

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

                $file = $request['file'];
                $disk = $request['source_type']; // "wasabi" or "s3"
                $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);

                $movieFile = Episode::create([
                    'season_id' => $request['season_id'],
                    'series_id' => $request['tv_series_id'],
                    'episode_name' => $request['episode_name'],
                    'slug' => $slug,
                    'description' => $request['description'],
                    'order' => $request['order'],
                    'file_url' => $fileUrl,
                    'runtime' => $request['runtime'],
                    'source_type' => $request['source_type'],
                    'poster' => isset($poster) ? json_encode($poster) : '',
                    'created_at' => Carbon::now(),
                    'updated_at' => Carbon::now(),
                ]);

                return true;
            } else {
                $data = [
                    'season_id' => $request['season_id'],
                    'series_id' => $request['tv_series_id'],
                    'episode_name' => $request['episode_name'],
                    'slug' => $slug,
                    'description' => $request['description'],
                    'order' => $request['order'],
                    'runtime' => $request['runtime'],
                    'file_url' => $request['file_url'],
                    'source_type' => $request['source_type'],
                    'poster' => isset($poster) ? json_encode($poster) : '',
                    'created_at' => Carbon::now(),
                    'updated_at' => Carbon::now(),
                ];
                return Episode::create($data);
            }
        } catch (\Exception $e) {
            return false;
        }
    }

    public function update($request, $id)
    {
        $episode = Episode::find($id);

        if (!$episode) {
            return false; // Episode not found
        }

        // Handle poster update
        if (isset($request['poster']) && $request['poster'] instanceof UploadedFile) {
            $this->imageDelete($id, 'episode', 'poster');
            $requestImage = $request['poster'];
            $response = $this->saveImage($requestImage, '_episode_');
            $poster = $response['images'];
        } else {
            $poster = $episode->poster;
        }

        // Handle slug change if name changed
        if ($episode->episode_name !== $request['episode_name']) {
            $baseSlug = slugify($request['episode_name']);
            $slug = $baseSlug;
            $counter = 1;
            while (
                Episode::where('slug', $slug)
                ->where('id', '!=', $episode->id)
                ->exists()
            ) {
                $slug = $baseSlug . '-' . $counter++;
            }
        } else {
            $slug = $episode->slug;
        }

        // If a new file is uploaded
        if (isset($request['file']) && $request['source_type'] === 'video') {
            delete_stored_movie_file($episode->source_type, $episode->file_url);

            $convertedPath = public_path("uploads/episodes/{$episode->id}");
            if (File::exists($convertedPath)) {
                File::deleteDirectory($convertedPath);
            }

            $defaultStorage = setting('default_storage') ?: 'local';
            $cloudDisk = storage_disk_for_setting($defaultStorage);

            if ($cloudDisk !== null) {
                $file = $request['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,
                };

                $episode->update([
                    'episode_name' => $request['episode_name'],
                    'slug' => $slug,
                    'description' => $request['description'],
                    'order' => $request['order'],
                    'file_url' => $fileUrl,
                    'runtime' => $request['runtime'],
                    'source_type' => $srcType,
                    'poster' => isset($request['poster']) ? json_encode($poster) : '',
                    'updated_at' => Carbon::now(),
                ]);

                return true;
            }

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

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

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

            $episode->update([
                'episode_name' => $request['episode_name'],
                'slug' => $slug,
                'description' => $request['description'],
                'order' => $request['order'],
                'file_url' => $relativePath,
                'runtime' => $request['runtime'],
                'source_type' => $request['source_type'],
                'poster' => isset($request['poster']) ? json_encode($poster) : '',
                'updated_at' => Carbon::now(),
            ]);

            dispatch(new ProcessVideoConversion(
                $episode,
                public_path($relativePath),
                $file->getClientOriginalExtension(),
                'episodes'
            ));

            return response()->json([
                'status' => true,
                'message' => 'Episode updated and video queued for conversion successfully.',
                'data' => $episode,
            ]);
        } elseif ($request['source_type'] == 's3' || $request['source_type'] == 'wasabi' || $request['source_type'] == 'do') {

            if (isset($request['file'])) {
                $file = $request['file'];
                $disk = $request['source_type']; // "wasabi" or "s3"
                $filename = uniqid() . '_' . time() . '.' . $file->getClientOriginalExtension();
                $path = "videos/{$filename}";
                delete_stored_movie_file($episode->source_type, $episode->file_url);

                Storage::disk($disk)->put($path, file_get_contents($file->getRealPath()), ['visibility' => 'public']);
                $fileUrl = Storage::disk($disk)->url($path);

            } else {
                $fileUrl = $episode->file_url;
            }
           
            // Update DB
            $episode->update([
                'episode_name' => $request['episode_name'],
                'slug'         => $slug,
                'description'  => $request['description'],
                'order'        => $request['order'],
                'file_url'     => $fileUrl,
                'runtime' => $request['runtime'],
                'source_type'  => $request['source_type'],
                'poster'       => isset($request['poster']) ? json_encode($poster) : '',
                'updated_at'   => Carbon::now(),
            ]);

            return true;
        } else {

            $data = [
                'episode_name' => $request['episode_name'],
                'slug'         => $slug,
                'description'  => $request['description'],
                'order'        => $request['order'],
                'file_url'     => $request['file_url'] ?? $episode->file_url,
                'source_type'  => $request['source_type'],
                'runtime' => $request['runtime'],
                'poster'       => isset($request['poster']) ? json_encode($poster) : $episode->poster,
                'updated_at'   => Carbon::now(),
            ];

            // If no new file is uploaded, just update other fields
            $episode->update($data);

            return $episode;
        }
    }



    public function store_download_link($request)
    {
        try {
            $data = [
                'season_id' => $request['season_id'],
                'link_title' => $request['link_title'],
                'resolution' => $request['resolution'],
                'file_size' => $request['file_size'],
                'download_url' => $request['download_url'],
                'created_at' => Carbon::now(),
                'updated_at' => Carbon::now(),
            ];
            return EpisodeDownload::create($data);
        } catch (\Exception $e) {
            return false;
        }
    }

    public function update_download_link($request, $id)
    {
        try {
            $data = [
                'link_title' => $request['link_title'],
                'resolution' => $request['resolution'],
                'file_size' => $request['file_size'],
                'download_url' => $request['download_url'],
                'updated_at' => Carbon::now(),
            ];
            return EpisodeDownload::where('id', $id)->update($data);
        } catch (\Exception $e) {
            return false;
        }
    }
}
