<?php

namespace App\Http\Controllers\Admin;

use App\Events\SaveDataEvent;
use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\SliderDetail;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use App\Slider;
use App\Media;
use App\Http\Resources\Admin\SliderResource;
use Intervention\Image\Exception\NotReadableException;
use Validator;
use ImageCross;

/**
 * Class SliderController
 *
 * @package App\Http\Controllers
 */
class SliderController extends Controller
{
    const ITEM_PER_PAGE = 100;
    private $_pathFile;
    private $_mediaPath;
    private $_pathTemp;
    private $_imageTellerPath;

    public function __construct()
    {
        $this->_pathFile = public_path('uploads/image/slider/');
        $this->_mediaPath = public_path('uploads/files/');
        $this->_imageTellerPath = public_path('uploads/image/fortune/');
        $this->_pathTemp = storage_path('app/public/uploads/temp/image/');
    }

    public function index(Request $request)
    {
        $searchParams = $request->all();
        $list = Slider::notDeleted();
        $limit = Arr::get($searchParams, 'limit', static::ITEM_PER_PAGE);
        $keyword = Arr::get($searchParams, 'keyword', '');
        $status = Arr::get($searchParams, 'status', '');

        if (!empty($keyword)) {
            $list->where('name', 'LIKE', '%' . $keyword . '%');
        }

        if ($status != '') {
            $list->where('is_activated', $status);
        }

        $list->orderBy('position')->orderBy('id');

        return SliderResource::collection($list->paginate($limit));
    }

    public function all()
    {
        $list = Slider::select('*')->notDeleted()->orderBy('position')->orderBy('id');

        return SliderResource::collection($list->get());
    }

    public function show($id = 0)
    {
        $slider = Slider::notDeleted()->where('id', $id)->first();
        if (!isset($slider)) return response()->json(['errors' => 'Slider is not valid'], 403);

        return new SliderResource($slider);
    }

    public function store(Request $request)
    {
        $validator = Validator::make($request->all(), ['name' => ['required'], 'image' => ['required'], 'is_activated' => ['required']]);
        if ($validator->fails()) return response()->json(['errors' => $validator->errors()], 403);
        $params = $request->all();
        $position = Slider::count() + 1;

        $isInternalUrl = true;
        $url = trim($params['url']);
        $currentUrl = env('APP_URL');
        $domain = str_replace("http://", "", $currentUrl);
        $domain = str_replace("https://", "", $domain);

        if (!empty($url)) {
            if (str_starts_with($url, 'http://') || str_starts_with($url, 'https://')) {
                $temp = str_replace("https://", "", $url);
                $temp = str_replace("http://", "", $temp);
                if (str_starts_with($temp, $domain)) {
                    $url = str_replace($domain, "", $temp);
                } else {
                    $isInternalUrl = false;
                }
            } else {
                $url = str_replace($domain, "", $url);
                $url = "____/" . $url;
                $url = str_replace("____//", "/", $url);
                $url = str_replace("____/", "/", $url);
            }
        }

        $slider = Slider::create([
            'name'            => $params['name'],
            'image'           => $params['image'],
            'url'             => $url,
            'is_internal_url' => $isInternalUrl,
            'position'        => $position,
            'is_activated'    => ($params['is_activated'] === true) ? 1 : 0,
            'created_at'      => date('Y-m-d H:i:s'),
            'updated_at'      => date('Y-m-d H:i:s')
        ]);

        return new SliderResource($slider);
    }

