<?php

namespace auctionforge\inc\helpers;

use DateTime;
use Exception;
use auctionforge\inc\abs\ImageModel;
use auctionforge\inc\controllers\MultiLanguageSupport;
use auctionforge\inc\controllers\PolylangSupport;
use auctionforge\inc\controllers\Settings;
use auctionforge\inc\Debug;
use auctionforge\inc\InstanceDB;
use auctionforge\inc\model\Auction;
use auctionforge\inc\model\LotImage;
use auctionforge\inc\model\LotMetaData;
use WP_Post;

class LotHelper
{
    private $postId;
    /**
     * LotHelper constructor.
     * @param $postId
     */
    public function __construct($postId)
    {
        $this->setPostId($postId);
    }

    public function getFeatureImage()
    {
        $cdnUse = SettingsHelper::getOption('cdn_images', 'on');
        $cdnUseCondition = apply_filters('auctionforge_cdn_use_conditions', ($cdnUse == 'on'), $cdnUse, $this);
        if ($cdnUseCondition) {
            $lotImages = new LotImage($this->getPostId());
            $imageList = $lotImages->getImageList();
            if (!empty($imageList[0])) {
                $quality = apply_filters('bp_quality_feature_image', ImageModel::LABEL_MEDIUM);
                $featureImage = $imageList[0][$quality];
            } else {
                $featureImage = false;
            }
        } else {
            $featureImage = get_the_post_thumbnail_url($this->getPostId(), 'lot-thumbnail');
        }
        if (!$featureImage) {
            $featureImage = self::getPlaceholderImage();
        }

        return $featureImage;
    }

    public static function getFeatureImageByID($postId)
    {
        $lotImages = new LotImage($postId);
        $images = $lotImages->getImageList();
        if (!empty($images[0])) {
            $featureImage = $images[0][ImageModel::LABEL_MEDIUM];
        } else {
            $featureImage = null;
        }
        return $featureImage;
    }

    public function getActualPrice()
    {
        return [
            "startPrice" => $this->getOptionValue('lot_startPrice', 0),
            "leadingBid" => $this->getOptionValue('lot_leadingBid', 0),
            "soldBid" => $this->getOptionValue('lot_soldBid', 0)
        ];
    }

    public static function getPlaceholderImage()
    {
        return apply_filters("auctionforge_placeholder_image", plugins_url('auctionforge/img/not_found.jpg'));
    }

    public static function formattedPrice($price, $onlyPrice = false)
    {
        $lang = MultiLanguageSupport::getDefaultLangCode();
        $currency = SettingsHelper::getOption('currency', '$');

        $price = preg_replace("/\D/", "", $price);
        $price = floatval($price);

        $price = number_format($price);

        if ($onlyPrice) {
            $currency = '';
        }

        if ($lang == 'ru') {
            return preg_replace('/\,/', ' ', $price) . $currency;
        } else if (apply_filters('bp_currency_position', false, "")) {
            return $price . $currency;
        } else {
            return $currency . $price;
        }
    }

    public static function getPolyLangPermalink($pageIdOrUrl)
    {
        // Allow override through filter first
        $filteredUrl = apply_filters('auctionforge_form_action_url_override', null, $pageIdOrUrl);
        if ($filteredUrl !== null) {
            return self::addPolylangSupportToUrl($filteredUrl);
        }

        // Check if it's a URL or page ID
        if (is_string($pageIdOrUrl) && (strpos($pageIdOrUrl, 'http') === 0 || strpos($pageIdOrUrl, '/') === 0)) {
            // It's already a URL - add Polylang support
            return self::addPolylangSupportToUrl($pageIdOrUrl);
        }

        // It's a page ID - use existing logic
        $pageId = intval($pageIdOrUrl);
        $polylangPageId = 0;

        if (is_plugin_active('polylang/polylang.php') &&
            (function_exists('pll_get_post') && function_exists('pll_current_language'))
        ) {
            $lang = MultiLanguageSupport::getDefaultLangCode();
            $polylangPageId = pll_get_post($pageId, $lang);
        }

        $finalUrl = '';
        if ($polylangPageId != 0) {
            $finalUrl = get_permalink($polylangPageId);
        } else {
            $finalUrl = get_permalink($pageId);
        }

        // Apply final filter for additional customization
        return apply_filters('auctionforge_form_action_url_final', $finalUrl, $pageIdOrUrl);
    }

