<?php

namespace App\Http\Controllers\User;

use Carbon\Carbon;
use App\Models\Plan;
use App\Models\User;
use App\Models\Medias;
use App\Models\Optimer;
use App\Models\Setting;
use Illuminate\Support\Str;
use Illuminate\Http\Request;
use App\Classes\S3MediaStorage;
use App\Classes\LocalMediaStorage;
use App\Classes\WasabiMediaStorage;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use App\Classes\BackblazeMediaStorage;
use Illuminate\Support\Facades\Storage;

class MediaController extends Controller
{
    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('auth');
    }

    /**
     * Show the application dashboard.
     *
     * @return \Illuminate\Contracts\Support\Renderable
     */

    // All user media
    public function media()
    {
        // Get plan details
        $active_plan = Plan::where('id', Auth::user()->plan_id)->first();
        // Get user details
        $plan = User::where('id', Auth::user()->id)->first();

        if ($active_plan != null) {
            // Get media images 
            $media = Medias::where('user_id', Auth::user()->id)->where('status', '1')->orderBy('id', 'desc')->paginate(12);
            $settings = Setting::where('status', 1)->first();

            $current_storage = 0;

            // Subscription storage
            $current_storage = json_decode(Auth::user()->plan_details)->storage;

            // Get storage usage
            $storageUsage = Medias::where('user_id', Auth::user()->id)->where('status', 1)->sum('size');

            // View media
            return view('user.pages.media.index', compact('media', 'settings', 'storageUsage', 'current_storage'));
        } else {
            // Page redirect
            return redirect()->route('user.plans');
        }
    }

    // Add media
    public function addMedia()
    {
        // Get plan details
        $plan = User::where('id', Auth::user()->id)->where('status', 1)->where('status', 1)->first();
        $plan_details = json_decode($plan->plan_details);

        // Check validity
        $validity = User::where('id', Auth::user()->id)->whereDate('plan_validity', '>=', Carbon::now())->count();

        // Get access types
        $plan_details->access_types = "";
        if ($plan_details->png == 1) {
            $plan_details->access_types .= '.png,';
        }
        if ($plan_details->jpg == 1) {
            $plan_details->access_types .= '.jpg,.jpeg,';
        }
        if ($plan_details->svg == 1) {
            $plan_details->access_types .= '.svg,';
        }
        if ($plan_details->webp == 1) {
            $plan_details->access_types .= '.webp,';
        }
        if ($plan_details->gif == 1) {
            $plan_details->access_types .= '.gif,';
        }

        // Queries
        $settings = Setting::where('status', 1)->first();

        if ($validity == 1) {
            // Add media
            return view('user.pages.media.add', compact('settings', 'plan_details'));
        } else {
            // Redirect
            return redirect()->route('user.media')->with('failed', trans('Your plan is over. Choose your plan renewal or new package and use it.'));
        }
    }

    // Upload media
    public function uploadMedia(Request $request)
    {
        // Get user created optimers overall size
        $overallMediaSize = Medias::where('user_id', Auth::user()->id)->sum('size');

        // Get plan details
        $plan = User::where('id', Auth::user()->id)->where('status', 1)->first();
        $plan_details = json_decode($plan->plan_details);

        // Check validity
        $validity = User::where('id', Auth::user()->id)->whereDate('plan_validity', '>=', Carbon::now())->count();

        // Check storage available
        if ($validity == 1) {
            if ($overallMediaSize < $plan_details->storage) {

                if (env('AWS_ENABLE') == 'on' && $plan_details->s3 == 1) {
                    // Upload local
                    $image = $request->file('file');

                    // Upload AWS S3
                    $path = Storage::disk('s3')->put('files/' . Auth::user()->id . '/media', $image);
                    $request->merge([
                        'size' => $image->getSize(),
                        'path' => $path
                    ]);

                    $mediaImage = $request->only('path', 'title', 'size');

                    $media = new Medias();
                    $media->media_id = random_int(000000000000001, 99999999999999);
                    $media->user_id = Auth::user()->id;
                    $media->media_name = $image->getClientOriginalName();
                    $media->media_url = Storage::disk('s3')->url($path);
                    $media->size = $image->getSize();
                    $media->save();
                } else if (env('WAS_ENABLE') == 'on' && $plan_details->s3 == 1) {
                    // Upload local
                    $image = $request->file('file');

                    // Upload AWS S3
                    $path = Storage::disk('wasabi')->put('files/' . Auth::user()->id . '/media', $image);
                    $request->merge([
                        'size' => $image->getSize(),
                        'path' => $path
                    ]);

                    $mediaImage = $request->only('path', 'title', 'size');

                    $media = new Medias();
                    $media->media_id = random_int(000000000000001, 99999999999999);
                    $media->user_id = Auth::user()->id;
                    $media->media_name = $image->getClientOriginalName();
                    $media->media_url = Storage::disk('wasabi')->url($path);
                    $media->size = $image->getSize();
                    $media->save();
                } else if (env('BACK_ENABLE') == 'on' && $plan_details->s3 == 1) {
                    // Upload local
                    $image = $request->file('file');

                    // Upload AWS S3
                    $path = Storage::disk('backblaze')->put('files/' . Auth::user()->id . '/media', $image);
                    $request->merge([
                        'size' => $image->getSize(),
                        'path' => $path
                    ]);

                    $mediaImage = $request->only('path', 'title', 'size');

                    $media = new Medias();
                    $media->media_id = random_int(000000000000001, 99999999999999);
                    $media->user_id = Auth::user()->id;
                    $media->media_name = $image->getClientOriginalName();
                    $media->media_url = Storage::disk('backblaze')->url($path);
                    $media->size = $image->getSize();
                    $media->save();
                } else {
                    // Upload local
                    $image = $request->file('file');

                    // Image name
                    $imageName = random_int(000000000000001, 99999999999999) . '.' . $image->extension();
                    $movedImage = $image->move(public_path('/storage/media/files/' . Auth::user()->id . '/'), $imageName);

                    $media = new Medias();
                    $media->media_id = random_int(000000000000001, 99999999999999);
                    $media->user_id = Auth::user()->id;
                    $media->media_name = $image->getClientOriginalName();
                    $media->media_url = "/storage/media/files/" . Auth::user()->id . '/' . $imageName;
                    $media->size = $movedImage->getSize();
                    $media->save();
                }


                return response()->json(['status' => 'success', 'message' => trans('Image has been successfully uploaded.')]);
            } else {
                return response()->json(['status' => 'failed', 'message' => trans('Image upload failed. Because, Maximum upload limit / storage is exceeded, Please upgrade your plan.')]);
            }
        } else {
            // Redirect
            return response()->json(['status' => 'failed', 'message' => trans('Your plan is over. Choose your plan renewal or new package and use it.')]);
        }
    }

    // Optimize image
    public function optimizeImage($galleryId)
    {
        // Get user created optimers counts
        $optimers_counts = Optimer::where('uploaded_by', Auth::user()->id)->count();

        // Get user created optimers overall size
        $optimers_size = Optimer::where('uploaded_by', Auth::user()->id)->sum('actual_image_size');

        // Get plan details
        $plan = User::where('id', Auth::user()->id)->where('status', 1)->first();
        $plan_details = json_decode($plan->plan_details);

        // Check validity
        $validity = User::where('id', Auth::user()->id)->whereDate('plan_validity', '>=', Carbon::now())->count();

        // Check no of optimers
        if ($plan_details->maximum == 9999) {
            $maximum = 9999999999;
        } else {
            $maximum = $plan_details->maximum;
        }

        // Check storage available
        if ($validity == 1) {
            if ($optimers_counts < $maximum && $optimers_size < $plan_details->storage) {
                // Get gallery details
                $mediaDetails = Medias::where('id', $galleryId)->where('user_id', Auth::user()->id)->first();

                // Check s3 available
                if (env('AWS_ENABLE') == 'on') {
                    if ($plan_details->s3 == 0) {
                        $storage = new LocalMediaStorage;
                        $storage->localMediaFunction($mediaDetails);
                    } else {
                        $storage = new S3MediaStorage;
                        $storage->s3MediaFunction($mediaDetails);
                    }
                } else if (env('WAS_ENABLE') == 'on') {
                    if ($plan_details->s3 == 0) {
                        $storage = new LocalMediaStorage;
                        $storage->localMediaFunction($mediaDetails);
                    } else {
                        $storage = new WasabiMediaStorage;
                        $storage->wasabiMediaFunction($mediaDetails);
                    }
                } else if (env('BACK_ENABLE') == 'on') {
                    if ($plan_details->s3 == 0) {
                        $storage = new LocalMediaStorage;
                        $storage->localMediaFunction($mediaDetails);
                    } else {
                        $storage = new BackblazeMediaStorage;
                        $storage->backBlazeMediaFunction($mediaDetails);
                    }
                } else {
                    $storage = new LocalMediaStorage;
                    $storage->localMediaFunction($mediaDetails);
                }

                return redirect()->route('user.media')->with('success', trans('Image has been optimized successfully. Please check your optimized image in your Optimizer page.'));
            } else {
                return redirect()->route('user.media')->with('failed', trans('Maximum optimized image creation limit is exceeded, Please upgrade your plan.'));
            }
        } else {
            // Redirect
            return redirect()->route('user.media')->with('failed', trans('Your plan is over. Choose your plan renewal or new package and use it.'));
        }
    }

    // Delete media
    public function deleteMedia($mid)
    {
        $media_data = Medias::where('user_id', Auth::user()->id)->where('id', $mid)->first();
        if ($media_data != null) {
            // Get media details
            $mediaDetails = Medias::where('user_id', Auth::user()->id)->where('id', $mid)->first();

            // Delete (local) media image
            $optimized_image = str_replace('/storage/media/files/' . Auth::user()->id . '/', '', $mediaDetails->media_url);

            // Check s3
            if (substr($optimized_image, 0, 5) == "https") {
                try {
                    // Delete s3 image
                    Storage::disk('s3')->delete(str_replace(Storage::disk('s3')->url('.'), '', $mediaDetails->media_url));
                } catch (\Throwable $th) {
                    //throw $th;
                }
                // Delete wasabi image
                Storage::disk('wasabi')->delete(str_replace(Storage::disk('wasabi')->url('.'), '', $mediaDetails->media_url));
            } else {
                unlink(public_path('storage/media/files/' . Auth::user()->id . '/' . $optimized_image));
            }

            // Delete media
            Medias::where('user_id', Auth::user()->id)->where('id', $mid)->delete();

            // Page redirect
            return redirect()->route('user.media')->with('success', trans('Media file removed!'));
        } else {
            // Page redirect
            return redirect()->route('user.media')->with('failed', trans('Media not found!'));
        }
    }

    // Bulk Delete
    public function bulkDeleteMedia(Request $request)
    {
        // Update status
        Medias::whereIn('id', explode(',', $request->query('id')))->where('user_id', Auth::user()->id)->update(['status' => 0]);

        return redirect()->route('user.media')->with('success', trans('Media Deleted Successfully!'));
    }

    // Bulk Download
    public function bulkDownloadMedia(Request $request)
    {
        // Queries
        $optimize_details = Medias::whereIn('id', explode(',', $request->query('id')))->where('user_id', Auth::user()->id)->get();

        $downloads = [];
        $folderName = str_replace(" ", "-", config('app.name'));
        $zipName = Str::lower($folderName) . '-' . uniqid() . '.zip'; // Name of our archive to download

        // Initializing PHP class
        $zip = new \ZipArchive();
        $zip->open($zipName, \ZipArchive::CREATE | \ZipArchive::OVERWRITE);

        if (isset($optimize_details)) {
            for ($i=0; $i < count($optimize_details); $i++) { 
                if (substr($optimize_details[$i]->media_url, 0, 5) != "https") {
                    // Download optimized image
                    $file_name = public_path($optimize_details[$i]->media_url);
    
                    $zip->addFile($file_name, $optimize_details[$i]->media_name);
                } else {
                    // Download optimized image
                    $path = public_path($optimize_details[$i]->media_url);
                    Storage::disk('local')->put($optimize_details[$i]->media_name, file_get_contents($path));
    
                    // Path
                    $downloads[$i] = Storage::path($optimize_details[$i]->media_name);

                    // Adding file: second parameter is what will the path inside of the archive
                    // So it will create another folder called "storage/" inside ZIP, and put the file there.
                    $zip->addFile($downloads[$i], $optimize_details[$i]->media_name);

                }
            }
        } else {
            return redirect()->route('user.media')->with('failed', trans('Image Not Found!'));
        }

        $zip->close();

        // We return the file immediately after download
        return response()->download($zipName);
    }
}
