<?php

namespace modules\listings\views;

use bff;
use tpl;
use Geo;
use HTML;
use Site;
use Users;
use Banners;
use Listings;
use Business;
use Response;
use Redirect;
use bff\view\Page;
use modules\listings\views\item\ClaimBlock;
use modules\users\views\profile\OnlineBlock;
use modules\listings\views\item\PromoteBlock;
use modules\listings\views\item\CommentsBlock;
use modules\listings\views\item\ControlsBlock;
use modules\listings\views\item\ContactFormBlock;
use modules\listings\views\item\SendfriendBlock;
use modules\listings\views\item\SimilarItemsBlock;
use modules\listings\views\item\ViewsStatisticBlock;

/**
 * Item Page
 * @copyright Tamaranga
 */
class ItemPage extends Page
{
    /** @var bool Item comments enabled */
    public $comments = true;
    /** @var bool Show Sharecode */
    public $sharecode = true;
    /** @var bool Show publication date */
    public $publicationDate = true;
    /** @var bool Gallery Images Width */
    public $mediaGalleryImagesWidth = 'auto';
    /** @var int Item Id */
    public $itemId = 0;
    /** @var array Item data */
    public $item = [];
    /** @var int Item Category Id */
    public $categoryId = 0;
    /** @var int Current user id */
    public $userId = 0;
    /** @var string Redirect from */
    public $from = '';
    /** @var bool Moderation mode */
    public $moderation = false;

    public function init()
    {
        parent::init();

        $this->setTemplate('item/page', 'listings');
        $this->setKey('view');
        $this->setTitle(_t('@listings', 'Listings / View'));
        $this->withSeoSettings('view', 'listings')->seotext();
        $this->useBreadcrumbs();
    }

    public static function handleRoute($id)
    {
        return (new static())->handle($id);
    }

    /**
     * Handle page request
     * @param int $id item id
     */
    public function handle($id)
    {
        $this->itemId = $id;
        $this->userId = $this->request->userId();
        if (! $id || ! $this->loadItem()) {
            return $this->errors->error404();
        }
        $this->from = $this->input->get('from', TYPE_STR);
        $this->moderation = Listings::moderationUrlKey($id, $this->input->get('mod', TYPE_STR));

        # Last Modified
        if (! $this->isDebug() && ! $this->userId && $this->request->isRobot()) {
            if (! $this->request->lastModified($this->item['modified'])) {
                return Response::notModified($this->item['modified']);
            }
        }

        # Url correction
        $this->request->urlCorrection($this->item['link']);

        return $this;
    }

