<?php

namespace App\Presenters;

use Laracasts\Presenter\Presenter;

class MessagePresenter extends Presenter
{
    private function normalizeLegacyEncodedAnchors(string $text): string
    {
        return (string) preg_replace_callback('/&#60;a\b(.*?)&#62;(.*?)&#60;\/a&#62;/is', function ($m) {
            $attrs = (string) ($m[1] ?? '');
            $inner = (string) ($m[2] ?? '');

            $href = '';
            if (preg_match('/href=(?:&#34;|&quot;|&#39;)(.*?)(?:&#34;|&quot;|&#39;)/i', $attrs, $hm)) {
                $href = (string) ($hm[1] ?? '');
            }

            // Only decode harmless entities for URL/text; never introduce real tags.
            $decodeSafe = function (string $value): string {
                $value = str_replace(['&amp;', '&quot;', '&#34;', '&#39;'], ['&', '"', '"', "'"], $value);
                return $value;
            };

            $innerText = trim($decodeSafe($inner));
            $hrefText = trim($decodeSafe($href));

            $candidate = $innerText;
            if ($candidate === '' || ! preg_match('~\b(https?://|www\.)~i', $candidate)) {
                $candidate = $hrefText !== '' ? $hrefText : $candidate;
            }

            // If it's not a URL-ish thing, just return the original inner text.
            if ($candidate === '' || ! preg_match('~\b(https?://|www\.)~i', $candidate)) {
                $candidate = $innerText;
            }

            // Ensure we never output raw angle brackets here.
            $candidate = str_replace(['<', '>'], ['&lt;', '&gt;'], $candidate);

            return $candidate;
        }, $text);
    }

    public function canView()
    {

        $userid = \Auth::user()->id;

        if ($userid == $this->entity->receiver and $this->entity->seen == 0) {
            $this->entity->seen = 1;
            $this->entity->save();
        }

        // if ($this->entity->sender_status == 1 and $this->entity->receiver_status == 1) {
        if ($this->entity->sender_status == 1) {
            $this->entity->delete();

            return false;
        }

        /* if ($userid == $this->entity->sender) {

             if ($this->entity->sender_status == 0) return true;
         } else {
             if ($this->entity->receiver_status == 0) return true;
         }*/

        if ($this->entity->sender_status == 0) {
            return true;
        }

        return false;
    }

    public function time()
    {
        if (date('I', time())) {
            return str_replace(' ', 'T', $this->entity->created_at).'-04:00';
        } else {
            return str_replace(' ', 'T', $this->entity->created_at).'-05:00';
        }

        /*$timeSet="+05:30";
        if(\Session::has('user_client_timezone')){
            $user_client_timezone=\Session::get('user_client_timezone');

            $timeSet=getTimeAgo($user_client_timezone);
        }
        return str_replace(' ', 'T', $this->entity->created_at).$timeSet;*/
    }