    /**
     * Add Polylang language support to any URL
     * 
     * @param string $url The URL to add language support to
     * @return string URL with language support
     */
    public static function addPolylangSupportToUrl($url)
    {
        if (!PolylangSupport::isPolylangActive()) {
            return $url;
        }

        $currentLang = pll_current_language();
        $defaultLang = pll_default_language();

        // Only add language parameter if current language is different from default
        if ($currentLang && $currentLang !== $defaultLang) {
            $separator = (strpos($url, '?') !== false) ? '&' : '?';
            $url .= $separator . 'lang=' . $currentLang;
        }

        return $url;
    }

    /**
     * @param string $option
     * @param $default
     * @return string
     */
    public function getOptionValue($option, $default)
    {
        return $this->getOptionValueBS($option, $default);
    }

    private function getOptionValueBS($option, $default)
    {
        $option = preg_replace("/lot_/", "", $option);
        $option = preg_replace_callback('/\_\w/', function ($matches) {
            $matches = preg_replace("/\_/", "", $matches);
            return strtoupper($matches[0]);
        }, $option);

        return LotMetaData::getMetaField($option, $this->getPostId());
    }

    private function getOptionValueWP($option, $default)
    {
        $optionData = get_post_custom_values($option, $this->getPostId());
        if (!empty($optionData)) {
            return $optionData[0];
        } else {
            return $default;
        }
    }

    public static function getOptionPageLink($pageId)
    {
        if (!PolylangSupport::isPolylangActive()) {
            return get_permalink($pageId);
        }

        $currentLang = pll_current_language();
        $defaultLang = pll_default_language();
        if ($currentLang != $defaultLang) {
            if($pllPageId = pll_get_post($pageId)) {
                $pageId = $pllPageId;
            }
        }
        return get_permalink($pageId);
    }

    public static function getLotTitle($title, $content)
    {
        if ($title == '') {
            $contentLines = explode(PHP_EOL, strip_tags($content));
            $contentLines = array_map(function ($i) {
                return trim($i);
            }, $contentLines);
            $contentLines = array_values(array_diff($contentLines, array('')));

            $limitWords = apply_filters('auctionforge_lot_title_words', 8);
            if (!empty($contentLines[0])) {
                $title = wp_trim_words($contentLines[0], $limitWords, '...');
            } else {
                $title = wp_trim_words(strip_tags($content), $limitWords, '');
            }
        }
        return $title;
    }

    public static function getLotLink($post_link, $force = false)
    {
        if (PolylangSupport::isFullSupport()) {
            return $post_link;
        }

        $uri = parse_url($_SERVER['REQUEST_URI']);
        (strpos($post_link, '?') !== false) ? $delimiter = '&' : $delimiter = '?';
        if (!empty($uri['query'])) {
            parse_str($uri['query'], $params);
        }
        if (isset($params[PolylangSupport::LANG_SWITCH_PARAM])) {
            unset($params['part']);
            $post_link .= $delimiter . http_build_query($params);
        } elseif ($force) {
            $params[PolylangSupport::LANG_SWITCH_PARAM] = $force;
            $post_link .= $delimiter . http_build_query($params);
        }

        return $post_link;
    }

    public static function getAuctionLink($termId, $part = false)
    {
        if (empty($termId)) {
            return "#";
        }

        $auctionLink = get_term_link($termId);
        if ($part !== false) {
            $auctionLink .= "part/" . $part . "/";
        }
        return $auctionLink;
    }

