<?php

namespace auctionforge\inc\import;

use auctionforge\inc\abs\Importer;
use auctionforge\inc\abs\InsertLotsAbstract;
use auctionforge\inc\abs\Model;
use auctionforge\inc\controllers\BidspiritLots;
use auctionforge\inc\controllers\HummingbirdSupport;
use auctionforge\inc\controllers\MultiLanguageSupport;
use auctionforge\inc\controllers\PolylangSupport;
use auctionforge\inc\controllers\Settings;
use auctionforge\inc\Debug;
use auctionforge\inc\helpers\Conditions;
use auctionforge\inc\helpers\LotHelper;
use auctionforge\inc\helpers\LotLogging;
use auctionforge\inc\helpers\SettingsHelper;
use auctionforge\inc\ImageUploader;
use auctionforge\inc\InstanceDB;
use auctionforge\inc\model\Auction;
use auctionforge\inc\model\Lot;

class InsertLots extends InsertLotsAbstract
{
    /**
     * @var $logger LotLogging
     */
    private $logger;
    private $priority;
    private $forceSync;
    private $mlSupport;

    private $auctionIds;

    /**
     * InsertLots constructor.
     * @param int $priority
     */
    public function __construct($priority = 1)
    {
        $this->setPriority($priority);
        $mlSupport = new MultiLanguageSupport();
        $this->setMlSupport($mlSupport);
        if ($mlSupport->isLotSupport()) {
            $mlSupport->init();
        }
    }

    public function init($args = [])
    {
        $args = wp_parse_args($args, array(
            "limit" => RAW_LOT_LIMIT
        ));
        $limit = (int)$args["limit"];
        if ($limit == 0) {
            $limit = RAW_LOT_LIMIT;
        }

        $db = InstanceDB::getInstanceDB();
        $autoCommit = SettingsHelper::isChecked(Settings::AUTO_COMMIT_DISABLED, 'off');
        wp_defer_comment_counting(true);

        InstanceDB::unlockTable();

        $db->query('START TRANSACTION;');
        $rawLots = Lot::getRawLots($limit);
        $rawRecordId = wp_list_pluck($rawLots, 'id');
        $this->blockRawRecordsLots($rawRecordId);
        $db->query('COMMIT;');

        if (empty($rawLots)) {
            return;
        }

        $rawLotsId = wp_list_pluck($rawLots, 'lotId');

        $this->setForceSync(SettingsHelper::isChecked(Settings::SYNC_FORCE_NAME, "off"));

        if ($autoCommit) {
            $db->query('SET autocommit = 0;');
        }

        $postData = Lot::findDataLots($rawLotsId, $limit);
        if (!$this->isForceSync()) {
            $filteredData = $this->rawDataFilter($rawLots, $postData);
            $rawLots = $filteredData['new'];
            $oldLots = $filteredData['old'];
            $oldIds = wp_list_pluck($oldLots, 'id');
            $this->disableUnUpdatedLots($oldIds);

            $this->setLoggedInfo(array(
                "unupdated lots" => count($oldLots)
            ));
        }
        $rawLots = array_slice($rawLots, 0, $limit);
        $rawIds = wp_list_pluck($rawLots, 'id');

        if (!empty($rawLots) && $this->blockRawLots($rawIds)) {
            $waSuspended = wp_suspend_cache_addition();
            wp_suspend_cache_addition(true);

            $_SERVER['AUCTIONFORGE_IMPORT_LOT'] = true;
            $_SERVER['HTTP_HOST'] = preg_replace( '|(?:https?:\/\/)|', '', get_option('siteurl'));

            $hummingbird = HummingbirdSupport::getInstance();
            $hummingbird->run();

            $instancesLot = array();
            foreach ($rawLots as $rawLot) {
                /** @var Lot $lot */
                $lot = apply_filters('auctionforge_image_lot_initial', new Lot());
                $lot->loadAttributes($rawLot);

                $instancesLot[] = $lot;
            }

            $updatedLots = 0;
            foreach ($instancesLot as $lot) {
                $this->setLogger();
                $datum = array_filter($postData, function ($item) use ($lot) {
                    return ($item->lotId == $lot->getLotId());
                });
                $datum = array_values($datum);
                if (count($datum) <= 1) {
                    if (isset($datum[0])) {
                        $datum = $datum[0];
                    } else {
                        $datum = array();
                    }
                    $postId = $this->lotProcessing($lot, $datum);
                    if (!empty($postId)) {
                        do_action('auctionforge_before_fixed_result_lot_import', $lot, $postId);
                    }
                    $this->fixResult($lot, $postId);
                    $updatedLots++;
                } else {
                    Debug::logData($datum, "Double", [__FILE__, __LINE__]);
                }
            }

            $this->setLoggedInfo(array(
                "updated lots" => $updatedLots
            ));

            wp_suspend_cache_addition($waSuspended);
        }

        $this->unblockRawRecordsLots($rawRecordId);

        wp_defer_comment_counting(false);
        if ($autoCommit) {
            $db->query('COMMIT;');
        }
    }