    public function loadItem()
    {
        if (! empty($this->item)) {
            return true;
        }
        $this->item = Listings::model()->itemDataView($this->itemId);
        if (empty($this->item)) {
            return false;
        }

        # Item owner
        $this->item['owner'] = ($this->item['user_id'] && $this->userId && $this->userId == $this->item['user_id']);

        # Owner data
        $this->item['user'] = Users::model()->usersDataSidebar($this->item['user_id']);

        # Owner company data
        $this->item['company'] = [];
        if ($this->item['company_id'] && $this->item['user']['company_id'] && bff::businessEnabled()) {
            $this->item['company'] = Business::model()->companiesDataSidebar($this->item['user']['company_id']);
            if ($this->item['company']) {
                $this->item['name'] = $this->item['company']['title'];
            }
        }
        $this->item['is_company'] = ($this->item['company_id'] && $this->item['company']);

        # Add contacts from profile
        if (Listings::getItemContactsFromProfile()) {
            if ($this->item['is_company']) {
                $contactsData = &$this->item['company'];
            } else {
                $contactsData = &$this->item['user'];
                $this->item['name'] = ! empty($contactsData['name']) ? $contactsData['name'] : $contactsData['login'];
            }
            $contacts = [
                'contacts' => $contactsData['contacts'],
                'phones'   => [],
            ];
            if (! empty($contactsData['phones'])) {
                foreach ($contactsData['phones'] as $v) {
                    $contacts['phones'][] = $v['m'];
                }
            }
            $this->item['contacts'] = &$contacts;
            unset($contactsData);
            $this->item['contacts']['has'] = !empty($contacts['contacts']) || !empty($contacts['phones']);
        }

        # Categories
        $this->item['categories'] = Listings::categoryCrumbs($this->item['cat_id'], 'view', $this->item['city']['url'] ?? []);

        # Status
        $this->item['is_publicated'] = ($this->item['status'] == Listings::STATUS_PUBLICATED) && ! empty($this->item['is_publicated']);
        $this->item['is_publicated_out'] = ($this->item['status'] == Listings::STATUS_PUBLICATED_OUT);
        $this->item['is_blocked'] = ($this->item['status'] == Listings::STATUS_BLOCKED && ($this->item['owner'] || $this->moderation));

        # Shortcuts
        $this->item['is_business'] = ($this->item['owner_type'] == Listings::OWNER_BUSINESS);
        $this->item['is_map'] = ( ! empty($this->item['addr_addr']) && $this->item['addr_lat'] != 0 && $this->item['cat_addr'] );
        $this->item['city_title_delivery'] = $this->item['city']['title'] ?? '';
        if (!empty($this->item['regions_delivery']) && !empty($this->item['city_title'])) {
            $region = Geo::filter();
            $this->item['city_title_delivery'] = _t('listings', 'Delivery from [city]', [
                'city' => $this->item['city']['title'] ?? '',
                'filter_region' => $region['title'] ?? '',
            ]);
        }
        $this->item['is_soon_left'] = (
            $this->item['publicated_period'] > 0 &&
            ((strtotime($this->item['publicated_to']) - time()) < Listings::PUBLICATION_SOON_LEFT)
        );

        # Category
        $this->categoryId = $this->item['cat_id'] ?: 0;

        return true;
    }

    /**
     * Show status message only
     * @return bff\http\RedirectResponse|false|string
     */
    public function showStatusMessage()
    {
        if ($this->item['is_publicated']) {
            if (! $this->item['moderated'] && Listings::premoderation() && ! $this->moderation && ! $this->item['owner']) {
                return $this->forbiddenMessage(
                    _t('view', 'This listing is under moderation'),
                    _t('view', 'It will be published after verification')
                );
            }
            return false;
        }

        if ($this->item['status'] == Listings::STATUS_DELETED) {
            if (! empty($this->item['categories'])) {
                # возвращаем на список объявлений категории
                # в которой находилось данное объявление до удаления
                foreach (array_reverse($this->item['categories']) as $v) {
                    if ($v['id']) {
                        return Redirect::to($v['link']);
                    }
                }
                return Redirect::to(Listings::url('items.search', $this->item['city']['url'] ?? []));
            }

            return $this->forbiddenMessage(
                _t('view', 'View Listing'),
                _t('view', 'The listing was removed or blocked by the moderator')
            );
        }

        if (! $this->moderation) {
            if ($this->item['status'] == Listings::STATUS_BLOCKED && !$this->item['owner']) {
                return $this->forbiddenMessage(
                    _t('view', 'Listing blocked'),
                    _t('view', 'Reason for blocking:<br />[reason]', [
                        'reason' => nl2br($this->item['blocked_reason']),
                    ])
                );
            }
            if ($this->item['status'] == Listings::STATUS_NOTACTIVATED) {
                return $this->successMessage(
                    _t('view', 'View Listing'),
                    _t('view', 'The listing is not yet activated by the user')
                );
            }
            if (
                $this->item['moderated'] &&
                $this->item['status'] != Listings::STATUS_PUBLICATED_OUT &&
                $this->item['status'] != Listings::STATUS_BLOCKED &&
                !$this->item['owner']
            ) {
                return $this->forbiddenMessage(
                    _t('view', 'This listing is under moderation'),
                    _t('view', 'It will be published again after verification')
                );
            }
        }
        # Listings::STATUS_PUBLICATED_OUT => show unpublicated items
        return false;
    }