    /**
     * @param $auctionDay
     * @return int
     */
    public static function isHiddenLots($auctionDay)
    {
        $hidePricesHours = SettingsHelper::getOption('hide_prices', 0);
        if (isset($auctionDay->auctionEnded)) {
            $currentTime = time();
            $auctionEnded = intval($auctionDay->auctionEnded / 1000) + (intval($hidePricesHours) * 3600);
            return ($auctionEnded <= $currentTime) ? 0 : 1;
        } else {
            return 0;
        }
    }

    public static function chunkSlug($sanitizeTitle)
    {
        $delimiter = '-';
        $lengthSlug = apply_filters('auctionforge_length_slug', 4);
        $offsetSlug = apply_filters('auctionforge_offset_slug', 0);
        $chunks = array_slice(explode($delimiter, $sanitizeTitle), $offsetSlug, $lengthSlug);
        return implode($delimiter, $chunks);
    }

    /**
     * @param $lotIndex
     * @param $termId
     * @param string $adjacent
     * @param string $post_type
     * @return object|\WP_Error
     */
    public function da_the_adjacent_lot($lotIndex, $termId, $adjacent = '', $post_type = 'lot')
    {
        $adjacent = ($adjacent == 'prev');
        $db = InstanceDB::getInstanceDB();
        $cond = ">";
        $order = "ASC";

        if ($adjacent) {
            $cond = "<";
            $order = "DESC";
        }

        $sql = $this->getAdjacentLotLinkBS($db, $cond, $order);
        $sql2 = $db->prepare($sql, $post_type, $termId, self::formatPaddedIndex($lotIndex));

        return $db->get_row($sql2);
    }

    /**
     * @param $lotIndex
     * @param $termId
     * @param string $adjacent
     * @param string $post_type
     * @return bool|false|string|\WP_Error
     * Deprecated: use da_the_adjacent_lot
     */
    public function da_the_adjacent_lot_link($lotIndex, $termId, $adjacent = '', $post_type = 'lot' )
    {
        global $post;
        $adjacent = $adjacent == 'prev';
        $db = InstanceDB::getInstanceDB();
        $cond = ">";
        $order = "ASC";
        $currentLink = get_post_permalink($post->ID);
        $adjacentLink = "";

        if ($adjacent) {
            $cond = "<";
            $order = "DESC";
        }

        $sql = $this->getAdjacentLotLinkBS($db, $cond, $order);
        $sql = $db->prepare($sql, $post_type, $termId, $lotIndex);
        $need_post = self::da_the_adjacent_lot($lotIndex, $termId, $adjacent, $post_type);

        if (empty($need_post) || $currentLink == $adjacentLink) {
            $adjacentLink = "#";
        } else {
            $adjacentLink = get_post_permalink($need_post->ID);
        }

        return $adjacentLink;
    }

    private function getAdjacentLotLinkBS($db, $cond, $order)
    {
        return "SELECT * FROM " . $db->posts . " AS p 
            INNER JOIN " . $db->term_relationships . " AS r ON r.object_id = p.ID
            INNER JOIN " . $db->prefix . LotMetaData::TABLE_LOT_META . " AS m ON m.postId = p.ID
            WHERE p.post_type = '%s' AND p.post_status = 'publish' AND r.term_taxonomy_id = %d
            AND (m.paddedIndex " . $cond . " %s)
            ORDER BY m.paddedIndex " . $order . "
            LIMIT 0, 1";
    }

    /**
     * Depricated.
     * @param $db
     * @param $cond
     * @param $order
     * @return string
     */
    private function getAdjacentLotLinkWP($db, $cond, $order)
    {
        return "SELECT * FROM " . $db->posts . " AS p
            INNER JOIN " . $db->term_relationships . " AS r ON r.object_id = p.ID
            INNER JOIN " . $db->postmeta . " AS m ON m.post_id = p.ID
            WHERE p.post_type = '%s' AND p.post_status = 'publish' AND r.term_taxonomy_id = %d
            AND (m.meta_key = 'lot_itemIndex' AND m.meta_value " . $cond . " %d)
            ORDER BY m.meta_value+0 " . $order . "
            LIMIT 0, 1";
    }

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

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

