<?php

use FluentCommunity\App\Models\Space;
use FluentCommunity\App\Models\User;
use FluentCommunity\App\Services\Helper;

defined( 'ABSPATH' ) || exit;

if ( ! class_exists( 'Better_Messages_Fluent_Community_Spaces' ) ) {

    class Better_Messages_Fluent_Community_Spaces
    {
        public static function instance()
        {

            static $instance = null;

            if (null === $instance) {
                $instance = new Better_Messages_Fluent_Community_Spaces();
            }

            return $instance;
        }

        public function __construct()
        {
            add_filter('better_messages_is_valid_group', array( $this, 'is_valid_group' ), 10, 2 );

            add_filter('fluent_community/space_header_links', array( $this, 'group_link_to_chat' ), 10, 2);
            add_filter('better_messages_has_access_to_group_chat', array( $this, 'has_access_to_group_chat'), 10, 3 );
            add_filter('better_messages_can_send_message', array( $this, 'can_reply_to_group_chat'), 10, 3 );

            add_filter('better_messages_groups_active', array($this, 'enabled') );
            add_filter('better_messages_get_groups', array($this, 'get_groups'), 10, 2 );

            add_filter('better_messages_thread_title', array( $this, 'group_thread_title' ), 10, 3 );
            add_filter('better_messages_thread_image', array( $this, 'group_thread_image' ), 10, 3 );
            add_filter('better_messages_thread_url',   array( $this, 'group_thread_url' ), 10, 3 );

            add_action('fluent_community/space/created', array( $this, 'on_something_changed' ), 10, 3 );
            add_action('fluent_community/space/updated', array( $this, 'on_something_changed' ), 10, 3 );

            add_action('fluent_community/space/join_requested', array( $this, 'on_something_changed' ), 10, 3 );
            add_action('fluent_community/space/joined', array( $this, 'on_something_changed' ), 10, 3 );
            add_action('fluent_community/space/user_left', array( $this, 'on_something_changed' ), 10, 3 );

            if (Better_Messages()->settings[ 'FCenableGroupsFiles' ] === '0') {
                add_action('bp_better_messages_user_can_upload_files', array($this, 'disable_upload_files'), 10, 3);
            }

            add_action('fluent_community/on_wp_init', array( $this, 'on_wp_init' ), 10, 1 );

            add_filter( 'better_messages_bulk_get_all_groups', array($this, 'bulk_get_all_groups') );
            add_filter( 'better_messages_bulk_get_group_members', array($this, 'bulk_get_group_members'), 10, 3 );
        }

        public function on_wp_init( $app ){
            $api = \FluentCommunity\App\Functions\Utility::extender();

            $api->addMetaBox('better_messages_space_settings', [
                'section_title'   => _x('Group Messages', 'FluentCommunity Integration (Spaces Settings)', 'bp-better-messages'),
                'fields_callback' => function ($space) {
                    return [
                        'enabled' => [
                            'true_value'     => 'yes',
                            'false_value'    => 'no',
                            'type'           => 'inline_checkbox',
                            'checkbox_label' => _x('Enable group messages for this space members', 'FluentCommunity Integration (Spaces Settings)', 'bp-better-messages'),
                        ]
                    ];
                },
                'data_callback'   => function ($space) {
                    $settings = $space->getCustomMeta('better_messages_space_settings', []);

                    $defaults = [
                        'enabled'      => apply_filters('better_messages_fluent_community_group_chat_enabled', 'yes', $space->id )
                    ];

                    $settings = wp_parse_args($settings, $defaults);

                    return $settings;
                },
                'save_callback'   => function ($settings, $space) {
                    if ( ! is_array($settings) ) {
                        return;
                    }

                    $space->updateCustomMeta('better_messages_space_settings', $settings);
                }
            ], ['space']);

        }

        public function is_valid_group( $is_valid_group, $thread_id )
        {
            $group_id = (int) Better_Messages()->functions->get_thread_meta($thread_id, 'fluentcommunity_group_id');

            if ( !! $group_id ) {
                $group = Space::find( $group_id );

                if( $group ) {
                    if ( $this->is_group_messages_enabled($group_id)) {
                        $is_valid_group = true;
                    }
                }
            }

            return $is_valid_group;
        }

        public function disable_upload_files( $can_upload, $user_id, $thread_id ){
            if( Better_Messages()->functions->get_thread_type( $thread_id ) === 'group' ) {
                return false;
            }

            return $can_upload;
        }

        public function on_something_changed( $space, $userId = null, $initiator = null ){
            if( ! $this->is_group_messages_enabled( $space->id ) ){
                return;
            }

            $thread_id = $this->get_group_thread_id( $space->id );
            $this->sync_thread_members( $thread_id );
        }

        /**
         * @param string $url
         * @param int $thread_id
         * @param BM_Thread $thread
         * @return string
         */
        public function group_thread_url(string $url, int $thread_id, $thread ){
            $thread_type = Better_Messages()->functions->get_thread_type( $thread_id );
            if( $thread_type !== 'group' ) return $url;

            $group_id = Better_Messages()->functions->get_thread_meta($thread_id, 'fluentcommunity_group_id');

            $space = Space::find( $group_id );

            if( $space ){
                $url = Helper::baseUrl('space/' . $space->slug . '/home');
            }

            return $url;
        }

        /**
         * @param string $title
         * @param int $thread_id
         * @param BM_Thread $thread
         * @return string
         */
        public function group_thread_title(string $title, int $thread_id, $thread ){
            $thread_type = Better_Messages()->functions->get_thread_type( $thread_id );
            if( $thread_type !== 'group' ) return $title;

            $group_id = Better_Messages()->functions->get_thread_meta($thread_id, 'fluentcommunity_group_id');

            $space = Space::find( $group_id );
            if( $space ){
                return $space->title;
            } else {
                return $title;
            }
        }

        /**
         * @param string $image
         * @param int $thread_id
         * @param BM_Thread $thread
         * @return string
         */
        public function group_thread_image(string $image, int $thread_id, $thread ){
            $thread_type = Better_Messages()->functions->get_thread_type( $thread_id );
            if( $thread_type !== 'group' ) return $image;

            $group_id = Better_Messages()->functions->get_thread_meta($thread_id, 'fluentcommunity_group_id');

            $space = Space::find( $group_id );

            if( $space ){
                $image = $this->get_space_image( $space->toArray() );
            }

            return $image;
        }

        private function get_space_image( array $space_arr ){
            if( ! empty( $space_arr['logo'] ) ){
                return $space_arr['logo'];
            } else if( ! empty( $space_arr['settings'] ) && isset( $space_arr['settings']['emoji'] ) && ! empty( trim($space_arr['settings']['emoji']) ) ){
                return 'html:<span class="bm-thread-emoji">' . trim($space_arr['settings']['emoji']) . '</span>';
            } else if( ! empty( $space_arr['settings'] ) && isset( $space_arr['settings']['shape_svg'] ) && ! empty( trim($space_arr['settings']['shape_svg']) ) ) {
                return 'html:<span class="bm-thread-svg">' . trim($space_arr['settings']['shape_svg']) . '</span>';
            } else {
                return 'html:<span style="margin:auto" class="fcom_no_avatar"></span>';
            }
        }


        public function group_link_to_chat( $links, $space ) {
            $space_id = $space->id;

            if( ! $this->is_group_messages_enabled( $space_id ) ){
                return $links;
            }

            if( ! $this->user_has_access( $space_id, get_current_user_id() ) ){
                return $links;
            }

            $thread_id = $this->get_group_thread_id( $space_id );

            $url = Better_Messages()->functions->get_user_messages_url( get_current_user_id(), $thread_id );

            $links[] = [
                'title' => _x('Messages', 'FluentCommunity Integration (Button in Spaces)', 'bp-better-messages'),
                'url'   => $url
            ];

            return $links;
        }

        public function is_group_messages_enabled( $group_id ){
            $group = Space::find($group_id);

            if( ! $group ){
                return false;
            }

            $defaults = [
                'enabled'      => apply_filters('better_messages_fluent_community_group_chat_enabled', 'yes', $group_id )
            ];

            $settings = $group->getCustomMeta('better_messages_space_settings', $defaults );

            return $settings['enabled'] === 'yes';
        }

        public function user_has_access( $group_id, $user_id ){
            $allowed = false;

            if( $user_id > 0 ) {
                $user = User::find($user_id);

                if( $user ) {
                    $group = Space::find($group_id);

                    if( $group ) {
                        $role = $user->getSpaceRole($group);

                        if (!empty($role)) {
                            $allowed = true;
                        }
                    }
                }
            }

            return apply_filters('better_messages_fluent_community_group_chat_user_has_access', $allowed, $group_id, $user_id );
        }

        public function user_can_moderate( $group_id, $user_id )
        {
            $allowed = false;

            if( $user_id > 0 ) {
                $user = User::find($user_id);

                if( $user ) {
                    $group = Space::find($group_id);

                    if( $group ) {
                        $role = $user->getSpaceRole($group);

                        if ( $role === 'moderator' || $role === 'admin' ) {
                            $allowed = true;
                        }
                    }
                }
            }

            return apply_filters('better_messages_fluent_community_group_chat_user_can_moderate', $allowed, $group_id, $user_id );
        }

        public function has_access_to_group_chat( $has_access, $thread_id, $user_id ){
            $group_id = Better_Messages()->functions->get_thread_meta($thread_id, 'fluentcommunity_group_id');

            if ( !! $group_id ) {
                if( $this->is_group_messages_enabled( $group_id ) && $this->user_has_access( $group_id, $user_id ) ){
                    return true;
                }
            }

            return $has_access;
        }

        public function can_reply_to_group_chat( $allowed, $user_id, $thread_id ){
            $type = Better_Messages()->functions->get_thread_type( $thread_id );

            if( $type === 'group' ){
                $group_id = Better_Messages()->functions->get_thread_meta($thread_id, 'fluentcommunity_group_id');
                if ( !! $group_id ) {
                    if( $this->is_group_messages_enabled( $group_id ) && $this->user_has_access( $group_id, $user_id ) ){
                        return true;
                    } else {
                        return false;
                    }
                }
            }

            return $allowed;
        }

        public function enabled( $var ){
            return true;
        }

        public function get_groups( $groups, $user_id ){
            $user = User::find( $user_id );

            if( ! $user ) return $groups;

            $spaces = $user->spaces;

            $return = [];

            if( $spaces && count( $spaces ) > 0 ) {
                foreach ( $spaces as $space ) {
                    if( ! $this->is_group_messages_enabled( $space->id ) ){
                        continue;
                    }

                    $thread_id = $this->get_group_thread_id( $space->id );
                    $image = $this->get_space_image( $space->toArray() );

                    $return[] = [
                        'group_id'  => (int) $space->id,
                        'name'      => html_entity_decode( esc_attr( $space->title ) ),
                        'messages'  => 1,
                        'thread_id' => (int) $thread_id,
                        'image'     => $image,
                        'url'       => Helper::baseUrl('space/' . $space->slug . '/home')
                    ];
                }
            }

            return $return;
        }

        public function get_group_thread_id( $group_id ){
            global $wpdb;

            $thread_id = (int) $wpdb->get_var( $wpdb->prepare( "
            SELECT bm_thread_id 
            FROM `" . bm_get_table('threadsmeta') . "` 
            WHERE `meta_key` = 'fluentcommunity_group_id' 
            AND   `meta_value` = %s
            ", $group_id ) );

            $thread_exist = (int) $wpdb->get_var($wpdb->prepare("SELECT COUNT(*)  FROM `" . bm_get_table('threads') . "` WHERE `id` = %d", $thread_id));

            if( $thread_exist === 0 ){
                $thread_id = false;
            }

            if( ! $thread_id ) {
                $wpdb->query( $wpdb->prepare( "
                DELETE  
                FROM `" . bm_get_table('threadsmeta') . "` 
                WHERE `meta_key` = 'fluentcommunity_group_id' 
                AND   `meta_value` = %s
                ", $group_id ) );

                $space = Space::find( $group_id );

                if( $space ){
                    $title = $space->title;

                    $wpdb->insert(
                        bm_get_table('threads'),
                        array(
                            'subject' => $title,
                            'type'    => 'group'
                        )
                    );

                    $thread_id = $wpdb->insert_id;

                    Better_Messages()->functions->update_thread_meta( $thread_id, 'fluentcommunity_group_thread', true );
                    Better_Messages()->functions->update_thread_meta( $thread_id, 'fluentcommunity_group_id', $group_id );

                    $this->sync_thread_members( $thread_id );
                }
            }

            return $thread_id;
        }

        public function get_group_members( $group_id ){
            $result = [];

            $space = Space::find( $group_id );

            if( $space ){
                $members = $space->members->toArray();

                foreach ( $members as $member ){
                    if( $member['pivot']['status'] === 'active' ){
                        $result[] = $member['ID'];
                    }
                }
            }

            return $result;
        }


        public function sync_thread_members( $thread_id ){
            wp_cache_delete( 'thread_recipients_' . $thread_id, 'bm_messages' );
            wp_cache_delete( 'bm_thread_recipients_' . $thread_id, 'bm_messages' );

            $group_id = Better_Messages()->functions->get_thread_meta( $thread_id, 'fluentcommunity_group_id' );

            $members = $this->get_group_members( $group_id );

            if( count($members) === 0 ) {
                return false;
            }

            global $wpdb;
            $array     = [];
            $user_ids  = [];
            $removed_ids  = [];

            /**
             * All users ids in thread
             */
            $recipients = Better_Messages()->functions->get_recipients( $thread_id );

            foreach( $members as $user_id ){
                if( isset( $recipients[$user_id] ) ){
                    unset( $recipients[$user_id] );
                    continue;
                }

                if( in_array( $user_id, $user_ids ) ) continue;

                $user_ids[] = $user_id;

                $array[] = [
                    $user_id,
                    $thread_id,
                    0,
                    0,
                ];
            }

            $changes = false;

            if( count($array) > 0 ) {
                $sql = "INSERT INTO " . bm_get_table('recipients') . "
                (user_id, thread_id, unread_count, is_deleted)
                VALUES ";

                $values = [];

                foreach ($array as $item) {
                    $values[] = $wpdb->prepare( "(%d, %d, %d, %d)", $item );
                }

                $sql .= implode( ',', $values );

                $wpdb->query( $sql );

                $changes = true;
            }

            if( count($recipients) > 0 ) {
                foreach ($recipients as $user_id => $recipient) {
                    if( $user_id < 0 ){
                        continue;
                    }

                    global $wpdb;

                    $wpdb->delete( bm_get_table('recipients'), [
                        'thread_id' => $thread_id,
                        'user_id'   => $user_id
                    ], ['%d','%d'] );

                    $removed_ids[] = $user_id;
                }

                $changes = true;
            }

            Better_Messages()->hooks->clean_thread_cache( $thread_id );

            if( $changes ){
                do_action( 'better_messages_thread_updated', $thread_id );
                do_action( 'better_messages_info_changed', $thread_id );
                do_action( 'better_messages_participants_added', $thread_id, $user_ids );
                do_action( 'better_messages_participants_removed', $thread_id, $removed_ids );
            }

            return true;
        }

        public function bulk_get_all_groups( $groups ){
            if( ! class_exists('FluentCommunity\App\Models\Space') ) return $groups;

            $spaces = Space::get();

            if( $spaces ){
                foreach( $spaces as $space ){
                    $groups[] = [
                        'id'         => (int) $space->id,
                        'name'       => esc_attr( $space->title ),
                        'type'       => 'fc',
                        'type_label' => 'FluentCommunity',
                    ];
                }
            }

            return $groups;
        }

        public function bulk_get_group_members( $user_ids, $group_type, $group_id ){
            if( $group_type !== 'fc' ) return $user_ids;

            $members = $this->get_group_members( $group_id );

            if( is_array( $members ) ){
                foreach( $members as $uid ){
                    $user_ids[] = (int) $uid;
                }
            }

            return $user_ids;
        }

    }
}
