<?php

namespace App\Http\Controllers\Frontend;

use App\Http\Controllers\Controller;
use App\Libs\Exception\InvalidConfigurationException;
use App\Libs\Facades\Localization;
use App\Libs\Facades\RequestContext;
use App\Libs\Services\RedirectService;
use App\Libs\Support\SitemapGenerator;
use App\Models\CodeEmbed;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\URL;
use stdClass;
use App\Models\VisitorPageView;
use App\Models\VisitorSession;
use App\Models\WebsiteObject;
use App\Models\MediaItem;
use App\Models\ShareLink;
use App\Models\WebsiteObjectLanguage;

class GenericController extends Controller
{
    protected RedirectService $redirectService;

    public function __construct(RedirectService $redirectService)
    {
        $this->redirectService = $redirectService;
    }

    /*
    | Default controller - grabs all unattended routes and tries to fulfill
    | the request by looking to the backoffice generic pages
    */
    public function getIndex(Request $request, $uriPath = '')
    {
        $uri = '/'.$uriPath;

        //If root, $parameters comes with 2 empty strings (don't know why) so we improvise
        $uri = $uri == '//' ? '/' : $uri;

        $website = Localization::getWebsite();
        $lang = Localization::getActiveLocale();
        $availableLanguages = Localization::getSupportedLanguages()->keyBy('id');

        $redirectUri = $this->redirectService->getRedirect('/' . $request->path());

        if ($redirectUri) {
            return redirect($redirectUri['target'], $redirectUri['type']);
        }

        $isPreview = false;
        $shareLink = null;

        if (strpos($uri, '/_preview/') === 0 && strlen($uri) == 42) {
            $token = substr($uri, 10);
            $shareLink = ShareLink::where('token', $token)->first();
            RequestContext::set('no_cache', true);

            if (!$shareLink) {
                abort(404);
            }

            if ($shareLink->expires_at < now()) {
                return view('frontend.templates.page.preview-expired');
            }

            if ($shareLink->data['language'] != $lang) {
                abort(404);
            }

            $wo = WebsiteObject::find($shareLink->data['websiteObjectId']);
            if (!$wo) {
                abort(404);
            }
            $uri = $shareLink->data['lang_uri'];
            $uriPath = substr($uri, 1);
            $isPreview = true;
        }

/*
        $websiteObject = WebsiteObject::whereRaw("? like concat(lang_uri, '/%')", array($uri.'/'))
            ->where('website_id', $website->id)
            ->whereNotNull('template')
            ->join('website_objects_lang', 'website_objects_lang.website_object_id', '=',
                'website_objects.website_object_id')
            ->where('website_objects_lang.wo_language_id', $lang)
            ->where('website_objects_lang.wo_website_id', $website->id)
            ->orderByRaw("(length( lang_uri ) - length( replace(lang_uri, '/', ''))) desc")
            ->orderByRaw("length(lang_uri) desc")
            ->first();
*/

        $websiteObjectLang = WebsiteObjectLanguage::fromRaw('website_objects_lang USE INDEX (wo_lang_uri_index)')
            ->whereRaw("? like concat(lang_uri, '/%')", array($uri.'/'))
            ->join('website_objects', 'website_objects_lang.website_object_id', '=',
                'website_objects.website_object_id')
            ->where('website_id', $website->id)
            ->whereNotNull('template')
            ->where('website_objects_lang.wo_language_id', $lang)
            ->where('website_objects_lang.wo_website_id', $website->id)
            ->orderByRaw("(length( lang_uri ) - length( replace(lang_uri, '/', ''))) desc")
            ->orderByRaw("length(lang_uri) desc")
            ->first();

        if (!$websiteObjectLang) {
            abort(404);
        }

        $user = Auth::guard('admin')->user();

        if ($websiteObjectLang->status != 'published' && !$user && !$isPreview) {
            abort(404);
        }

        $websiteObject = WebsiteObject::find($websiteObjectLang->website_object_id);

        //Gets alternative language uris
        $langUris = [];
        $translatedUris = [];
        if ($website->languages->count() > 1) {
            $langWOs = DB::table('website_objects_lang AS wo1')
                ->select(array('wo1.wo_language_id', 'wo1.lang_uri', 'wo1.lang_status'))
                ->join('website_objects_lang AS wo2', 'wo1.website_object_id', '=', 'wo2.website_object_id')
                ->join('website_objects AS wo', 'wo.website_object_id', '=', 'wo2.website_object_id')
                ->join('website_language AS wl', 'wl.language_id', '=', 'wo1.wo_language_id')
                ->where('wl.website_id', $website->id)
                ->where('wl.is_active', true)
                ->where('wo.website_id', $website->id)
                ->where('wo2.lang_uri', $uri)
                ->where('wo2.wo_language_id', $lang)
                ->whereNull('wo.deleted_at')
                ->get();

            foreach ($langWOs as $langWO) {
                $langUris[$langWO->wo_language_id] = $langWO->lang_uri;
                if (!empty($availableLanguages[$langWO->wo_language_id]) && $langWO->lang_status === 'published') {
                    $translatedUris[$langWO->wo_language_id] = $langWO->lang_uri;
                }
            }
        }

        if ($websiteObjectLang->lang_status != 'published' && !$user && !$isPreview) {
            if (!empty($translatedUris)) {
                RequestContext::set('is_missing_translation', true);
                RequestContext::set('translated_uris', $translatedUris);
            }
            RequestContext::set('no_cache', true);
            abort(404);
        }

        $contentType = $websiteObjectLang->content_type;
        $templateId = $websiteObjectLang->template;

        $template = config('backoffice.generic.'.$contentType.'.templates.'.$website->id.'.'.$templateId);

        if (!$template) {
            throw new InvalidConfigurationException("You must provide a configuration");
        }

        $allowedParameters = 0;
        if (isset($template['parameters'])) {
            $allowedParameters = $template['parameters'];
        }
        $inputParameters = sizeof(explode('/', $uri)) - sizeof(explode('/', $websiteObjectLang->uri));

        if ($allowedParameters < $inputParameters) {
            abort(404);
        }

        if (!empty($template['blocks']) && $template['blocks'] && $inputParameters == 0) {
            $object = $websiteObject->objectable()->withBlocks()->first();
        } else {
            $object = $websiteObject->objectable;
        }

        $objectEmbeds = null;
        $metaData = null;
        if ($inputParameters > 0 && isset($template['detailView'])) {
            $view = $template['detailView'];
            RequestContext::set('no_cache', $user != null || $isPreview);
        } else {
            RequestContext::set('no_cache', $object->no_cache || $user != null || $isPreview);
            if (!isset($template['view'])) {
                abort(404);
            }
            $view = $template['view'];
            if ($object->codeEmbeds) {
                $objectEmbeds = $object->codeEmbeds;
            }
            $metaData = new stdClass();
            if ($object->meta_title) {
                $metaData->meta_title = $object->meta_title;
            } else {
                $metaData->meta_title = cut_string(strip_tags($object->title), 100);
            }
            if ($object->meta_description) {
                $metaData->meta_description = $object->meta_description;
            } else {
                $metaData->meta_description = cut_string(strip_tags($object->summary), 200);
            }
            if ($object->no_index) {
                $metaData->no_index = true;
            }

            $metaData->meta_keywords = $object->meta_keywords;

            if ($object->metaImage) {
                $metaData->metaImage = getMediaUrl($object->metaImage->filename, '600x600');
            } else {
                $image = MediaItem::find($object->image_id);
                if(!is_null($image)) {
                    $metaData->metaImage = getMediaUrl($image->filename, '600x600');
                }
            }
        }

        // if ($website->track_pages) {
        //    $this->_pageView($website, $websiteObjectLang);
        // }

        $stickyCta = null;
        if ($contentType == 'page') {
            if ($object->stickyCta) {
                $stickyCta = $object->stickyCta;
            }
        }

        $embeds = CodeEmbed::full()
            ->where('status', 'published')
            ->where('global', true)
            ->orderBy('position', 'asc')
            ->get();

        return view($view)
            ->with(array(
                'object' => $object,
                'websiteObject' => $websiteObject,
                'parameters' => explode('/', $uriPath),
                'objectEmbeds' => $objectEmbeds,
                'embeds' => $embeds,
                'metaData' => $metaData,
                'langUris' => $langUris,
                'stickyCta' => $stickyCta,
                'translatedUris' => $translatedUris,
                'isPreview' => $isPreview,
                'shareLink' => $shareLink
            ));
    }

