<?php

namespace LoftyIDX\includes\common;

use LoftyIDX\includes\common\LoftyIDXListingHelper;
use LoftyIDX\includes\LoftyIDXHelpers;
use LoftyIDX\includes\common\LoftyIDXNumberFormatter;

defined('ABSPATH') || exit;

class LoftyIDXHouseHelper
{
    public static $vowStatus = null;

    public static function getLng($key, $options = [])
    {
        $k = str_replace('common:house.', '', $key);
        $str = '';
        $house_lng = [
            "sqft" => "SqFt",
            "acres" => "Acres",
            "acresLot" => "Acres Lot",
            "sqftLot" => "Sqft Lot",
            "bed_one" => "Bed",
            "bed_other" => "Beds",
            "bath_one" => "Bath",
            "bath_other" => "Baths",
            "priceDroppedBy" => "Price Dropped by {{price}}K",
            "priceDroppedByM" => "Price Dropped by {{price}}M",
            "newToSite" => "New To Site"
        ];

        if (isset($house_lng[$k])) {
            $str = $house_lng[$k];
        }

        if (isset($options['count'])) {
            if ($options['count'] > 1) {
                $k = $k . '_other';
            } else {
                $k = $k . '_one';
            }
        }

        if (isset($house_lng[$k])) {
            $str = $house_lng[$k];
        }

        //  Replace a variable in a string with a property in an object
        $str = preg_replace_callback('/{{(.*?)}}/', function ($matches) use ($options) {
            //  Here we use the property name to get the corresponding value from the replacement object
            return isset($options[$matches[1]]) ? $options[$matches[1]] : $matches[0];
        }, $str);

        return $str;
    }


    public static function numberGFormat($count, $globalizationKey, $options = [])
    {
        $isNeedUnit = $options['isNeedUnit'] ?? false;
        $Fixed = $options['Fixed'] ?? 2;
        $split = $options['split'] ?? " ";
        $unit = self::getLng($globalizationKey, ['count' => $count]);
        if (!$unit) {
            return "";
        }
        $text =  LoftyIDXNumberFormatter::numberFormat($count, $isNeedUnit, $Fixed);
        if (!$text) {
            return '';
        }
        return $text  . $split . $unit;
    }


    public static function get_sqft_text($info, $isNeedUnit = false, $Fixed = 2, $split = " ")
    {
        $text = "";

        $format = function ($count, $key) use ($isNeedUnit, $Fixed, $split) {
            return self::numberGFormat($count, $key, ['isNeedUnit' => $isNeedUnit, 'Fixed' => $Fixed, 'split' => $split]);
        };
        if (isset($info['propertyType']) && $info['propertyType'] == "Vacant Land") {
            if (isset($info['totalAvailableAcres']) && $info['totalAvailableAcres'] > 0) {
                $text = $format(
                    $info['totalAvailableAcres'] / (10890 * 4),
                    "common:house.acres"
                );
            }
        } else {
            if (isset($info['sqft']) && $info['sqft'] > 0) {
                $text = $format($info['sqft'], "common:house.sqft");
            } elseif (isset($info['totalAvailableAcres']) && $info['totalAvailableAcres'] >= 10890) {
                $text = $format(
                    $info['totalAvailableAcres'] / (10890 * 4),
                    "common:house.acresLot"
                );
            } elseif (isset($info['totalAvailableAcres']) && $info['totalAvailableAcres'] > 0 && $info['totalAvailableAcres'] < 10890) {
                $text = $format($info['totalAvailableAcres'], "common:house.sqftLot");
            }
        }

        if (strlen($text) > 0) {
            $text =  '<span>' . $text . '</span>';
        }
        return $text;
    }
    
    public static function get_bed_text($bedrooms)
    {
        $bedroomsText = '';
        if (isset($bedrooms) && $bedrooms > 0) {
            $bedroomsText = '<span>' . $bedrooms . " " .  (self::getLng("bed", ["count" => $bedrooms])) . '</span>';
        }
        return $bedroomsText;
    }

    public static function get_bath_text($bathrooms)
    {
        $bathroomsText = '';
        if (isset($bathrooms) && $bathrooms > 0) {
            $bathroomsText = '<span>' . $bathrooms . " " .  (self::getLng("bath", ["count" => $bathrooms])) . '</span>';
        }
        return $bathroomsText;
    }