    public static function printTranslateLot($title)
    {
        return apply_filters('auctionforge_print_translate_lot', __('Lot', 'auctionforge') . " " . preg_replace('/^(.*?)\s/', '', $title));
    }

    public function getImagesListStr()
    {
        return $this->getOptionValue('lot_imagesListStr', '');
    }

    public function getImagesBase()
    {
        return $this->getOptionValue('lot_imagesBase', '');
    }

    public function isCloned()
    {
        return $this->getOptionValue('lot_imagesCloned', 'false');
    }

    public static function auctionIsActive($termId)
    {
        $allowStatus = array('ARCHIVED', 'ENDED');
        $state = get_term_meta($termId, 'auction_state');
        if (!empty($state) && in_array($state[0], $allowStatus)) {
            return true;
        }
        return false;
    }

    /**
     * @param $typeSync string option name AUCTIONFORGE_SYNC_ARCHIVE_START|AUCTIONFORGE_SYNC_START
     */
    public static function startSync($typeSync, $modify = 60) {
        $syncStart = get_option($typeSync);
        $trigger = false;
        if (intval($syncStart) == 0) {
            update_option($typeSync, date(Auction::DATE_FORMAT), 'no');
            $trigger = true;
        } elseif ($syncStart > 0) {
            $now = new DateTime();
            $now->modify("-{$modify} minutes");
            $now->modify("+1 minutes");

            $syncStartTime = strtotime($syncStart);

            if ($now->getTimestamp() > $syncStartTime) {
                $trigger = true;
            }
        }
        return $trigger;
    }

    /**
     * @param $posts WP_Post[]
     */
    public static function movedToDraftPosts($posts)
    {
        if (!empty($posts)) {
            foreach ($posts as $post) {
                $data = array(
                    'ID' => $post->ID,
                    'post_status' => 'draft'
                );
                wp_update_post($data);
            }
        }
    }

    public static function movedToTrashPosts($postIDs)
    {
        // https://wordpress.stackexchange.com/questions/208608/delete-all-posts-of-a-custom-post-type-efficiently
        $res = false;
        if (!empty($postIDs)) {
            $db = InstanceDB::getInstanceDB();
            $sql = "UPDATE `" . $db->posts. "` SET `post_status` = 'trash' WHERE `id` IN (" . implode(",", $postIDs) . ")";
            $res = $db->query($sql);
        }
        return $res;
    }

    public static function isOpenedUntil($timestamp)
    {
        return (!empty($timestamp) && $timestamp > (time() * 1000)) ?: 0;
    }

    /**
     * Formats the lot index by padding with zeros to 10 digits and handling letter suffix
     * @param string|int $index The lot index to format
     * @return string Formatted index with padding
     */
    public static function formatPaddedIndex($index) 
    {
        // Extract numeric and letter parts
        preg_match('/(\d+)([A-Za-z])?/', $index, $matches);
        
        if (empty($matches)) {
            return str_pad('0', 10, '0', STR_PAD_LEFT);
        }

        $numericPart = $matches[1];
        $letterPart = isset($matches[2]) ? $matches[2] : '';

        // Pad the numeric part to 10 digits
        $paddedNumber = str_pad($numericPart, 10, '0', STR_PAD_LEFT);

        // Append letter if exists
        return $paddedNumber . $letterPart;
    }

    public static function clearAdjacentLotCacheForPost($postId, $postType = 'lot')
    {
        $cacheKey = 'adjacent_lot_' . $postId . '_' . $postType;
        wp_cache_delete($cacheKey, 'auctionforge');
    }

    public static function singleLotId($lotIndex)
    {
//        $auctionId = SettingsHelper::getTermOption($auction->term_id, 'auction_id');
        return "#lot-" . $lotIndex;
    }
}