    public function update($id = 0, Request $request)
    {
        $validator = Validator::make($request->all(), ['name' => ['required'], 'image' => ['required'], 'is_activated' => ['required']]);
        if ($validator->fails()) return response()->json(['errors' => $validator->errors()], 403);
        $slider = Slider::notDeleted()->where('id', $id)->first();
        if (!isset($slider)) return response()->json(['errors' => 'Slider is not valid'], 403);
        $params = $request->all();
        $isInternalUrl = true;
        $url = trim($params['url']);
        $currentUrl = env('APP_URL');
        $domain = str_replace("http://", "", $currentUrl);
        $domain = str_replace("https://", "", $domain);

        if (!empty($url)) {
            if (str_starts_with($url, 'http://') || str_starts_with($url, 'https://')) {
                $temp = str_replace("https://", "", $url);
                $temp = str_replace("http://", "", $temp);
                if (str_starts_with($temp, $domain)) {
                    $url = str_replace($domain, "", $temp);
                } else {
                    $isInternalUrl = false;
                }
            } else {
                $url = str_replace($domain, "", $url);
                $url = "____/" . $url;
                $url = str_replace("____//", "/", $url);
                $url = str_replace("____/", "/", $url);
            }
        }

        $slider->update([
            'name'            => $params['name'],
            'image'           => $params['image'],
            'url'             => $url,
            'is_internal_url' => $isInternalUrl,
            'is_activated'    => ($params['is_activated'] === true) ? 1 : 0,
            'updated_at'      => date('Y-m-d H:i:s')
        ]);

        return response()->json(null, 204);
    }

    public function destroy($id = 0)
    {
        $slider = Slider::notDeleted()->where('id', $id)->first();
        if (!isset($slider)) response()->json(['error' => 'Ehhh! Can not delete this slider'], 403);

        try {
            $slider->update(['is_deleted' => true]);
        } catch (\Exception $ex) {
            response()->json(['error' => $ex->getMessage()], 403);
        }
        event(new SaveDataEvent());

        return response()->json(null, 204);
    }

    public function destroyMultiple(Request $request)
    {
        $validator = Validator::make($request->all(), ['ids' => 'required']);
        if ($validator->fails()) return response()->json(['errors' => $validator->errors()], 403);
        $listIds = $request->get('ids', []);
        $sliderList = Slider::notDeleted()->whereIn('id', $listIds)->get();
        if ($sliderList->count() <= 0) response()->json(['error' => 'Slider is not valid.'], 403);
        try {
            Slider::notDeleted()->whereIn('id', $listIds)->update(['is_deleted' => true]);
        } catch (\Exception $ex) {
            response()->json(['error' => $ex->getMessage()], 403);
        }
        event(new SaveDataEvent());

        return response()->json(null, 204);
    }

    public function activateMultiple(Request $request)
    {
        $validator = Validator::make($request->all(), ['ids' => 'required']);
        if ($validator->fails()) return response()->json(['errors' => $validator->errors()], 403);
        $listIds = $request->get('ids', []);
        $sliderList = Slider::notDeleted()->whereIn('id', $listIds)->get();
        if ($sliderList->count() <= 0) response()->json(['error' => 'Slider is not valid.'], 403);
        try {
            Slider::notDeleted()->whereIn('id', $listIds)->update(['is_activated' => true]);
        } catch (\Exception $ex) {
            response()->json(['error' => $ex->getMessage()], 403);
        }
        event(new SaveDataEvent());

        return response()->json(null, 204);
    }

    public function deactivateMultiple(Request $request)
    {
        $validator = Validator::make($request->all(), ['ids' => 'required']);
        if ($validator->fails()) return response()->json(['errors' => $validator->errors()], 403);
        $listIds = $request->get('ids', []);
        $sliderList = Slider::notDeleted()->whereIn('id', $listIds)->get();
        if ($sliderList->count() <= 0) response()->json(['error' => 'Slider is not valid.'], 403);
        try {
            Slider::notDeleted()->whereIn('id', $listIds)->update(['is_activated' => false]);
        } catch (\Exception $ex) {
            response()->json(['error' => $ex->getMessage()], 403);
        }
        event(new SaveDataEvent());

        return response()->json(null, 204);
    }

