<?php

namespace auctionforge\inc\controllers;

use auctionforge\inc\Debug;
use auctionforge\inc\InstanceDB;
use auctionforge\inc\model\LotMetaData;

class BidspiritQuery
{
    const BIDSPIRIT_QUERY = 'bp_query';
    const BIDSPIRIT_ID = 'bp_id';
    const BIDSPIRIT_INDEX = 'bp_index';
    const BIDSPIRIT_FIELD = 'bp_field';

    public function init()
    {
        add_filter('posts_join', array($this, 'bp_query_join'), 10, 2);
        add_filter('posts_where', array($this, 'bp_query_where'), 10, 2);
        add_filter('posts_orderby', array($this, 'bp_query_orderby'), 10, 2);
        add_filter('posts_groupby', array($this, 'bp_query_groupby'), 10, 2);
    }

    public function bp_query_join($join, $wpQuery)
    {
        /**
         * Check it in admin panel
         */
        $bpQuery = $wpQuery->get(self::BIDSPIRIT_QUERY, false);
        if (is_admin() && !wp_doing_ajax() && !isset($bpQuery)) {
            return $join;
        }

        if (!empty($bpQuery)) {
            $db = InstanceDB::getInstanceDB();
            $join .= " INNER JOIN " . $db->prefix . LotMetaData::TABLE_LOT_META . " AS bpMeta ON ( " . $db->posts . ".ID = bpMeta.postId ) ";
        }

        return $join;
    }

    /**
     * @param $where
     * @param $wpQuery
     * @return mixed|string
     * TODO: Add parameter "relations"
     */
    public function bp_query_where($where, $wpQuery)
    {
        $bpQuery = $wpQuery->get(self::BIDSPIRIT_QUERY, false);
        if (is_admin() && !wp_doing_ajax() && !isset($bpQuery)) {
            return $where;
        }

        if (is_array($bpQuery)) {
            $postIdsQuery = "";
            $postFieldQuery = "";
            if (!empty($bpQuery[self::BIDSPIRIT_ID]) &&
                isset($bpQuery[self::BIDSPIRIT_ID]["compare"]) &&
                isset($bpQuery[self::BIDSPIRIT_ID]["value"])
            ) {
                $value = intval($bpQuery[self::BIDSPIRIT_ID]["value"]);
                $compare = $bpQuery[self::BIDSPIRIT_ID]["compare"];

                $postIdsQuery = " bpMeta.`id` {$compare} {$value} ";

            } elseif (!empty($bpQuery[self::BIDSPIRIT_INDEX])) {
                if (!empty($bpQuery[self::BIDSPIRIT_INDEX]["between"]) && !empty($bpQuery[self::BIDSPIRIT_INDEX]["between"][0])) {
                    $compare = $bpQuery[self::BIDSPIRIT_INDEX]["between"][0]["compare"];
                    $value = intval($bpQuery[self::BIDSPIRIT_INDEX]["between"][0]["value"]);
                    $postIdsQuery = " (CAST(bpMeta.`itemIndex` AS UNSIGNED) {$compare} " . $value;

                    if (!empty($bpQuery[self::BIDSPIRIT_INDEX]["between"][1])) {
                        $compare = $bpQuery[self::BIDSPIRIT_INDEX]["between"][1]["compare"];
                        $value = intval($bpQuery[self::BIDSPIRIT_INDEX]["between"][1]["value"]);
                        $postIdsQuery .= " AND CAST(bpMeta.`itemIndex` AS UNSIGNED) {$compare} " . $value . ") ";
                    } else {
                        $postIdsQuery .= " ) ";
                    }
                } else {
                    $value = (!empty($bpQuery[self::BIDSPIRIT_INDEX]["value"])) ? intval($bpQuery[self::BIDSPIRIT_INDEX]["value"]) : 0;
                    $compare = (!empty($bpQuery[self::BIDSPIRIT_INDEX]["compare"])) ? $bpQuery[self::BIDSPIRIT_INDEX]["compare"] : "";
                    $postIdsQuery .= " CAST(bpMeta.`itemIndex` AS UNSIGNED) {$compare} " . $value . " ";
                }
            }

            if (!empty($bpQuery[self::BIDSPIRIT_FIELD])) {
                if (!empty($bpQuery[self::BIDSPIRIT_FIELD])) {
                    foreach ($bpQuery[self::BIDSPIRIT_FIELD] as $key => $item) {
                        $lastIndex = false;
                        if ((count($bpQuery[self::BIDSPIRIT_FIELD]) - 1) == $key) {
                            $lastIndex = true;
                        }

                        if (!empty($item["between"]) && !empty($item["between"][0])) {
                            $compare = $item["between"][0]["compare"];
                            $value = $item["between"][0]["value"];
                            $field = $item["field"];

                            $postFieldQuery = " (bpMeta.`{$field}` {$compare} {$value}";

                            if (!empty($item["between"][1])) {
                                $compare = $item["between"][1]["compare"];
                                $value = $item["between"][1]["value"];
                                $postFieldQuery .= " AND bpMeta.`{$field}` {$compare} {$value}) ";

                                if (!$lastIndex) {
                                    $postFieldQuery .= " AND ";
                                }
                            } else {
                                $postFieldQuery .= " ) AND ";
                            }
                        } else {
                            $field = $item["field"];
                            $value = $item["value"];
                            $compare = $item["compare"];
                            $postFieldQuery .= " bpMeta.`{$field}` {$compare} {$value} ";
                            if (!$lastIndex) {
                                $postFieldQuery .= " AND ";
                            }
                        }
                    }
                }
            }

            if (!empty($bpQuery["term_id"])) {
                if ($postIdsQuery == "") {
                    $postIdsQuery = " bpMeta.`termId` = '" . intval($bpQuery["term_id"]) . "' ";
                } else {
                    $postIdsQuery .= " AND bpMeta.`termId` = '" . intval($bpQuery["term_id"]) . "' ";
                }
            }

            if (!empty($bpQuery["lang"]) && PolylangSupport::isPolylangActive()) {
                $postIdsQuery .= " AND bpMeta.`lang` = '" . sanitize_title($bpQuery["lang"]) . "' ";
            }

            if (!empty($bpQuery[self::BIDSPIRIT_INDEX]) || !empty($bpQuery[self::BIDSPIRIT_ID])) {
                $where .= " AND ( $postIdsQuery ) ";
            }

            if (!empty($bpQuery[self::BIDSPIRIT_FIELD])) {
                $where .= " AND ( $postFieldQuery ) ";
            }
        }
        return $where;
    }

