<?php

namespace auctionforge\inc\import;

use auctionforge\inc\abs\Importer;
use auctionforge\inc\BidSpiritRequest;
use auctionforge\inc\controllers\MultiLanguageSupport;
use auctionforge\inc\controllers\PolylangSupport;
use auctionforge\inc\Debug;
use auctionforge\inc\helpers\SettingsHelper;
use auctionforge\inc\model\Auction;
use WP_Error;

class AuctionList extends Importer
{
    /**
     * Initialize SessionId to Bidspirit API and run process import
     * @return void
     */
    public function init() {
        $offset = 0;
        if (defined('BIDSPIRIT_AUCTIONS_LIMIT')) {
            $limit = BIDSPIRIT_AUCTIONS_LIMIT;
        } else {
            $limit = 50;
        }
        do {
            $result = $this->getAllAuctionsFromAPI($offset);
            $this->setAuctions();
            $this->run();
            $offset = $limit + $offset;
        } while($result);
    }

    /**
     * Get and update data for auctions
     * @param  int  $offset
     * @return bool
     */
    private function getAllAuctionsFromAPI($offset = 0)
    {
        if (defined('BIDSPIRIT_AUCTIONS_LIMIT')) {
            $limit = BIDSPIRIT_AUCTIONS_LIMIT;
        } else {
            $limit = 50;
        }

        $mlSupport = new MultiLanguageSupport();
        $action = "auctions/getAllAuctions.api";
        //$actionTest = "auctions/getAllAuctionsUpdatedSince.api";
        //$oldestDays = SettingsHelper::getOption(Settings::OLDEST_DAYS_NAME, 30);

        $data = array(
            self::FIELD_SESSION_ID => $this->getSessionId(),
            self::FIELD_LANGUAGE => MultiLanguageSupport::getDefaultLangCode(),
            'limit' => $limit,
            'offset' => $offset,
        );

        /*$nowTime = new DateTime();
        $nowTime->modify('-' . $oldestDays . ' days');*/
        //$since = $nowTime->getTimestamp();
        /*$dataTest = array(
            self::FIELD_SESSION_ID => $this->getSessionId(),
            self::FIELD_LANGUAGE => MultiLanguageSupport::getDefaultLangCode(),
            'limit' => 50,
            'offset' => 50,
            'since' => $since
        );*/

        $responseSecond = array();
        if ($mlSupport->isAuctionSupport()) {
            $dataSecond = array(
                self::FIELD_SESSION_ID => $this->getSessionId(),
                self::FIELD_LANGUAGE => MultiLanguageSupport::getSecondLangCode(),
                'limit' => $limit,
                'offset' => $offset,
            );

            $responseSecond = BidSpiritRequest::send($action, $dataSecond);
        }

        $response = BidSpiritRequest::send($action, $data);

//        $responseTest = BidSpiritRequest::send($actionTest, $dataTest);

        if (!$response["response"]) {
            $this->setLoggedInfo(array(
                "auctions/getAllAuctions" => $response
            ));
        }

        if (defined("AUCTIONFORGE_RESPONSE_LOG")) {
            Debug::logData($response["response"], "{$action}: response");
        }

        $this->setErrors($response["response"]);

        if (empty($this->getErrors())) {
            $this->setResponseData($response, $responseSecond);
        }

        if ($response['response']) {
            $responseData = json_decode($response['response']);
            // Capture the auction-house region for the "Auto" spelling dialect
            // (no page-load API calls — resolved here during the sync).
            if (!empty($responseData->response) && class_exists('\auctionforge\inc\helpers\Dialect')) {
                \auctionforge\inc\helpers\Dialect::captureRegionFromAuctions($responseData->response);
            }
            return !empty($responseData->response);
        } else {
            return false;
        }
    }