    public function uploadImage(Request $request)
    {
        if (!$request->hasFile('image')) return response()->json(['status' => 'error', 'message' => 'Upload Fail.', 'file_name' => null], 403);
        $file = $request->file('image');
        $baseName = $file->getClientOriginalName();

        $mediaSlider = Media::where('name', 'Sliders')
            ->where('slug', 'sliders')
            ->where('type', 0)
            ->where('parent_id', 0)
            ->where('is_deleted', false)
            ->first();

        if (!isset($mediaSlider) || $mediaSlider->id == null) {
            $mediaSlider = Media::create([
                'name'       => 'Sliders',
                'slug'       => 'sliders',
                'file'       => md5('Sliders' . rand(1000, 100000)),
                'type'       => 0,
                'parent_id'  => 0,
                'is_deleted' => 0,
                'created_at' => date('Y-m-d H:i:s'),
                'updated_at' => date('Y-m-d H:i:s')
            ]);
        }

        try {
            $fileName = md5($baseName . rand(1111, 9999) . date('YmdHis')) . '.' . $file->getClientOriginalExtension();
            $imageCross = ImageCross::make($file)->orientate()->save($this->_mediaPath . $fileName);
            $imgWidth = $imageCross->width();
            $imgHeight = $imageCross->height();
            $imgSize = $imageCross->filesize();
            $fileType = $imageCross->mime();
            $extension = "." . $this->fileExtension($fileName);

            $baseName = str_replace($extension, "", $baseName);
            $baseName = $baseName . $extension;

            $slug = str_replace($extension, "", $fileName);
            $slug = str_replace(" ", "", $slug);
            $slug = str_replace(".", "", $slug);

            $extKey = "223344";
            $countBaseName = 0;
            $checkName = Media::where('is_deleted', 0)->where('parent_id', $mediaSlider->id)->where('name', $baseName)->count();
            $firstBaseName = str_replace($extension . $extKey, "", $baseName . $extKey);
            while ($checkName > 0) {
                $countBaseName += 1;
                $baseName = $firstBaseName . " (" . $countBaseName . ")" . $extension;
                $checkName = Media::where('is_deleted', 0)->where('parent_id', $mediaSlider->id)->where('name', $baseName)->count();
            }

            Media::create([
                'name'       => $baseName,
                'slug'       => $slug,
                'file'       => $fileName,
                'file_type'  => $fileType,
                'extension'  => $extension,
                'size'       => $this->formatBytes($imgSize),
                'width'      => $imgWidth,
                'height'     => $imgHeight,
                'type'       => 1,
                'parent_id'  => $mediaSlider->id,
                'is_deleted' => 0,
                'created_at' => date('Y-m-d H:i:s'),
                'updated_at' => date('Y-m-d H:i:s')
            ]);

            return response()->json(['status' => 'success', 'message' => 'Upload Success.', 'file_name' => $fileName, 'baseName' => $baseName], 200);
        } catch (\Exception $exception) {
            logger("[Error] Upload file: " . $exception->getMessage());
            return response()->json(['status' => 'error', 'message' => 'Upload Fail.', 'file_name' => null, 'baseName' => $baseName], 403);
        }
    }