    public function data()
    {
        $data = parent::data();

        if (empty($this->item)) {
            return $this->errors->error404();
        }

        # Publication date
        if (! $this->publicationDate) {
            $this->item['created'] = '';
            $this->item['publicated'] = '';
            $this->item['publicated_last'] = '';
        }

        # Check item status
        $statusMessage = $this->showStatusMessage();
        if ($statusMessage !== false) {
            return $statusMessage;
        }

        # Images
        $images = Listings::itemImages($this->itemId);
        $data['images'] = $images->getData($this->item['imgcnt']);
        if (! empty($data['images'])) {
            $data['image_view'] = $images->getURL(reset($data['images']), $images::szView);
            $i = 1;
            foreach ($data['images'] as &$v) {
                $v['t'] = _t('view', '[title] [city] - photo [num]', [
                    'title' => $this->item['title'], 'city' => $this->item['city_title'], 'num' => $i++,
                ]);
                $v['url_small'] = $images->getURL($v, $images::szSmall);
                $v['url_view'] = $images->getURL($v, $images::szView);
                $v['url_zoom'] = $images->getURL($v, $images::szZoom);
            }
            unset($v);
        } else {
            $data['image_view'] = $images->urlDefault($images::szView);
        }

        # Video
        $this->item['video'] = Listings::itemVideo()->viewIframe($this->item['video_embed']);

        # Dynprops
        $data['dynprops'] = Listings::dp()->onView($this->item['cat_id'], $this->item, ['dataOnly' => -1]);
        $data['dynpropsBlock'] = $data['dynprops']['form'] ?: '';

        # Is favorite
        $data['fav'] = Listings::favorites()->isFavorite($this->itemId, $this->userId);

        # Increment views if not:
        # - owner
        # - redirect from admin panel
        # - page refresh
        if (!$this->item['owner'] && $this->from != 'adm' && !$this->request->isRefresh()) {
            if (Listings::model()->itemViewsIncrement($this->itemId, 'item', $this->item['views_today'])) {
                $this->item['views_total']++;
                $this->item['views_today']++;
            }
        }

        # Free top up
        if ($this->input->get('up_free', TYPE_UINT) == 1 && $this->item['owner']) {
            $up = Listings::itemServices('up');
            if ($up) {
                $msg = $up->upFree($this->itemId);
                if ($this->errors->no()) {
                    $data['msg_success'] = $msg;
                } else {
                    $data['msg_error'] = join('<br />', $this->errors->get());
                }
            }
        }

        $data['premoderation'] = Listings::premoderation();

        # Share code
        $data['sharecodeBlock'] = ($this->sharecode ? $this->config('sharecode', '', TYPE_STR) : '');

        # Banners query
        Banners::viewQuery($this->item['title']);

        # Merge data + item data
        foreach ($this->item as $key => $value) {
            $data[$key] = &$this->item[$key];
        }

        # Page data
        $this->view->setPageData([
            'listings_view_id' => $this->itemId,
            'listings_view_data' => &$data,
        ]);

        $data['descr'] = nl2br($data['descr']);

        return $data;
    }

