<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Jobs\ProcessSearch;
use App\Libs\Backoffice\Generic\UriHelper;
use App\Libs\Events\ContentTypeRestored;
use App\Libs\Facades\ContentTypes;
use App\Libs\Facades\Localization;
use Illuminate\Pagination\Paginator;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use WebsiteObject;
use Str;
use Throwable;
use WebsiteObjectLanguage;

class TrashController extends Controller
{
    public function view()
    {
        return view('admin/pages/trash');
    }

    public function list()
    {
        $website = Localization::getWebsite();
        $page = request()->input("current");
        $sort = request()->input("sort");
        $search = request()->input("searchPhrase");

        if (!empty($page)) {
            Paginator::currentPageResolver(function () use ($page) {
                return $page;
            });

            $query = WebsiteObject::where('website_id', $website->id)->onlyTrashed();

            if (!empty($search)) {
                $query->whereHasMorph('objectable', '*', function ($query) use ($search) {
                    $query->withTrashed()->lang()->where('title', 'like', "%$search%");
                });
            }

            if (empty($sort)) {
                $rows = $query->paginate(request()->input("rowCount"));
            } else {
                foreach ($sort as $field => $direction) {
                    if (empty($direction) || !Str::is(strtolower($direction), "desc")) {
                        $order_direction = "asc";
                    }
                    $rows = $query->orderBy($field, strtolower($direction))->paginate(request()->input("rowCount"));
                    break;
                }
            }

            $collection = $rows->getCollection();

            foreach ($collection as $row) {
                $row->title = $row->objectable()->withTrashed()->get()->get(0)->title;
            }
            $result = array(
                "total" => $rows->total(),
                "current" => $rows->currentPage(),
                "rowCount" => request()->input("rowCount"),
                "rows" => $collection
            );

            return response()->json($result);
        }
    }

    public function restore($websiteObjectId)
    {
        $websiteObject = WebsiteObject::onlyTrashed()->where('website_object_id', $websiteObjectId)->first();
        if (!$websiteObject) {
            return response()->json([
                'success' => false,
                'error' => 'Object not found!'
            ], 200);
        }

        DB::beginTransaction();
        try {
            $restoreModel = $websiteObject->objectable()->withTrashed()->get()->get(0);
            $contentType = ContentTypes::find($websiteObject->content_type);

            $websiteObject->restore();
            $restoreModel->restore();
            $restoreModel->refresh();
            $restoreCode = random_string('alnum', 3);
            foreach ($websiteObject->languages as $wol) {
                $slugRestore = substr($wol->lang_slug, 8);
                if (WebsiteObjectLanguage::where('lang_slug', $slugRestore)->where('wo_language_id', $wol->wo_language_id)->count() > 0) {
                    $slugRestore = $slugRestore . '-restored-' . $restoreCode;
                }
                $wol->lang_slug = $slugRestore;
                $wol->save();
            }

            $slugRestore = substr($websiteObject->slug, 8);
            if (WebsiteObject::where('slug', $slugRestore)->count() > 0) {
                $slugRestore = $slugRestore . '-restored-' . $restoreCode;
            }
            $websiteObject->slug = $slugRestore;
            $websiteObject->save();
            UriHelper::updateUri($websiteObject, $restoreModel, $contentType);
            ProcessSearch::dispatch($contentType, $restoreModel, true, $websiteObject->website_id);
            ContentTypeRestored::dispatch($restoreModel);
            DB::commit();
        } catch (Throwable $e) {
            DB::rollback();
            Log::error($e);
            return response()->json([
                'success' => false,
                'error' => $e->getMessage()
            ], 200);
        }

        return response()->json([
            'success' => true
        ], 200);
    }

    public function delete($websiteObjectId)
    {
        $websiteObject = WebsiteObject::onlyTrashed()->where('website_object_id', $websiteObjectId)->first();
        if (!$websiteObject) {
            return response()->json([
                'success' => false,
                'error' => 'Object not found!'
            ], 200);
        }

        DB::beginTransaction();
        try {
            $websiteObject->objectable()->withTrashed()->get()->get(0)->forceDelete();
            $websiteObject->forceDelete();
            $this->cleanWebsiteObjects();
            DB::commit();
        } catch (Throwable $e) {
            DB::rollback();
            Log::error($e);
            return response()->json([
                'success' => false,
                'error' => $e->getMessage()
            ], 200);
        }

        return response()->json([
            'success' => true
        ], 200);
    }

    /**
     * Cleans the website objects table for objects that got deleted by database
     * foreign key cascade deletes
     *
     */
    protected function cleanWebsiteObjects()
    {
        $contentTypes = ContentTypes::all();

        foreach ($contentTypes as $contentType) {
            $modelType = $contentType->getModelType();
            $model = new $modelType();
            $table = $model->getTable();

            $toDelete = WebsiteObject::where('content_type', $contentType->getType())
                ->whereNotExists(function ($query) use ($table) {
                    $query->select(DB::raw(1))
                        ->from($table)
                        ->whereRaw(WebsiteObject::getTableName().".object_id = {$table}.id");
                })->delete();
        }
    }
}