    /**
     * Preparing data and inserting / updating post and related meta data
     * @param $lot Lot
     * @param $postMeta object
     * @return integer
     */
    private function lotProcessing($lot, $postMeta) {
        $auction = Auction::findAuctionById($lot->getAuctionId());

        if ($auction instanceof \WP_Term) {
            $auctionId = $auction->term_id;
        } else {
            return 0;
        }

        $this->setAuctionIds($auctionId);
        $post = null;
        if (!empty($postMeta)) {
            $post = get_post($postMeta->ID);
        }

        $lastUpdate = (int)$lot->getLastUpdate();

        $metaLoadImages = false;
        if (!empty($postMeta->ID)) {
            $metaLoadImages = get_post_meta($postMeta->ID, 'load_images', true);
        }

        $postData = $this->postDataBuild($post, $lot, $postMeta, $metaLoadImages);
        $postId = $this->lotInsertOrUpdate($postData, $auctionId);
        if (!empty($postId)) {
            wp_set_post_terms($postId, array((int)$auctionId), BidspiritLots::TAX_AUCTION_TYPE, false);

            if (Conditions::isSyncImages($lot, $metaLoadImages, $postId, $lastUpdate)) {
                $this->uploadImages($lot, $postId);
            }
        } else {
            $this->instanceLogger()->setErrors(["Lot saving error"]);
        }

        if ($this->getMlSupport()->isLotSupport()) {
            $secondPostData = apply_filters('auctionforge_multi_language_post_data', $postData, $postId, $lot);

            $secondAuctionId = pll_get_term($auctionId, MultiLanguageSupport::getSecondLangCode());
            $secondPostId = $this->lotInsertOrUpdate($secondPostData, $secondAuctionId);

            if (Conditions::isSyncImages($lot, $metaLoadImages, $secondPostId, $lastUpdate) && !PolylangSupport::isThumbnailSync()) {
                $this->uploadImages($lot, $secondPostId);
            }

            do_action('auctionforge_second_lot_links', $postId, $secondPostId);

            wp_set_post_terms($secondPostId, array((int)$secondAuctionId), BidspiritLots::TAX_AUCTION_TYPE, false);
            wp_set_post_terms($postId, array((int)$auctionId), BidspiritLots::TAX_AUCTION_TYPE, false);
        }

        return $postId;
    }

    /**
     * @param $post \WP_Post
     * @param $lot Lot
     * @param $postMeta object
     * @param $metaLoadImages string
     * @return array
     */
    private function postDataBuild($post, $lot, $postMeta, $metaLoadImages)
    {
        $postData = array();
        if (!empty($post->ID)) {
            $postData = array(
                'ID' => $post->ID
            );
        }

        $isSecondLang = false;
        $lotTitle = apply_filters('auctionforge_lot_title_field', $lot->getName(), $lot, $isSecondLang);

        if ($lotTitle != "") {
            $lotTitle = "Lot " . wp_strip_all_tags($lot->getItemIndex()) . " - " . wp_strip_all_tags($lotTitle);
        } else if ($lot->getAuthor() != "") {
            $lotTitle = "Lot " . wp_strip_all_tags($lot->getItemIndex()) . " - " . wp_strip_all_tags($lot->getAuthor());
        } else {
            $lotTitle = "Lot " . wp_strip_all_tags($lot->getItemIndex());
        }

        $lotSlug = LotHelper::chunkSlug(sanitize_title($lotTitle));
        $lotSlug = apply_filters('auctionforge_lot_name_field', $lotSlug);

        $postData = array_merge($postData, array(
            'post_title' => $lotTitle,
            'post_name' => $lotSlug
        ));
        if (Conditions::isNotSyncTitle($post)) {
            $postData = array_merge($postData, array(
                'post_title' => $post->post_title,
                'post_name' => $post->post_name
            ));
        }

        $postData = array_merge($postData, array(
            'post_content' => $lot->getDescription()
        ));
        if (Conditions::isNotSyncDesc($post)) {
            $postData = array_merge($postData, array(
                'post_content' => $post->post_content
            ));
        }

        if (SettingsHelper::isChecked('sync_fields')) {
            $postData = array_merge($postData, array(
                'meta_input' => $this->getMetaFields($lot)
            ));
        }

        if ($metaLoadImages === '') {
            $postData['meta_input'] = array_merge($postData['meta_input'], array('load_images' => '0'));
        }

        $dateTime = $this->getDatetimeValue(intval($lot->getLastUpdate()/1000), "+00:00");

        $postStatus = SettingsHelper::getPostStatus($lot->getRemovedFromAuction());

        return array_merge($postData, array(
            'post_type' => BidspiritLots::POST_TYPE,
            'post_status' => $postStatus,
            'post_author' => $this->getUserIdAdmin(),
            'post_parent' => $lot->getLotId(),
            'post_date' => $dateTime,
            'post_date_gmt' => $dateTime
        ));
    }