    public function sitemap()
    {
        $website = Localization::getWebsite();

        $sitemapFilename = 'sitemap_'.$website->id.'.xml';

        if (!Storage::has($sitemapFilename)
            || (Storage::lastModified($sitemapFilename) + 24 * 60 * 60) < time()) {
            $sitemapGenerator = new SitemapGenerator();
            $sitemapGenerator->buildSitemap();
        }

        return response()->make(Storage::get($sitemapFilename), '200')
            ->header('Content-Type', 'text/xml');
    }

    public function robots()
    {
        $website = Localization::getWebsite();

        $robotsFilename = 'robots_'.$website->id.'.txt';

        if (!Storage::has($robotsFilename)) {
            abort(404);
        }

        return response()->make(Storage::get($robotsFilename), '200')
            ->header('Content-Type', 'text/txt');
    }

    private function _pageView($website, $object)
    {
        $token = request()->cookie('visitor_token');
        if (!$token) {
            return;
        }

        $visitor = $website->getVisitorByToken($token);
        if (!$visitor) {
            return;
        }

        $limitDate = now();
        $limitDate->subMinutes(config('app.cfSessionTimeout'));
        $session = VisitorSession::where('visitor_id', $visitor->id)
            ->whereExists(function ($query) use ($limitDate) {
                $query->select(DB::raw(1))
                    ->from('visitor_page_views')
                    ->whereRaw('visitor_page_views.session_id = sessions.id')
                    ->whereRaw("visitor_page_views.created_at >= '{$limitDate}'");
            })
            ->orderBy('id', 'desc')
            ->first();

        if (!$session) {
            $session = new VisitorSession();
            $session->visitor_id = $visitor->id;
            $session->visit_number = VisitorSession::where('visitor_id', $visitor->id)->count() + 1;
            $session->save();
        }

        $pageView = new VisitorPageView();
        $pageView->visitor_id = $visitor->id;
        $pageView->session_id = $session->id;
        if ($object) {
            $pageView->website_object_id = $object->id;
        }
        $pageView->request_url = request()->url();
        $pageView->page = request()->path(); // Request::server('REQUEST_URI');

        $pageView->referer_url = request()->server('HTTP_REFERER');
        if ($pageView->referer_url) {
            $pageView->referer_page = str_replace(url(''), '', substr($pageView->referer_url, 0, 255));
        }

        $pageView->ip = request()->server('REMOTE_ADDR');
        $pageView->save();
    }

    /*
    public function getRecoverFolder () {
        $folderId = Config::get('google.vacanciesAppsFolderId');
        $drive = Google::make('drive');
        $q = "name = 'Job 78'";
        $q.= " and mimeType = 'application/vnd.google-apps.folder'";
        $q.= " and '$folderId' in parents";

        $files = $drive->files->listFiles (array(
            'q' => $q,
            'spaces' => 'drive',
            'fields' => 'files(id, name)'
        ));
        $foundId = null;
        foreach ($files as $f) {
            echo $f->name . ' ';
            $foundId = $f->id;
            break;
        }
        $drive = Google::make('drive');
        $userPermission = new Google_Service_Drive_Permission(array(
            'type' => 'user',
            'role' => 'writer',
            'emailAddress' => 'd.schmid@southpolecarbon.com'
          ));
        $drive->permissions->create($foundId, $userPermission, array('fields' => 'id'));
        return $foundId;
    }
    */
}