    public function text()
    {
        $text = (string) $this->entity->text;

        // Allow a sender-specific version of meeting push text.
        if (isset($this->entity->message_type) && $this->entity->message_type === 'meeting_push') {
            try {
                $authId = (int) \Auth::user()->id;
                $senderId = (int) ($this->entity->sender ?? 0);
                if ($authId > 0 && $senderId > 0 && $authId === $senderId) {
                    $senderText = (string) ($this->entity->text_sender ?? '');
                    if (trim($senderText) !== '') {
                        $text = $senderText;
                    }
                }
            } catch (\Exception $e) {
                // ignore
            }
        }

        // Some older messages stored link tags as literal HTML entities (e.g. "&#60;a ...&#62;"),
        // which shows up as mangled text like "...'>...'>" and isn't clickable.
        // Normalize those back to plain URLs before linkifying.
        $text = $this->normalizeLegacyEncodedAnchors($text);

        // Turn plain URLs into clickable links (open in new tab).
        // We can't store HTML in DB (sanitizeText escapes it), so we linkify at render time.
        $text = preg_replace_callback('~(?<!["\'>])\b(https?://[^\s<]+)~i', function ($m) {
            $url = (string) $m[1];
            $trail = '';
            while ($url !== '' && preg_match('~[\)\]\}\.,!?;:]$~', $url)) {
                $trail = substr($url, -1) . $trail;
                $url = substr($url, 0, -1);
            }
            if ($url === '') {
                return $m[1];
            }

            $href = htmlspecialchars($url, ENT_QUOTES, 'UTF-8');
            $label = htmlspecialchars($url, ENT_QUOTES, 'UTF-8');
            return "<a target='_blank' rel='noopener noreferrer' href='{$href}'>{$label}</a>{$trail}";
        }, $text);

        $text = preg_replace_callback('~(?<!["\'>])\b(www\.[^\s<]+)~i', function ($m) {
            $display = (string) $m[1];
            $url = $display;
            $trail = '';
            while ($url !== '' && preg_match('~[\)\]\}\.,!?;:]$~', $url)) {
                $trail = substr($url, -1) . $trail;
                $url = substr($url, 0, -1);
            }
            if ($url === '') {
                return $display;
            }
            $href = 'http://' . $url;
            $hrefEsc = htmlspecialchars($href, ENT_QUOTES, 'UTF-8');
            $labelEsc = htmlspecialchars($url, ENT_QUOTES, 'UTF-8');
            return "<a target='_blank' rel='noopener noreferrer' href='{$hrefEsc}'>{$labelEsc}</a>{$trail}";
        }, $text);

        $text = nl2br($text);

        /*$regexB = '(?:[^-\\/"\':!=a-z0-9_@＠]|^|\\:)';
        $regexUrl = '(?:[^\\p{P}\\p{Lo}\\s][\\.-](?=[^\\p{P}\\p{Lo}\\s])|[^\\p{P}\\p{Lo}\\s])+\\.[a-z]{2,}(?::[0-9]+)?';
        $regexUrlChars = '(?:(?:\\([a-z0-9!\\*\';:=\\+\\$\\/%#\\[\\]\\-_,~]+\\))|@[a-z0-9!\\*\';:=\\+\\$\\/%#\\[\\]\\-_,~]+\\/|[\\.\\,]?(?:[a-z0-9!\\*\';:=\\+\\$\\/%#\\[\\]\\-_~]|,(?!\s)))';
        $regexURLPath = '[a-z0-9=#\\/]';
        $regexQuery = '[a-z0-9!\\*\'\\(\\);:&=\\+\\$\\/%#\\[\\]\\-_\\.,~]';
        $regexQueryEnd = '[a-z0-9_&=#\\/]';

        $regex = '/(?:'             # $1 Complete match (preg_match already matches everything.)
            . '('.$regexB.')'    # $2 Preceding character
            . '('                                     # $3 Complete URL
            . '((?:https?:\\/\\/|www\\.)?)'           # $4 Protocol (or www)
            . '('.$regexUrl.')'          # $5 Domain(s) (and port)
            . '(\\/'.$regexUrlChars.'*'   # $6 URL Path
            . $regexURLPath.'?)?'
            . '(\\?'.$regexQuery.'*'  # $7 Query String
            . $regexQueryEnd.')?'
            . ')'
            . ')/iux';

        return preg_replace_callback($regex, function($matches) {

            list($all, $before, $url, $protocol, $domain, $path, $query) = array_pad($matches, 7, '');
            $href = ((!$protocol || strtolower($protocol) === 'www.') ? 'https://'.$url : $url);

                $href=getShortUrl($href);
            if (!$protocol && !preg_match('/\\.(?:com|net|org|gov|edu)$/iu' , $domain)) return $all;

            $newUrl=$url;

            $newUrl=((!$protocol || strtolower($protocol) === 'www.') ? 'https://'.$newUrl : $newUrl);
           if(strlen($href) >30){
                 $hrefShort=\Str::limit($href, 30);
           }else{
                $hrefShort=$href;
           }
           return $before."<a nofollow='nofollow' href='".$newUrl."' target='_blank'>".$hrefShort."</a>";
        } , $text);*/

        // turn links to clickable
        // $text = app('App\\Repositories\\PostRepository')->turnLinks($text);

        return \Hook::fire('post-text', $text);
    }