    private function generateImage($itemStatus, $fileName, $itemUrlContent, $folderId)
    {
        try {
            if ($itemStatus != null && $itemStatus != "" && ($itemStatus == "edited" || $itemStatus == "choice")) {
                if ($itemStatus == "edited") {
                    $fileName = md5(date('YmdHis') . rand(1, 9999)) . '.jpg';
                    $imageCross = ImageCross::make($itemUrlContent)->orientate()->save($this->_mediaPath . $fileName);
                } else {
                    $imageCross = ImageCross::make($this->_mediaPath . $fileName)->orientate()->save($this->_mediaPath . $fileName);
                }

                $imgWidth = $imageCross->width();
                $imgHeight = $imageCross->height();
                $imgSize = $imageCross->filesize();
                $fileType = $imageCross->mime();
                $extension = "." . $this->fileExtension($fileName);

                $baseName = str_replace($extension, "", $fileName);
                $baseName = $baseName . $extension;

                $slug = str_replace($extension, "", $fileName);
                $slug = str_replace(" ", "", $slug);
                $slug = str_replace(".", "", $slug);

                $extKey = "223344";
                $countBaseName = 0;
                $checkName = Media::where('is_deleted', 0)->where('parent_id', $folderId)->where('name', $baseName)->count();
                $firstBaseName = str_replace($extension . $extKey, "", $baseName . $extKey);
                while ($checkName > 0) {
                    $countBaseName += 1;
                    $baseName = $firstBaseName . " (" . $countBaseName . ")" . $extension;
                    $checkName = Media::where('is_deleted', 0)->where('parent_id', $folderId)->where('name', $baseName)->count();
                }

                $checkMedia = Media::where('file', $fileName)->where('type', 1)->where('parent_id', $folderId)->first();
                if (!isset($checkMedia) || $checkMedia == null) {
                    Media::create([
                        'name'       => $baseName,
                        'slug'       => $slug,
                        'file'       => $fileName,
                        'file_type'  => $fileType,
                        'extension'  => $extension,
                        'size'       => $this->formatBytes($imgSize),
                        'width'      => $imgWidth,
                        'height'     => $imgHeight,
                        'type'       => 1,
                        'parent_id'  => $folderId,
                        'is_deleted' => 0,
                        'created_at' => date('Y-m-d H:i:s'),
                        'updated_at' => date('Y-m-d H:i:s')
                    ]);
                } else {
                    $checkMedia->update([
                        'slug'       => $slug,
                        'file'       => $fileName,
                        'file_type'  => $fileType,
                        'extension'  => $extension,
                        'size'       => $this->formatBytes($imgSize),
                        'width'      => $imgWidth,
                        'height'     => $imgHeight,
                        'type'       => 1,
                        'parent_id'  => $folderId,
                        'is_deleted' => 0,
                        'updated_at' => date('Y-m-d H:i:s')
                    ]);
                }
            }
            Helper::convertJpgToWebp($fileName);
        } catch (NotReadableException $exception) {
            logger("[Error] Image Cross: " . $exception->getMessage());
        } catch (\Exception $exception) {
            logger("[Error] Image Cross: " . $exception->getMessage());
        } finally {
            return $fileName;
        }
    }

    private function generateThumb($fileName, $width, $height)
    {
        if (file_exists($this->_pathFile . $fileName) && !file_exists($this->_pathFile . "thumb_{$width}x{$height}/" . $fileName)) {
            $imgCross = ImageCross::make($this->_pathFile . $fileName)->orientate();
            $imgCross->fit($width, $height, function ($constraint) {
                $constraint->upsize();
            })->save($this->_pathFile . "thumb_{$width}x{$height}/" . $fileName);
        }
    }

    private function detectLinkType($link)
    {
        $type = 0;
        if ($link != "" && strpos($link, "https://") === false && strpos($link, "http://") === false) {
            $link = "/" . $link;
            $link = str_replace("//", "/", $link);
            $type = 1;
        }

        return ['link' => $link, 'type' => $type];
    }

    private function fileExtension($s)
    {
        $n = strrpos($s, ".");
        return ($n === false) ? "" : substr($s, $n + 1);
    }

    private function formatBytes($bytes, $precision = 2)
    {
        $units = array('B', 'Kb', 'MB', 'GB', 'TB');
        $bytes = max($bytes, 0);
        $pow = floor(($bytes ? log($bytes) : 0) / log(1024));
        $pow = min($pow, count($units) - 1);
        $bytes /= pow(1024, $pow); //$bytes /= (1 << (10 * $pow));

        return round($bytes, $precision) . '' . $units[$pow];
    }

    public function position(Request $request)
    {
        if (!$request->has('position')) return response()->json(['errors' => 'Data is invalid'], 403);
        $newIndexes = $request->position;
        if (is_array($newIndexes)) {
            foreach ($newIndexes as $item) {
                Slider::where('id', $item['id'])->update(['position' => $item['order']]);
            }
        }

        return response()->json(null, 204);
    }
}