    public function blocks()
    {
        $this->addMenu('listings.item');
        $this->addBlock('contactFormBlock', ContactFormBlock::class, function ($block) {
            $block->prerenderable(true);
        });
        $this->addBlock('claimBlock', ClaimBlock::class, function (ClaimBlock $block) {
            $block->itemId = $this->itemId;
            $block->itemOwner = $this->itemId && $this->item['owner'];
        });
        $this->addBlock('sendfriendBlock', SendfriendBlock::class, function (SendfriendBlock $block) {
            $block->itemId = $this->itemId;
        });
        $this->addBlock('viewsStatisticBlock', ViewsStatisticBlock::class, function (ViewsStatisticBlock $block) {
            $block->prerenderable(true);
            $block->itemId = $this->itemId;
            $block->itemOwner = $this->itemId && $this->item['owner'];
            $block->views_total = $this->item['views_total'] ?? 0;
            $block->views_today = $this->item['views_today'] ?? 0;
        });
        $this->addBlock('promoteBlock', PromoteBlock::class, function (PromoteBlock $block) {
            $block->prerenderable(true);
            $block->itemId = $this->itemId;
            $block->itemOwner = $this->itemId && $this->item['owner'];
        });
        $this->addBlock('commentsBlock', CommentsBlock::class, function (CommentsBlock $block) {
            if ($this->itemId) {
                $block->setSettings(Listings::itemComments()->getBlockSettings(
                    $this->itemId,
                    $this->userId,
                    [
                        'user_id' => $this->item['user_id'],
                        'company_id' => $this->item['company_id'],
                        'status' => $this->item['status'],
                    ],
                    $this->item['company'] ?? []
                ));
                $this->getMenu()->add('comments', _t('comments', 'Comments: [total]', [
                        'total' => $this->item['comments_cnt'] ?? 0,
                    ]))
                    ->first()
                    ->addBlock('comments', $block)
                    ->enabled(function () {
                        return $this->comments;
                    })
                    ->icon(bff::url('/img/icons/page-comments.svg'))
                    ->active(true)
                    ->end();
            }
        });
        $this->addBlock('similarBlock', SimilarItemsBlock::class, function (SimilarItemsBlock $block) {
            $block->prerenderable(true);
            if ($this->itemId && $this->item['is_publicated'] && ! $this->moderation) {
                $block->itemId = $this->itemId;
                $block->categories = array_filter(array_keys($this->item['categories']), function ($v) {
                    return ($v > 0);
                });
                $block->categoryType = $this->item['cat_type'];
                $block->regionId = Geo::filter('id');
            }
        });
        $this->addTemplateBlock('actionsTop', 'item/actions.top', 'listings');
        $this->addTemplateBlock('actionsBottom', 'item/actions.bottom', 'listings');
        $this->addTemplateBlock('alertsBlock', 'item/alerts', 'listings');
        $this->addTemplateBlock('mediaBlock', 'item/media', 'listings');
        $this->addTemplateBlock('vendorBlock', 'item/vendor', 'listings');
        $this->addTemplateBlock('contactsBlock', 'item/contacts', 'listings');
        $this->addBlock('onlineBlock', OnlineBlock::class, function (OnlineBlock $block) {
            $block->lastActivity = $this->item['user']['last_activity'] ?? false;
        });
        $this->addBlock('controlsBlock', ControlsBlock::class);
        $this->banners();
    }

    public function banners()
    {
        //
    }

