<?php

namespace App\Http\Controllers\User;

use ZipArchive;
use Carbon\Carbon;
use App\Models\Plan;
use App\Models\User;
use App\Models\Optimer;
use App\Models\Setting;
use App\Classes\S3Storage;
use Illuminate\Support\Str;
use Illuminate\Http\Request;
use App\Classes\LocalStorage;
use App\Classes\WasabiS3Storage;
use App\Classes\BackblazeS3Storage;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\File;
use Intervention\Image\Facades\Image;
use Illuminate\Support\Facades\Storage;

class OptimerController 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 Optimer
    public function indexAllOptimer()
    {
        // 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 User Optimer
            $optimers = Optimer::where('uploaded_by', Auth::user()->id)->where('status', 1)->orderBy('id', 'desc')->paginate(12);
            $settings = Setting::where('status', 1)->first();

            // Get today optimize images
            $today_optimized_images = Optimer::where('uploaded_by', Auth::user()->id)->whereDate('created_at', Carbon::today())->count();

            // Get today optimize image size
            $today_optimized_image_size = Optimer::where('uploaded_by', Auth::user()->id)->whereDate('created_at', Carbon::today())->sum('optimized_image_size');

            // Get overall optimize image size
            $overall_optimized_image_size = Optimer::where('uploaded_by', Auth::user()->id)->sum('optimized_image_size');

            // View page
            return view('user.pages.optimer.index', compact('optimers', 'settings', 'today_optimized_images', 'today_optimized_image_size', 'overall_optimized_image_size'));
        } else {
            // Page redirect
            return redirect()->route('user.plans');
        }
    }

    // Create Optimer
    public function CreateOptimer()
    {
        // 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();

        // 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,';
        }

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

        if ($validity == 1) {
            // Check user created optimers count
            if ($optimers_counts < $maximum && $optimers_size < $plan_details->storage) {
                return view('user.pages.optimer.create', compact('plan_details'));
            } else {
                return redirect()->route('user.all.optimer')->with('failed', trans('Maximum optimer creation limit / storage is exceeded, Please upgrade your plan.'));
            }
        } else {
            // Redirect
            return redirect()->route('user.all.optimer')->with('failed', trans('Your plan is over. Choose your plan renewal or new package and use it.'));
        }
    }

    // Save Optimer
    public function saveOptimer(Request $request)
    {
        // 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;
        }

        if ($validity == 1) {
            // Check storage available
            if ($optimers_counts < $maximum && $optimers_size < $plan_details->storage) {
                // Check s3 available
                if (env('AWS_ENABLE') == 'on') {
                    if ($plan_details->s3 == 0) {
                        $storage = new LocalStorage;
                        $storage->localFunction($request);
                    } else {
                        $storage = new S3Storage;
                        $storage->s3Function($request);
                    }
                } else if (env('WAS_ENABLE') == 'on') {
                    if ($plan_details->s3 == 0) {
                        $storage = new LocalStorage;
                        $storage->localFunction($request);
                    } else {
                        $storage = new WasabiS3Storage;
                        $storage->wasabiFunction($request);
                    }
                } else if (env('BACK_ENABLE') == 'on') {
                    if ($plan_details->s3 == 0) {
                        $storage = new LocalStorage;
                        $storage->localFunction($request);
                    } else {
                        $storage = new BackblazeS3Storage;
                        $storage->backBlazeFunction($request);
                    }
                } else {
                    $storage = new LocalStorage;
                    $storage->localFunction($request);
                }

                return response()->json(['status' => 'success', 'message' => trans('Image has been optimized successfully')]);
            } else {
                return response()->json(['status' => 'failed', 'message' => trans('Maximum optimer creation 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.')]);
        }
    }


    // Download Optimer
    public function downloadOptimer($id)
    {
        // Queries  
        $optimize_details = Optimer::where('id', $id)->where('uploaded_by', Auth::user()->id)->first();

        if (isset($optimize_details)) {
            if ($optimize_details->disk == 'local') {
                // Download optimized image
                $file_name = str_replace('/storage/files/' . Auth::user()->id . '/optimize/', '', $optimize_details->optimized_image);

                return response()->download('storage/files/' . Auth::user()->id . '/optimize/' . $file_name);
            } else {
                // Download optimized image
                $path = $optimize_details->optimized_image;
                Storage::disk('local')->put($optimize_details->name, file_get_contents($path));

                // Path
                $path = Storage::path($optimize_details->name);

                return response()->download($path);
            }
        } else {
            return redirect()->route('user.all.optimer')->with('failed', trans('Image Not Found!'));
        }
    }

    // Bulk Download
    public function bulkDownload(Request $request)
    {
        // Queries
        $localImages = Optimer::whereIn('id', explode(',', $request->query('id')))->where('disk', 'local')->where('uploaded_by', Auth::user()->id)->get('optimized_image');
        $s3Images = Optimer::whereIn('id', explode(',', $request->query('id')))->where('disk', '!=', 'local')->where('uploaded_by', Auth::user()->id)->get('optimized_image');

        // Local Images
        $arrayConverterOfLocal = [];
        foreach ($localImages->toArray() as $localImage) {
            array_push($arrayConverterOfLocal, public_path($localImage['optimized_image']));
        }

        // S3 Images
        $arrayConverterOfS3 = [];
        foreach ($s3Images->toArray() as $s3Image) {
            array_push($arrayConverterOfS3, $s3Image['optimized_image']);
        }

        $files = [];

        // Specify multiple folders within the public directory
        $publicFolders = $arrayConverterOfLocal;

        // Iterate over each folder and add images to the files array
        foreach ($publicFolders as $folder) {
            $folderFiles = glob($folder);
            $files = array_merge($files, $folderFiles);
        }

        // Add images from Backblaze S3 URL to the files array
        $s3Urls = $arrayConverterOfS3;

        foreach ($s3Urls as $url) {
            $fileContent = file_get_contents($url);
            $fileName = basename($url);

            $tempDirectory = public_path('temp');

            // Create the directory if it doesn't exist
            if (!is_dir($tempDirectory)) {
                mkdir($tempDirectory, 0755, true);
            }

            $tempFilePath = $tempDirectory . "/{$fileName}";
            file_put_contents($tempFilePath, $fileContent);
            $files[] = $tempFilePath;
        }

        // Generate a unique random ZIP file name
        $folderName = str_replace(" ", "-", config('app.name'));

        $uniqueZipName = Str::lower($folderName) . '-' . uniqid() . '.zip';
        $zipDirectory = public_path();
        $zipFilePath = $zipDirectory . "/" . $uniqueZipName;

        // Ensure the directory exists
        if (!is_dir($zipDirectory)) {
            mkdir($zipDirectory, 0755, true);
        }

        // Create a zip file
        $zip = new ZipArchive();
        $zip->open($zipFilePath, ZipArchive::CREATE | ZipArchive::OVERWRITE);

        foreach ($files as $file) {
            $zip->addFile($file, basename($file));
        }

        $zip->close();

        // Download the zip file
        return response()->download($zipFilePath)->deleteFileAfterSend(true);
    }

    // Delete Optimer
    public function deleteOptimer(Request $request)
    {
        // Update status
        Optimer::where('id', $request->query('id'))->where('uploaded_by', Auth::user()->id)->update(['status' => 0]);
        return redirect()->route('user.all.optimer')->with('success', trans('Image Deleted Successfully!'));
    }

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

        return redirect()->route('user.all.optimer')->with('success', trans('Images Deleted Successfully!'));
    }

    // Download Image
    public function downloadImage(Request $request)
    {
        // Parameters
        $name = $request->query('name');
        $url = $request->query('image');
        $format = $request->query('format');

        // Remove extensions
        $extensions = array('.jpg', '.jpeg', '.png', '.gif', '.webp');
        foreach ($extensions as &$str) {
            $name = str_replace($str, '', $name);
        }

        // Check url
        if (substr($url, 0, 5) == "https") {
            $url = $url;
        } else {
            $url = public_path($url);
        }

        // Convert
        Image::make($url)->encode($format, 100)->save(public_path('storage/files/' . Auth::user()->id . '/'  .  $name . '.' . $format));

        // Download image path
        $downloadImage = public_path('storage/files/' . Auth::user()->id . '/'  .  $name . '.' . $format);

        return response()->download($downloadImage)->deleteFileAfterSend(true);
    }
}