    public function bp_query_orderby($orderby, $wpQuery)
    {
        $bpQuery = $wpQuery->get(self::BIDSPIRIT_QUERY, false);
        if (is_admin() && !wp_doing_ajax() && !isset($bpQuery)) {
            return $orderby;
        }

        if (!empty($wpQuery->get('bp_orderby', false))) {
            $orderField = $wpQuery->get('bp_orderby', false);

            if ($orderField === 'effectivePrice') {
                $order = $wpQuery->get('order', 'DESC');
                $orderby = "GREATEST(bpMeta.soldBid+0, bpMeta.leadingBid+0, bpMeta.startPrice+0) {$order}, (CASE WHEN bpMeta.soldBid+0 > 0 OR bpMeta.leadingBid+0 > 0 THEN 1 ELSE 0 END) DESC";
            } else if ($orderField === 'mostActive') {
                $order = $wpQuery->get('order', 'DESC');
                $orderby = "(CASE WHEN bpMeta.soldBid+0 > 0 OR bpMeta.leadingBid+0 > 0 THEN 1 ELSE 0 END) DESC, (GREATEST(bpMeta.soldBid+0, bpMeta.leadingBid+0) / NULLIF(bpMeta.startPrice+0, 0)) {$order}";
            } else if ($orderField === 'leadingBid') {
                $order = $wpQuery->get('order', 'DESC');
                // Items with bids first (sorted by leadingBid), then items without bids sorted by startPrice
                $orderby = "(CASE WHEN bpMeta.leadingBid+0 > 0 THEN 0 ELSE 1 END) ASC, bpMeta.leadingBid+0 {$order}, bpMeta.startPrice+0 {$order}";
            } else {
                $orderby = "bpMeta." . $orderField;
                if ($orderField != "paddedIndex") {
                    $orderby .= "+0";
                }
                $order = $wpQuery->get('order', false);
                if (!empty($order)) {
                    $orderby .= " " . $order;
                }
            }
        }

        return $orderby;
    }

    public function bp_query_groupby($groupby, $wpQuery)
    {
        $bpQuery = $wpQuery->get(self::BIDSPIRIT_QUERY, false);
        if (is_admin() && !wp_doing_ajax() && !isset($bpQuery)) {
            return $groupby;
        }
        $db = InstanceDB::getInstanceDB();

        if (!empty($bpQuery)) {
            //$groupby = "bpMeta.id";
            $groupby = $db->prefix . "posts.ID";
        }

        return $groupby;
    }
}

$bidspiritQuery = new BidspiritQuery();
$bidspiritQuery->init();