    public function hasLink()
    {
        return $this->entity->link;

        $link = (empty($this->entity->link)) ? [] : perfectUnserialize($this->entity->link);

        // if (empty($link) or empty($link['title'])) return false;

        if (empty($link)) {
            return false;
        }

        return true;
    }

    public function getLinkDetail()
    {
        $link = (empty($this->entity->link)) ? [] : perfectUnserialize($this->entity->link);

        return $link;
    }

    public function messageReadStatus()
    {
        /*if($this->entity->group_id==0){
            if($this->entity->seen==1){
                return 1;
            }
            return 0;
        }else{
            $hasFound = app('App\\Repositories\\PostSeenRepository')->findByType('chat_message',$this->entity->group_id,$this->entity->id);
            if($hasFound>0){
                return 0;
            }
            return 1;
        }	*/

        if ($this->entity->group_id != 0) {
            $hasFound = app('App\\Repositories\\PostSeenRepository')->findByType('chat_message', $this->entity->group_id, $this->entity->id);
            if ($hasFound > 0) {
                return 0;
            }

            return 1;
        } elseif ($this->entity->communityGroupId != 0) {
            $hasFound = app('App\\Repositories\\PostSeenRepository')->findByType('group_message', $this->entity->communityGroupId, $this->entity->id);
            if ($hasFound > 0) {
                return 0;
            }

            return 1;
        } else {
            if ($this->entity->seen == 1) {
                return 1;
            }

            return 0;
        }
    }

    public function getMessageTime()
    {
        $messageDate = $this->entity->created_at;

        if ($messageDate != '') {
            if ($this->isMessageDateSame($messageDate)) {
                // return $this->isMessageDateSame($messageDate);
                return $this->convertTimeToLocal($messageDate);
            } else {
                $days = $this->getDays($messageDate);
                if ($days < 7) {
                    return date('l', strtotime($messageDate));
                } else {
                    return date('j M Y', strtotime($messageDate));
                }
            }
        }
    }

    public function getMessageFullTime()
    {
        $datetime = $this->entity->created_at;
        $timezone = \Session::get('user_client_timezone');
        if ($timezone != 'America/New_York' and $timezone != '') {
            date_default_timezone_set('America/New_York');
            $datetime = new \DateTime($datetime);
            $datetime->format('g:i A');
            $la_time = new \DateTimeZone($timezone);
            $datetime->setTimezone($la_time);

            return $datetime->format('Y-m-d H:i:s');
        } else {
            date_default_timezone_set('America/New_York');

            return date('Y-m-d H:i:s', strtotime($datetime));
        }
    }

    public function isMessageDateSame($messageDate)
    {
        if ($this->getOnlyDay($messageDate) === $this->getOnlyDay(date('Ymd'))) {
            return true;
        } else {
            return false;
        }
    }

    public function convertTimeToLocal($datetime)
    {
        $timezone = \Session::get('user_client_timezone');
        if ($timezone != 'America/New_York' and $timezone != '') {
            // return $datetime;
            // return $datetime;
            date_default_timezone_set('America/New_York');
            // return $datetime;
            $datetime = new \DateTime($datetime);
            $datetime->format('g:i A');
            $la_time = new \DateTimeZone($timezone);
            $datetime->setTimezone($la_time);

            return $datetime->format('g:i A');
        } else {
            date_default_timezone_set('America/New_York');

            return date('g:i A', strtotime($datetime));
        }
    }

    public function getOnlyDay($datetime)
    {
        $timezone = \Session::get('user_client_timezone');
        if ($timezone != 'America/New_York' and $timezone != '') {
            date_default_timezone_set('America/New_York');
            $datetime = new \DateTime($datetime);
            $datetime->format('Ymd');
            $la_time = new \DateTimeZone($timezone);
            $datetime->setTimezone($la_time);

            return $datetime->format('Ymd');

        } else {
            date_default_timezone_set('America/New_York');

            return date('Ymd', strtotime($datetime));
        }
    }

    public function getDays($messageDate)
    {
        $date1 = date('Y-m-d', strtotime($messageDate));
        $date2 = date('Y-m-d');

        $diff = strtotime($date2) - strtotime($date1);

        // 1 day = 24 hours
        // 24 * 60 * 60 = 86400 seconds
        return abs(round($diff / 86400));
    }
}
