<?php

namespace App\Http\Controllers\Admin;

use App\Facades\ContentTypes;
use App\Facades\RequestContext;
use App\Facades\Services\BackendUserService;
use App\Facades\Services\BackofficeService;
use App\Http\Controllers\Controller;
use App\Http\Requests\AdminContentAutoComplete;
use App\Models\GenericBackoffice\WebsiteObjectLanguage;
use Illuminate\Support\Facades\Validator;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Illuminate\Support\Arr;
use App\Models\MediaItem;

class ContentController extends Controller
{
    public function getIndex($type)
    {
        $contentType = ContentTypes::find($type);
        return view('admin.generic.pages.list', array("contentType" => $contentType));
    }

    public function postList($type)
    {
        $contentType = ContentTypes::find($type);

        //TODO implement form request
        $page = request()->input("current");
        $sort = request()->input("sort");
        $search = request()->input("searchPhrase");
        $rowCount = request()->input("rowCount");

        if (empty($sort) && $contentType->isOrderable() && !$contentType->isHierarchic()) {
            $sort = array("position" => "asc");
        }
        $list = $contentType->toList($page, $rowCount, $sort, $search);

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

    public function getForm($type, $id = false, $parentId = false, $parentContentType = false, $parentFieldName = false)
    {
        session()->forget("_old_input");

        $contentType = ContentTypes::find($type);

        if (!$contentType->userHasPermission()) {
            abort(403, trans("response.forbidden"));
        }

        $parentData = $contentType->getParent();

        if ($parentContentType && $parentFieldName) {
            $parentType = ContentTypes::find($parentContentType);
            $parentField = $parentType->getFields()->find($parentFieldName);
            if (!$parentField || $parentField->getObjectType() != $type) {
                abort(404, trans("response.not_found"));
            }

            $parentData = array(
                'field' => $parentFieldName,
                'contentType' => $parentContentType
            );
        }

        $modelType = $contentType->getModelType();

        if (!empty($id)) {
            $model = $modelType::find($id);

            if (is_null($model)) {
                abort(404, trans("response.not_found"));
            }

        } else {
            if (!$contentType->userHasPermission()) {
                abort(403, trans("response.forbidden"));
            }

            $modelType = $contentType->getModelType();
            $model = new $modelType;
        }
        if (!$model->exists && (!empty($parentId) && empty($parentData)) ||
            (empty($parentId) && !empty($parentData))) {
            abort(400, trans("response.bad_syntax"));
        }
        RequestContext::set('generic_form_timestamp', time());
        if (request()->ajax()) {
            return view('admin.generic.components.form',
                array(
                    "model" => $model,
                    "contentType" => $contentType,
                    "parentId" => $parentId
                ));
        } else {
            return view('admin.generic.pages.form',
                array(
                    "model" => $model,
                    "contentType" => $contentType,
                    "parentId" => $parentId
                ));
        }
    }

    public function postCheckSlug()
    {
        $originSlug = request()->input("slug");
        $langId = request()->input("lang");

        if (empty($originSlug) || empty($langId)) {
            return response()->json(array(
                "error" => "bad_syntax",
                "description" => "The request is missing the slug"
            ), 400);
        }
        $slug = BackofficeService::generateSlug($originSlug, $langId);

        if ($slug === false) {
            return response()->json(array(
                "error" => "invalid",
                "description" => "Impossible to generate this slug"
            ), 400);
        } else {
            return response()->json(array("slug" => $slug));
        }
    }

    public function postForm(
        $type,
        $id = false,
        $parentId = false,
        $parentContentType = false,
        $parentFieldName = false
    ) {
        $redirectTo = request()->input('redirect_to') !== '' ? request()->input('redirect_to') : null;
        $contentType = ContentTypes::find($type);

        if (!$contentType->userHasPermission()) {
            abort(403, trans("response.forbidden"));
        }

        $loggedUser = BackendUserService::getLoggedUser();
        if (!empty($id)) {
            $modelType = $contentType->getModelType();
            $model = $modelType::find($id);

            if (is_null($model)) {
                abort(404, trans("response.not_found"));
            }
        } else {
            $modelType = $contentType->getModelType();
            $model = new $modelType;
            $filters = $contentType->getFilters();
            foreach ($filters as $filter) {
                $model->$filter["field"] = $filter["value"];
            }
        }

        $parentData = $contentType->getParent();
        $hasPivot = false;

        if ($parentContentType && $parentFieldName) {
            $parentType = ContentTypes::find($parentContentType);
            $parentField = $parentType->getFields()->find($parentFieldName);
            if (!$parentField || $parentField->getObjectType() != $type) {
                abort(404, trans("response.not_found"));
            }

            $parentData = array(
                'field' => $parentFieldName,
                'contentType' => $parentContentType
            );
            $hasPivot = true;
        }

        if (!$model->exists && (!empty($parentId) && empty($parentData)) ||
            (empty($parentId) && !empty($parentData))) {
            abort(400, trans("response.bad_syntax"));
        }

        //TODO use Form Request?
        $validation = $contentType->getValidation(!$model->exists);

        $validator = Validator::make(
            $validation["values"],
            $validation["rules"]

        );

        $validator->setAttributeNames($validation["labels"]);

        $languages = getAvailableLanguages();
        foreach ($languages as $langCode => $lang) {
            $originSlug = $validation["values"]["lang_slug"][$langCode];
            if ($model->exists && $model->website_object_id) {
                $woLang = WebsiteObjectLanguage::where('website_object_id', $model->website_object_id)
                    ->where('wo_language_id', $langCode)
                    ->first();
                if ($woLang && $woLang->lang_slug == $originSlug) {
                    continue;
                }
            }
            $slug = BackofficeService::generateSlug($originSlug, $langCode);
            $validation["values"]["lang_slug"][$langCode] = ($slug ? $slug : '');
        }

        $validationFails = $validator->fails();
        $errors = $validator->errors();

        $mediaPickerErrors = [];

        // Eeters here if every rule passes
        if(!$validationFails) {
            // get Content type fields
            $contentTypeFields = $contentType->getFields();
            $mediaPickerFields = $contentTypeFields->filter(function ($value) {
                // get all mediaPicker fields in this ContentType
                return $value->getType() === 'mediaPicker' && $value->getAllowed();
            });
            foreach ($mediaPickerFields as $field) {
                // get the allowed extensions from the mediaPicker field
                $allowedExtensions = explode(',', $field->getAllowed());
                // get the ids of the media items
                $ids = json_decode(request()->input($field->getName()));
                // get the Media Item models
                $mediaItems = MediaItem::WhereIn('id', $ids)->get();
                foreach ($mediaItems as $mediaItem) {
                    // if the current media item extension is not in the allowed extensions
                    if (!in_array($mediaItem->extension, $allowedExtensions)) {
                        // manually add the error to the validator MessageBag
                        $errors->add($field->getName(), 'This extension is not allowed');
                        // set validationFails to true so it displays the messageBag errors
                        $validationFails = true;
                    }
                }
            }
        }

        if ($validationFails) {
            $errors = $validator->errors();
            RequestContext::set("errors",  $errors);
            view()->share("errors",  $errors);
            request()->flash();
            if (request()->ajax()) {
                return view('admin/generic/components/form',
                    array(
                        "model" => $model,
                        "contentType" => $contentType,
                        "parentId" => $parentId
                    ));
            } else {
                return view('admin/generic/pages/form',
                    array(
                        "model" => $model,
                        "contentType" => $contentType,
                        "parentId" => $parentId
                    ));
            }
        }

        BackofficeService::saveContentType(
            $contentType,
            $model,
            $validation["values"],
            $loggedUser,
            $parentData,
            $parentId,
            $hasPivot
        );

        $redirectUrl = request()->path();
        if ($id === false) {
            $redirectUrl .= "/".$model->id;
        }
        session()->forget("_old_input");
        if (request()->ajax()) {
            return response()->json(array(
                "id" => $model->id,
                "title" => $model->title,
                "website_object_id" => $model->website_object_id
            ));
        } else {
            //If has template and has template configuration, jumps to it

            if ($contentType->hasTemplate()) {
                $model->load('websites');
                $websiteObject = $model->websites->first();
                $objectTemplate = $contentType->getTemplates()[$websiteObject->template];
                if (isset($objectTemplate['contentType'])) {
                    $contentType = ContentTypes::find($objectTemplate['contentType']);
                    $parentData = $contentType->getParent();
                    if (empty($parentData)) {
                        abort(404, trans("response.not_found"));
                    }
                    $modelType = $contentType->getModelType();
                    $configModel = $modelType::where($parentData["field"], $model->id)->first();

                    if (!$configModel) {
                        $redirectUrl = 'admin/content/form-template/'.$objectTemplate['contentType'].'/'.$model->id;
                        return redirect()->to($redirectUrl);
                    }
                }
            }
            if ($redirectTo) {
                return redirect()->to($redirectTo)->withMessage(trans("backend.save_success"));
            } else {
                return redirect()->to($redirectUrl)->withMessage(trans("backend.save_success"));
            }
        }
    }

    public function postAutoComplete(AdminContentAutoComplete $request, $type)
    {

        $contentType = ContentTypes::find($type);
        $data = $request->validated();

        $results = $contentType->autoComplete($data['searchTerm']);

        return response()->json($results, 200);

    }

    public function deleteContentType($type, $id)
    {
        $contentType = ContentTypes::find($type);

        if (!$contentType->userHasPermission()) {
            abort(403, trans("response.forbidden"));
        }

        try {
            BackofficeService::deleteContentType($contentType, $id);
        } catch (NotFoundHttpException $e) {
            return response()->json(["success" => true]);
        }

        return response()->json(["success" => true]);
    }

    public function getOrder($type)
    {
        $contentType = ContentTypes::find($type);

        if (!$contentType->userHasPermission()) {
            abort(403, trans("response.forbidden"));
        }

        if ($contentType->isHierarchic()) {
            $entries = $contentType->toStructuredList();
        } else {
            $entries = $contentType->toList(null, null, array('position' => 'asc'))->all();
        }

        return view('admin.generic.pages.order', array(
            "contentType" => $contentType,
            "entries" => $entries
        ));
    }

    public function postOrder($type)
    {
        $contentType = ContentTypes::find($type);

        if (!$contentType->userHasPermission()) {
            abort(403, trans("response.forbidden"));
        }

        $newOrder = request()->input('content_order');
        $newOrder = json_decode($newOrder);

        if (!$newOrder || !is_array($newOrder)) {
            abort(400, trans("response.bad_syntax"));
        }

        try {
            BackofficeService::reorderContentType($contentType, $newOrder);
        } catch (BadRequestHttpException $e) {
            abort(400, trans("response.bad_syntax"));
        }

        if (request()->ajax()) {
            return response()->json(array("message" => "OK"));
        } else {
            $redirectUrl = 'admin/content/index/'.$type;
            return response()->redirectTo($redirectUrl)->withMessage(trans("backend.save_success"));
        }

    }

    public function getFormTemplate($type, $parentId)
    {

        $contentType = ContentTypes::find($type);

        if (!$contentType->userHasPermission()) {
            abort(403, trans("response.forbidden"));
        }

        $parentData = $contentType->getParent();

        if (empty($parentData)) {
            abort(404, trans("response.not_found"));
        }
        $modelType = $contentType->getModelType();
        $model = $modelType::where($parentData["field"], $parentId)->first();

        if (empty($model)) {
            $loggedUser = BackendUserService::getLoggedUser();
            $model = BackofficeService::createContentTypeTemplate($contentType, $parentId, $loggedUser);
        }
        $url = "/admin/content/form/{$type}/{$model->id}/{$parentId}";


        return response()->redirectTo($url);
    }


}