    /**
     * @param $postData array
     * @return int|\WP_Error
     */
    private function lotInsertOrUpdate($postData, $auctionId)
    {
        $clearCache = false;
        if (!isset($postData['ID'])) {
            $clearCache = true;
        }
        $postId = wp_insert_post($postData);
        if ($clearCache) {
            HummingbirdSupport::clearCacheByUrl(get_term_link($auctionId));
        }
        return $postId;
    }

    /**
     * Get meta fields for the lot
     * @param $lot Lot
     * @return array
     */
    private function getMetaFields($lot) {
        $metaFields = [
            'lot_name' => $lot->getName(),
            'lot_itemIndex' => $lot->getItemIndex(),
            'lot_paddedIndex' => $lot->getPaddedIndex(),
            'lot_author' => $lot->getAuthor(),
            'lot_categoryId' => $lot->getCategoryId(),
            'lot_details' => $lot->getDetails(),
            'lot_start_price' => $lot->getStartPrice(),
            'lot_leadingBid' => $lot->getLeadingBid(),
            'lot_soldBid' => $lot->getSoldBid(),
            'lot_auctionId' => $lot->getAuctionId(),
            'lot_estimated_price' => $lot->getEstimatedPrice(),
            'lot_estimated_price_int' => preg_replace("/^(\W)+|[\,\.]/", "", $lot->getEstimatedPrice()),
            'lot_tags' => $lot->getTags(),
            'lot_videoUrl' => $lot->getVideoUrl(),
            'lot_extraInfo' => $lot->getExtraInfo(),
            'lot_postSaleDisabled' => Model::toString($lot->getPostSaleDisabled()),
            'lot_imagesBase' => $lot->getImagesBase(),
            'lot_imagesCloned' => Model::toString($lot->getImagesCloned()),
            'lot_buyoutPrice' => $lot->getBuyoutPrice(),
            'lot_fullPriceVat' => $lot->getFullPriceVat(),
            'lot_largeDisplay' => Model::toString($lot->getLargeDisplay()),
            'lot_viewOnly' => Model::toString($lot->getViewOnly()),
            'lot_hidden' => Model::toString($lot->getHidden()),
            'lot_hiddenInPortal' => Model::toString($lot->getHiddenInPortal()),
            'lot_removedFromAuction' => Model::toString($lot->getRemovedFromAuction()),
            'lot_eroticContent' => Model::toString($lot->getEroticContent()),
            'lot_criminalContent' => Model::toString($lot->getCriminalContent()),
            'lot_isGem' => Model::toString($lot->getIsGem()),
            'lot_id' => $lot->getLotId(),
            'lot_imagesListStr' => $lot->getImagesListStr(),
            'lot_params' => $lot->getParams()
        ];

        $metaFields = apply_filters('auctionforge_build_meta_fields_2', $metaFields, $lot);
        return apply_filters('auctionforge_build_meta_fields', $metaFields, $lot);
    }

    /**
     * Get site admin id
     * @return int
     */
    protected function getUserIdAdmin()
    {
        $users = get_users([
            'role' => 'administrator',
        ]);
        if (!empty($users)) {
            $users = array_values(array_reverse($users));
            return $users[0]->ID;
        } else {
            return 0;
        }
    }

    /**
     * @return LotLogging
     */
    public function instanceLogger()
    {
        return $this->logger;
    }

    public function setLogger()
    {
        $this->logger = new LotLogging();
    }

    /**
     * @return mixed
     */
    public function getPriority()
    {
        return $this->priority;
    }

    /**
     * @param mixed $priority
     */
    public function setPriority($priority)
    {
        $this->priority = $priority;
    }

    /**
     * @return boolean
     */
    public function isForceSync()
    {
        return $this->forceSync;
    }

    /**
     * @param  boolean  $forceSync
     */
    public function setForceSync($forceSync)
    {
        $this->forceSync = $forceSync;
    }

    /**
     * @return mixed
     */
    public function getMlSupport()
    {
        return $this->mlSupport;
    }

    /**
     * @param  mixed  $mlSupport
     */
    public function setMlSupport($mlSupport)
    {
        $this->mlSupport = $mlSupport;
    }

    /**
     * @return mixed
     */
    public function getAuctionIds()
    {
        if (!empty($this->auctionIds)) {
            return array_keys($this->auctionIds);
        } else {
            return array();
        }
    }

    /**
     * @param mixed $auctionId
     */
    public function setAuctionIds($auctionId)
    {
        if (!empty($auctionId)) {
            $this->auctionIds[$auctionId] = 1;
        }
    }
}