    public function seo()
    {
        $data = &$this->data;

        $this->seo->canonicalUrl($this->item['link']);

        $metaCategories = [];
        $data['breadcrumb'] = [];
        foreach ($this->item['categories'] as $k => &$v) {
            if ($k) {
                $metaCategories[] = $v['title'];
            }
            $data['breadcrumb'][] = &$v['breadcrumb'];
        } unset($v);
        $this->seo->with([
            'id'                 => $this->itemId,
            'name'               => $this->item['name'],
            'title'              => $this->item['title'],
            'description'        => tpl::truncate($this->item['descr'], $this->config('listings.view.meta.description.limit', 150, TYPE_UINT)),
            'price'              => ($this->item['price_on'] ? $this->item['price'] . (!empty($this->item['price_mod']) ? ' ' . $this->item['price_mod'] : '') : ''),
            'address'            => (!empty($this->item['cat_addr']) && !empty($this->item['addr_addr']) ? $this->item['addr_addr'] : ''),
            'district'           => (!empty($this->item['district_data']['title']) ? $this->item['district_data']['title'] : ''),
            'category'           => $this->item['cat_title'],
            'categories'         => join(', ', $metaCategories),
            'categories.reverse' => join(', ', array_reverse($metaCategories, true)),
            'category+parent'    => join(', ', array_reverse(array_splice($metaCategories, (sizeof($metaCategories) > 2 ? sizeof($metaCategories) - 2 : 0)))),
        ]);

        # Region
        $this->seoMacrosRegionsData($this->item['geo_city']);

        # Dynprops
        $dynpropsData = [];
        foreach ($data['dynprops']['data'] as $v) {
            $catTypePrefix = ($this->item['cat_type'] == Listings::TYPE_OFFER ? ':offer' : ':seek');
            $v['value'] = (is_array($v['value']) ? join(', ', $v['value']) : $v['value']);
            if (!empty($v['child_to'])) {
                if (isset($dynprops['data'][$v['child_to']])) {
                    $vp = $dynprops['data'][$v['child_to']];
                    if (!empty($vp['cache_key'])) {
                        $dynpropsData[$vp['cache_key'] . '.sub'] = $v['value'];
                    }
                    $dynpropsData[$v['child_to'] . '.sub'] = $v['value'];
                }
            } else {
                if (!empty($v['cache_key'])) {
                    $dynpropsData[$v['cache_key']] = $v['value'];
                    $dynpropsData[$v['cache_key'] . $catTypePrefix] = $v['value'];
                }
                $dynpropsData[$v['id']] = $v['value'];
                $dynpropsData[$v['id'] . $catTypePrefix] = $v['value'];
            }
        }
        $this->seo->with($dynpropsData);

        # View template only (no category template)
        if (! $data['mcategorytemplate']) {
            $this->seo->fill($data);
        }

        # social images
        foreach ($data['images'] as $k => $v) {
            $data['images'][$k]['width'] = 0;
            $data['images'][$k]['height'] = 0;
            $data['images'][$k]['social_url'] = $v['url_zoom'];
        }

        # no index blocked items
        if ($this->item['status'] == Listings::STATUS_BLOCKED) {
            $this->seo->index(false);
            $this->seo->follow(false);
        }

        $this->seo->fieldPlaceholders(
            'breadcrumb',
            ['category'],
            ['region' => 'city','region.in' => 'city.in']
        );
        $this->seoApply($data, ['divider' => '|']);

        $this->breadcrumb = ''; # prevent autoreplace last breadcrumb
        $this->breadcrumbs->activateLast = false;
        $this->breadcrumbs->fill($this->item['categories'], function ($crumb) {
            return [
                'title' => $crumb['breadcrumb'],
                'link' => $crumb['link'],
            ];
        });
    }

    public function seoSettings()
    {
        $this->seo
            ->placeholders([
                'id'                 => _t('listings', 'Listing ID'),
                'name'               => _t('listings', 'User Name'),
                'title'              => _t('', 'Title'),
                'description'        => _t('listings', 'Description (Up to [size] characters)'),
                'price'              => _t('listings', 'Cost'),
                'address'            => _t('geo', 'Address'),
                'district'           => _t('geo', 'City District'),
                'category'           => _t('listings', 'Current listing category'),
                'category+parent'    => _t('listings', 'Current category + category above'),
                'categories'         => _t('listings', 'Title of all categories'),
                'categories.reverse' => _t('listings', 'Title of all categories<br />(reverse order)'),
            ])
            ->social()
            ->inheritance();
        $this->seoMacrosRegions();
    }

    public function settingsForm($form)
    {
        $form->checkbox('comments', _t('@listings', 'Listings Commenting'), $this->comments)
             ->sysAdmin('listings.comments');

        $form->select('mediaGalleryImagesWidth', _t('@listings', 'Gallery Images Width'))
            ->option('auto', _t('@listings', 'Auto'))
            ->option('default', _t('@listings', 'Default'))
        ;

        $form->select('sharecode', _t('@', 'Share Block'), $this->sharecode, function () {
            return [
                ['id' => 1, 'title' => _t('@', 'Enabled'), 'help' => (
                    '<a ' . HTML::attributes(['href' => Site::settingsSystemLink('main', ['sett' => 'sharecode']), 'target' => '_blank']) . '>' . _t('@site', 'block settings') . '</a>'
                )],
                ['id' => 0, 'title' => _t('@', 'Disabled')],
            ];
        }, false, ['showHelp' => true]);
    }
}