    /**
     * Processing data and insert/update categories/auctions in site
     * @return void
     */
    private function run()
    {
        $defaultLanguage = MultiLanguageSupport::getDefaultLangCode();
        $mlSupport = new MultiLanguageSupport();
        $mlSupport->init();
        $content = $this->getResponseData();
        $terms = array();
        $secondLanguage = false;

        if ($mlSupport->isAuctionSupport()) {
            $secondLanguage = MultiLanguageSupport::getSecondLangCode();
        }

        $auctionIds = Auction::getAllAuctionsIds();
        Auction::checkTrashTerms();

        $excludeAuction = SettingsHelper::getAuctionExclude();
        $auctionsTouch = array();
        if (!empty($content[$defaultLanguage]) && is_array($content)) {
            foreach ($content[$defaultLanguage] as $key => $category) {
                if  (!empty($category->id)) {
                    $terms[$defaultLanguage] = $this->saveAuction($category, $excludeAuction, $defaultLanguage);

                    if ($terms[$defaultLanguage] > 0) {
                        $auctionsTouch[$terms[$defaultLanguage]] = $category->id;
                    }

                    if ($mlSupport->isAuctionSupport() && $terms[$defaultLanguage] && $secondLanguage) {
                        $secondCategory = $content[$secondLanguage][$key];


                        if ($category->id == $secondCategory->id) {
                            $terms[$secondLanguage] = $this->saveAuction($secondCategory, $excludeAuction, $secondLanguage);

                            if ($terms[$secondLanguage] > 0) {
                                $auctionsTouch[$terms[$secondLanguage]] = $category->id;
                            }
                        }

                        $otherLanguages = PolylangSupport::getSupportedLanguages();
                        if (!empty($otherLanguages['other'])) {
                            foreach ($otherLanguages['other'] as $otherLanguage) {
                                $terms[$otherLanguage] = $this->saveAuction($category, $excludeAuction, $otherLanguage);
                            }
                        }
                        do_action('auctionforge_second_auction_links', $terms, $defaultLanguage, $otherLanguages);
                    }

                    if (isset($auctionIds[$category->id])) {
                        unset($auctionIds[$category->id]);
                    }
                }
            }
        }
        if (!empty($auctionsTouch)) {
            $this->setLoggedInfo(array(
                "auctions created|updated" => $auctionsTouch
            ));
        }

        // Transition orphaned auctions to ENDED.
        // Any IDs remaining in $auctionIds are active in WP but no longer
        // returned by the Bidspirit API — they should be marked as ended.
        // We update BOTH auction_state AND each auctionDay->ended flag,
        // because the query_auction_params filter strips meta_query on
        // sites without a theme template, so shortcodes rely on the
        // day-level ended flag to exclude past auctions.
        // Safety 1: skip entirely if the API returned no data (error/empty response)
        //           — we can't distinguish orphans from a broken API.
        // Safety 2: only auto-end if the latest auction day has fully passed
        //           (end-of-day 23:59:59), not just the auction start time.
        if (!empty($auctionIds) && !empty($content[$defaultLanguage])) {
            $endedTouch = array();
            $now = current_time('timestamp');
            foreach ($auctionIds as $auctionId => $item) {
                $termId = $item->term_id;
                $currentState = SettingsHelper::getTermOption($termId, 'auction_state');

                if ($currentState === Auction::STATE_ARCHIVED || $currentState === 'ENDED') {
                    continue;
                }

                // Date guard: only auto-end if the latest auction day is in the past
                $days = SettingsHelper::getTermOption($termId, 'auction_days');
                if (is_array($days) && !empty($days)) {
                    $latestDate = 0;
                    foreach ($days as $day) {
                        $dayTs = 0;
                        if (!empty($day->date)) {
                            // Use end-of-day (23:59:59) so auctions aren't
                            // auto-ended while still running on auction day
                            $dayTs = strtotime($day->date . 'T23:59:59+00:00');
                        }
                        if ($dayTs > $latestDate) {
                            $latestDate = $dayTs;
                        }
                    }
                    // Skip if the latest auction day hasn't passed yet
                    if ($latestDate > $now) {
                        continue;
                    }
                } else {
                    // No auction_days data — check auction_date meta as fallback
                    // Use end-of-day so the auction isn't ended on its own date
                    $auctionDate = SettingsHelper::getTermOption($termId, 'auction_date');
                    if (!empty($auctionDate)) {
                        $dateOnly = substr($auctionDate, 0, 10);
                        if (strtotime($dateOnly . 'T23:59:59+00:00') > $now) {
                            continue;
                        }
                    }
                }

                // 1. Update auction_state meta
                update_term_meta($termId, 'auction_state', 'ENDED');

                // 2. Mark each auction day as ended
                if (is_array($days)) {
                    foreach ($days as $day) {
                        $day->ended = true;
                    }
                    update_term_meta($termId, 'auction_days', $days);
                }

                $endedTouch[$termId] = $auctionId . ' (auto-ended)';
            }

            if (!empty($endedTouch)) {
                Auction::doClearCacheForAuctionPages();
                $this->setLoggedInfo(array(
                    "orphaned auctions auto-ended" => $endedTouch
                ));
            }
        }
    }

    /**
     * @param $category
     * @param $excludeAuction
     * @param  bool $mlPrefix
     * @return int|object|WP_Error
     */
    private function saveAuction($category, $excludeAuction, $mlPrefix = false)
    {
        if (isset($category->hidden) && $category->hidden == true) {
            Debug::logData(
                $category->id . ":" . $category->name,
                "hidden"
            );
            return 0;
        }

        $model = new Auction();
        $model->loadAttributes($category);
        $model->setDate($model->getDays());

        if (in_array($model->getId(), $excludeAuction)) {
            return 0;
        }

        if (!PolylangSupport::isPolylangActive()) {
            $mlPrefix = false;
        }

        $auction = Auction::findAuctionByIdWithLang($model->getId(), $mlPrefix);
        if ($auction instanceof \WP_Term) {
            $model->setTermId($auction->term_id);
        }

        return $model->save($auction, $mlPrefix);
    }

    /**
     * @param mixed $responseData
     */
    public function setResponseData($responseData, $secondResponse = array())
    {
        $this->responseData = array();
        $responseData = json_decode($responseData['response']);

        if (!empty($secondResponse) && !empty($responseData->response)) {
            $secondLanguage = MultiLanguageSupport::getSecondLangCode();
            $secondResponse = json_decode($secondResponse['response']);
            $this->responseData[$secondLanguage] = $secondResponse->response;
        }

        if (!empty($responseData->response)) {
            $defaultLanguage = MultiLanguageSupport::getDefaultLangCode();
            $this->responseData[$defaultLanguage] = $responseData->response;
        }
    }
}