    public static function get_bed_bath_sqft_text($info)
    {
        //  $bedroomsText . $bathroomsText . $sqftText
        return self::get_bed_text(isset($info["bedrooms"]) ? $info["bedrooms"] : null) . self::get_bath_text(isset($info["bathrooms"]) ? $info["bathrooms"] : null) . self::get_sqft_text($info);
    }

    public static function get_trend($soldPrice, $price)
    {
        $trendUp = true;
        $trend = (100 * ($soldPrice - $price)) / $price;

        if ($trend < 0) {
            $trend = abs($trend);
            $trendUp = false;
        }

        if (!is_numeric($trend) || !is_finite($trend)) {
            $trend = "";
        }

        if ($trend === "" || floatval($trend) === 0) {
            $trend = "";
        } else {
            $trend = number_format($trend, 1) . '%';
        }

        return [
            'trend' => $trend,
            'trendUp' => $trendUp,
        ];
    }

    public static function get_provider_text($template, $info)
    {
        $escapeMap =  array(
            '&nbsp;' => ' ',
            '&lt;' => '<',
            '&gt;' => '>',
            '&quot;' => '"',
            '&amp;' => '&',
            '&#10;' => '\n',
            '&#9;' => '\t',
            '&#39;' => "'"
        );

        $escapeReg = implode('|', array_map('preg_quote', array_keys($escapeMap)));

        $templateStr = preg_replace_callback('/' . $escapeReg . '/', function ($matcher) use ($escapeMap) {
            if ($matcher[0]) {
                return $escapeMap[$matcher[0]];
            }
            return $escapeMap[$matcher[0]];
        }, $template ?? "");
        return self::handle_template_str($templateStr, $info, "\n");
    }

    public static function format_phone_num($value)
    {
        $value = (string)$value;
        $value = preg_replace('/^ +| +$/', '', $value);
        $value = preg_replace('/^(\d{3})(\d{3})/', '$1-$2-', $value);
        return $value;
    }

    public static function get_provider_html($template, $info)
    {
        $agentCellPhone = self::format_phone_num(
            isset($info["agentCellPhone"]) ? $info["agentCellPhone"] : ''
        );
        $agentOfficePhone = self::format_phone_num(
            isset($info["agentOfficePhone"]) ? $info["agentOfficePhone"] : ''
        );
        $info["agentCellPhone"] = $agentCellPhone;
        $info["agentOfficePhone"] = $agentOfficePhone;
        return self::handle_template_str($template, $info, '<br>');
    }

    public static function calc_string_from_template($templateSentence, $info)
    {
        if (!$templateSentence || !preg_match('/#([^{}]*){(.*?)}([^#]*)#/', $templateSentence)) {
            return $templateSentence;
        }

        $hasInfoValue = false;
        $preHasValue = true;
        $ret = preg_replace_callback(
            '/([^#]*)#([^{}]*){(.*?)}([^#]*)#/',
            function ($matches) use ($info, &$hasInfoValue, &$preHasValue) {
                $preDelimiter = $matches[1];
                $leftStr = $matches[2];
                $variableName = $matches[3];
                $rightStr = $matches[4];
                $startIdx = $matches[5] ?? '';

                $infoText = $info[$variableName] ?? null;
                $curHasValue = !!$infoText;
                $fullText = $curHasValue ? $leftStr . $infoText . $rightStr : "";
                try {
                    if ($startIdx === 0) {
                        return $preDelimiter . $fullText;
                    }
                    if (!$curHasValue) {
                        return $preDelimiter;
                    }
                    if (!$preHasValue) {
                        $preDelimiter = "";
                    }
                    if (!$preDelimiter && !$leftStr) {
                        return ($hasInfoValue ? " • " : "") . $fullText;
                    }
                    return $preDelimiter . $fullText;
                } finally {
                    $preHasValue = $curHasValue;
                    $hasInfoValue = $hasInfoValue || $curHasValue;
                }
            },
            $templateSentence
        );

        return $hasInfoValue ? $ret : "";
    }


    public static function handle_template_str($template, $info, $delimiter)
    {
        if (!$template) {
            return "";
        }

        $templateSentences = explode("<br>", $template);
        $result = array_map(function ($templateSentence) use ($info) {
            return self::calc_string_from_template($templateSentence, $info);
        }, $templateSentences);

        $filteredResult = array_filter($result, function ($v) {
            return $v;
        });

        return implode($delimiter, $filteredResult);
    }


    public static function is_active_mls($data, $mls_list = [])
    {
        if (empty($mls_list)) {
            $mls_list = [];
        }
        $mlsOrgId = isset($data['mlsOrgId']) ? $data['mlsOrgId'] : null;

        $ids = array_map(function ($o) {
            if (is_array($o)) {
                return $o['id'] ?? null;
            }
            return $o;
        }, $mls_list);

        $mlsIsActive = array_filter($ids, function ($id) use ($mlsOrgId) {
            return $id == $mlsOrgId;
        });
        return !empty($mlsIsActive);
    }

    public static function format_mls_info($data, $mls_list = null)
    {
        if (self::is_active_mls($data, $mls_list)) {
            $isMobile = LoftyIDXHelpers::is_mobile();
            return [
                'provided' => self::get_provider_text($data['mlsOrg']['cardTemplate'] ?? null, $data),
                'mlsLogo' => ($isMobile ? ($data['mlsOrg']['smallLogo'] ?? $data['mlsOrg']['logo']) : ($data['mlsOrg']['logo'] ?? $data['mlsOrg']['smallLogo'])),
            ];
        }
        return [
             'provided' => '',
             'mlsLogo' => ''
        ];
    }

    /**
     * listing detail page data format
     */
    public static function format_house($data, $mls_list = null)
    {
        $mlsOrgHas74 = isset($data['mlsOrg']['mlsOrgHas74']) ? $data['mlsOrg']['mlsOrgHas74'] : false;
        $soldProtected = isset($data['mlsOrg']['soldProtected']) ? $data['mlsOrg']['soldProtected'] : '';
        $listingPictures = isset($data['listingPictures']) ? explode('|', $data['listingPictures']) : [];
        $isMobile = LoftyIDXHelpers::is_mobile();

        $mlsInfo = self::format_mls_info($data, $mls_list);
        $targetMls = array_filter($mls_list, function($item) use($data) {
            return isset($data['mlsOrg']['id']) && $item['id'] === $data['mlsOrg']['id'];
        });
        $targetMls = reset($targetMls);
        $formatted = [
            'id' => isset($data['id']) ? $data['id'] : null,
            'detailUrlTarget' => $isMobile ? '_self' : '_blank',
            'link' => isset($data['detailLink']) ? $data['detailLink'] : null,
            'detailUrl' => isset($data['detailUrl']) ? $data['detailUrl'] : null,
            'preview' => $listingPictures[0] ?? '',
            'status' => isset($data['listingStatus']) ? $data['listingStatus'] : null,
            'tour3D' => preg_match('/matterport\.(com|cn)\/show/', sprintf('%s %s', $data['link'] ?? '', $data['chimeVideoLink'] ?? '')),
            'picturesNum' => $data['picturesNum'] ?? 0,
            'collected' => $data['collectStatus'] ?? '',
            'price' => '$' . number_format(isset($data['price']) ? $data['price'] : 0, 0),
            'address' =>  preg_replace('/, */', ', ', $data['address'] ?? ''),
            'streetAddress' => isset($data['streetAddress']) ? $data['streetAddress'] : null,
            'cityAddress' => isset($data['cityAddress']) ? $data['cityAddress'] : null,
            'propertyType' => $data['propertyTypeText'] ?? (isset($data['propertyType']) ? $data['propertyType'] : null),
            'statusOrigin' => strtolower($data['statusOrigin'] ?? ''), //leased
            'desc' => $data['detailsDescribe'] ?? '',
            'listingPictures' => $data['listingPictures'] ?? '',
            'previewPictures' => $listingPictures,
            'latitude' => isset($data['latitude']) ? $data['latitude'] : null,
            'longitude' => isset($data['longitude']) ? $data['longitude'] : null,
            'showMls' => $mlsOrgHas74 && (isset($data['mlsListingId']) ? $data['mlsListingId'] : null),
            'showSoldPrice' => $targetMls ? $targetMls['showSoldPrice'] : false,
            'mlsid' => isset($data['mlsListingId']) ? $data['mlsListingId'] : null,
            'mlsLogo' => $mlsInfo['mlsLogo'],
            'soldDate' => $data['soldDate'] ?? null,
            'mlsOrgHas74' => $mlsOrgHas74,
            'listingTags' => $data['listingTags'] ?? array(),
            'exclusive' => $data['exclusiveListingTag'] ?? null,
            'listingSource' => $data['listingSource'] ?? '',
            'nodisclosureDes' => $data['nodisclosureDes'] ?? '',
            'vow' => $soldProtected,
            'isProtected' => strpos($soldProtected, isset($data['listingStatus']) ? $data['listingStatus'] : '') !== false,
            'flagText' => $data['flagText'] ?? '',
            'statusText' => $data['listingStatusText'] ?? '',
            'bedrooms' => isset($data['bedrooms']) ? $data['bedrooms'] : null,
            'bathrooms' => isset($data['bathrooms']) ? $data['bathrooms'] : null,
            'sqft' => $data['sqft'] ?? 0,
            'provided' => $mlsInfo['provided'],
        ];
        if (isset($data['soldDate']) && $data['soldDate']) {
            $trend_info = self::get_trend($data['soldPrice'], $data['price']);
            $trend = $trend_info['trend'];
            $trendUp = $trend_info['trendUp'];
            $soldPrice = $data['soldPrice'];
            $markPrice =  $soldPrice;
            $initialPrice = $data['price'];
            $formatted = array_merge($formatted, [
                'soldPrice' =>  '$' . number_format($soldPrice, 0),
                'markPrice' => '$' . number_format($markPrice, 0),
                'initialPrice' =>  '$' . number_format($initialPrice, 0),
                'trendUp' => $trendUp,
                'trend' => $trend,
            ]);
            if (!floatval(str_replace('%', '', $trend))) {
                $formatted['trend'] = '';
            }
        }
        return $formatted;
    }

    /**
     * listing card data format
     */
    public static function format_house_card(&$data, $mlsList) {
        $targetMls = array_filter($mlsList, function($item) use($data) {
            return $item['id'] === $data['mlsOrg']['id'];
        });
        $targetMls = reset($targetMls);
        $data['showSoldPrice'] = $targetMls ? $targetMls['showSoldPrice'] : false;
        $data['isProtected'] = self::get_house_protected($data);
        $data['loginStatus'] = isset($_COOKIE['lofty_idx_lead_id']);
        $data['vowStatus'] = self::$vowStatus;
        $data['mlsOrg']['cardTemplate'] = preg_replace_callback('/#\{(.*?)}#/', function ($matches) use ($data) {
            $key = $matches[1];
            return $data[$key] ?? $matches[0];
        }, $data['mlsOrg']['cardTemplate']);

        $data['priceChange'] = $data['soldPrice'] !== $data['price'];
        $data['priceTrend'] = (($data['soldPrice'] ?? 0) - ($data['price'] ?? 0)) > 0 ? 'up' : 'down';
        $price = $data['price'] ?? 0;
        $data['priceChangePercent'] = $price > 0 ? (($data['soldPrice'] ?? 0) - $price) / $price : 0;
        // Calculate the house area and unit
        $area = $data['sqft'] ?? 0;
        $unit = 'SqFt';
        $decimal = 0;
        if($data['propertyType'] === 'Vacant Land') {
            $area = $data['totalAvailableAcres'] / (10890 * 4);
            $unit = 'Acres';
            $decimal = 2;
        } elseif ($area === 0) {
            if($data['totalAvailableAcres'] >= 10890) {
                $area = $data['totalAvailableAcres'] / (10890 * 4);
                $unit = 'Acres Lot';
                $decimal = 2;
            } else {
                $area = $data['totalAvailableAcres'];
                $unit = 'Sqft Lot';
            }
        }
        $data['area'] = $area;
        $data['unit'] = $unit;
        $data['decimal'] = $decimal;
        $data['showMls'] =  $data['mlsOrg']['mlsOrgHas74'] && $data['mlsListingId'];
    }

    public static function get_house_protected($house)
    {
        $soldProtected = $house['mlsOrg']['soldProtected'] ?? "";
        $isLogin = isset($_COOKIE['lofty_idx_lead_id']);
        if (is_null(self::$vowStatus) && $isLogin) {
            self::$vowStatus = LoftyIDXListingHelper::getUserVowStatus();
        }
        if (!$isLogin || !self::$vowStatus) {
            return strpos($soldProtected, $house['listingStatus']) !== false;
        }
        return false;
    }
}
