<?php

namespace Shm\ShmChat\ShmChatBlueprints;

use Shm\Shm;
use Shm\ShmAuth\Auth;
use Shm\ShmChat\SchemaChat\ShmChannelMembers;
use Shm\ShmChat\SchemaChat\ShmChannelMessages;
use Shm\ShmChat\SchemaChat\ShmChannels;
use Shm\ShmChat\ShmChat;
use Shm\ShmDB\mDB;
use Shm\ShmRPC\ShmRPC;
use Shm\ShmUtils\I18n;
use Shm\ShmUtils\ShmDoctor\Utils\StructureHelper;

class ShmChatBlueprintsClientRPC extends ShmChatBlueprintsBaseRPC
{


    public static function init(array $authStructures = [])
    {


        $methods =  [

            "auth" => ShmRPC::auth()->email()->auth($authStructures),

            'mode' => ShmRPC::lazy(function () use ($authStructures) {
                return [
                    'type' => Shm::enum(["widget", "full"]),
                    'resolve' => function ($rootValue, array $args)  use ($authStructures) {

                        if (count($authStructures) > 0) {
                            return 'full';
                        }

                        return 'widget';
                    }
                ];
            }),

            'profileID' => ShmRPC::lazy(function () {
                return [
                    'type' => Shm::string(),
                    'resolve' => function ($rootValue, array $args) {

                        Auth::authenticateOrThrow();

                        return (string) Auth::getAuthID();
                    }
                ];
            }),

            'channelInfo' => ShmRPC::lazy(function () {

                return [

                    'type' =>  ShmChannels::structure(),

                    'args' => Shm::structure([
                        'channel' => Shm::ID(),

                    ]),
                    'resolve' => function ($rootValue, array $args) {


                        if (!isset($args['channel'])) {
                            Shm::error(I18n::get('channel_not_found'));
                        }


                        self::accessValidator($args['channel']);


                        $channel = ShmChannels::findOne([
                            '_id' => mDB::id($args['channel']),
                        ]);


                        return $channel;
                    }
                ];
            }),

            'joinChannel' => ShmRPC::lazy(function () {
                return [
                    'type' => Shm::bool(),
                    'args' => [
                        "channel" =>  Shm::nonNull(Shm::ID()),
                    ],
                    'resolve' => function ($rootValue, array $args) {
                        Auth::authenticateOrThrow();

                        self::accessValidator($args['channel']);



                        $channel = ShmChannels::findOne([
                            '_id' => mDB::id($args['channel']),
                        ]);

                        $members =  $channel->members ?? [];
                        $members = (array) $members;
                        $findMember = array_filter($members, function ($member) {
                            return $member->owner == Auth::getAuthID() && $member->ownerCollection == Auth::getAuthCollection();
                        });




                        if (count($findMember) > 0) {
                            return true;
                        }

                        $structure = StructureHelper::getStructureByCollection(Auth::getAuthCollection());

                        $name = "";
                        if ($structure) {
                            $name = $structure->getChatNameHandler(Auth::getAuthID());
                        }

                        ShmChannels::structure()->updateOne([
                            '_id' => mDB::id($args['channel']),
                        ], [
                            '$push' => [
                                'members' => [
                                    'owner' => Auth::getAuthID(),
                                    'ownerCollection' => Auth::getAuthCollection(),
                                ]
                            ]
                        ]);

                        return true;
                    }
                ];
            }),

            'joinChannelList' => ShmRPC::lazy(function () {
                return [
                    'type' => Shm::structure([
                        'data' => Shm::arrayOf(ShmChannels::structure()),
                        'hash' => Shm::string()
                    ]),
                    'args' => [
                        "limit" => Shm::int()->default(50)->title("Количество сообщений"),
                        "offset" => Shm::int()->default(0)->title("Смещение"),
                    ],
                    'resolve' => function ($rootValue, array $args) {
                        Auth::authenticateOrThrow();


                        if (!ShmChannels::hasJoinablePipelineHandler()) {
                            return [];
                        }

                        $pipeline = ShmChannels::getJoinablePipelineHandler();

                        $pipeline[] = [
                            '$sort' => [
                                'updated_at' => -1
                            ]
                        ];

                        if (isset($args['offset']) && $args['offset'] > 0) {
                            $pipeline[] = [
                                '$skip' => $args['offset']
                            ];
                        }

                        $pipeline[] = [
                            '$limit' => $args['limit'] ?? 50
                        ];

                        $result = ShmChannels::structure()->aggregate($pipeline)->toArray();

                        return [
                            'data' => $result,
                            'hash' => mDB::hashDocuments($result)
                        ];
                    }
                ];
            }),

            'channelList' => ShmRPC::lazy(function () {
                return [
                    'type' => Shm::structure([
                        'data' => Shm::arrayOf(ShmChannels::structure()),
                        'hash' => Shm::string()
                    ]),
                    'args' => [
                        "limit" => Shm::int()->default(50)->title("Количество сообщений"),
                        "offset" => Shm::int()->default(0)->title("Смещение"),
                    ],
                    'resolve' => function ($rootValue, array $args) {
                        Auth::authenticateOrThrow();



                        $pipeline = [
                            [
                                '$match' => [
                                    'members.owner' => Auth::getAuthID(),
                                    'members.ownerCollection' => Auth::getAuthCollection(),
                                ]
                            ],
                            [
                                '$sort' => [
                                    'updated_at' => -1
                                ]
                            ]
                        ];




                        if (isset($args['offset']) && $args['offset'] > 0) {
                            $pipeline[] = [
                                '$skip' => $args['offset']
                            ];
                        }

                        $pipeline[] = [
                            '$limit' => $args['limit'] ?? 50
                        ];


                        $result = ShmChannels::structure()->aggregate($pipeline)->toArray();



                        return [
                            'data' => $result,
                            'hash' => mDB::hashDocuments($result)
                        ];
                    }
                ];
            }),
            'channelSendMessage' => ShmRPC::lazy(function () {
                return [

                    'type' => ShmChannelMessages::structure(),
                    'args' => [
                        "channel" => Shm::nonNull(Shm::ID()),
                        'reply' => Shm::ID(),
                        "text" => Shm::string()->title("Текст сообщения"),
                        "attachments" => Shm::arrayOf(Shm::fileDocument())->title("Вложения"),
                        'voice' => Shm::fileAudio(),
                        "payload" => Shm::structure([
                            '*' => Shm::mixed()
                        ]),
                    ],
                    'resolve' => function ($rootValue, $args) {

                        self::accessValidator($args['channel']);

                        $channel = ShmChannels::structure()->findOne([
                            '_id' => mDB::id($args['channel']),
                        ]);

                        if (!$channel) {
                            Shm::error(I18n::get('channel_not_found'));
                        }



                        $insert =  ShmChannelMessages::structure()->insertOne([
                            "channel" => $channel->_id,
                            'owner' => Auth::getAuthID(),
                            'ownerCollection' => Auth::getAuthCollection(),
                            "text" => $args['text'] ?? "",
                            'reply' => $args['reply'] ?? null,
                            "attachments" => $args['attachments'] ?? [],
                            "voice" => $args['voice'] ?? null,
                            "type" => 'regular',
                            "custom" => $args['custom'] ?? null,
                        ]);


                        return ShmChannelMessages::structure()->findOne([
                            "_id" => $insert->getInsertedId(),

                        ]);
                    },


                ];
            }),




            'channelClose' => ShmRPC::lazy(function () {
                return [
                    'type' => Shm::bool(),
                    'args' => [
                        "channel" => Shm::ID(),
                    ],
                    'resolve' => function ($rootValue, array $args) {
                        self::accessValidator($args['channel']);

                        ShmChannels::structure()->updateOne([
                            '_id' => mDB::id($args['channel']),
                        ], ['$set' => ['closed' => true]]);

                        $channel = ShmChannels::structure()->findOne([
                            '_id' => mDB::id($args['channel']),
                        ]);

                        $channelType = $channel->type ?? 'default';

                        $text = "Диалог закрыт";
                        if ($channelType == 'support') {
                            $text = "Обращение закрыто";
                        }

                        ShmChannelMessages::structure()->insertOne([

                            'channel' => mDB::id($args['channel']),
                            'owner' => Auth::getAuthID(),
                            'ownerCollection' => Auth::getAuthCollection(),
                            'text' => $text,
                            'type' => 'system',
                        ]);


                        return true;
                    }
                ];
            }),


            'channelMessages' => ShmRPC::lazy(function () {
                return [
                    'type' => Shm::structure([
                        'data' => Shm::arrayOf(ShmChannelMessages::structure()),
                        'hash' => Shm::string()
                    ]),
                    'args' => [
                        "channel" => Shm::string(),
                        "limit" => Shm::int()->default(50)->title("Количество сообщений"),
                        "offset" => Shm::int()->default(0)->title("Смещение"),
                    ],
                    'resolve' => function ($rootValue, array $args) {


                        if (!isset($args['channel'])) {
                            Shm::error(I18n::get('channel_not_found'));
                        }





                        self::accessValidator($args['channel']);



                        ShmChannels::zeroUnreadCounts($args['channel'], Auth::getAuthID());





                        $channel = ShmChannels::structure()->findOne([
                            '_id' => mDB::id($args['channel']),
                        ]);

                        if (!$channel) {
                            Shm::error(I18n::get('channel_not_found'));
                        }



                        $pipeline = [
                            [
                                '$match' => [
                                    'channel' => $channel->_id,

                                ]
                            ],
                            [
                                '$sort' => ['_id' => -1]
                            ]
                        ];

                        if (isset($args['offset']) && $args['offset'] > 0) {
                            $pipeline[] = [
                                '$skip' => $args['offset']
                            ];
                        }

                        $pipeline[] = [
                            '$limit' => $args['limit'] ?? 50
                        ];


                        $result = ShmChannelMessages::structure()->aggregate($pipeline)->toArray();


                        return [
                            'data' => array_reverse($result),
                            'hash' => mDB::hashDocuments($result)
                        ];
                    }
                ];
            }),

            'pinnedMessage' => ShmRPC::lazy(
                function () {
                    return [
                        'type' => Shm::bool(),
                        'args' => [
                            "message" => Shm::ID(),
                        ],
                        'resolve' => function ($rootValue, array $args) {

                            Auth::authenticateOrThrow();




                            ShmChannelMessages::togglePinnedMessage($args['message'], Auth::getAuthOwner());

                            return true;
                        }
                    ];
                }
            ),
            'channelReaction' => ShmRPC::lazy(function () {
                return [
                    'type' => Shm::bool(),
                    'args' => [
                        "message" => Shm::ID(),
                        "channel" => Shm::ID(),
                        "reaction" => Shm::enum([
                            "heart" => "Сердце",
                            "like" => "Нравится",
                            "laugh" => "Смех",
                            "wow" => "Удивление",
                            "sad" => "Грусть",
                            "angry" => "Злость",
                            "clap" => "Аплодисменты",
                            "party" => "Праздник",
                            "poop" => "Какахa",
                            "fire" => "Огонь"
                        ])
                    ],
                    'resolve' => function ($rootValue, array $args) {

                        if (!isset($args['channel']) || !isset($args['message']) || !isset($args['reaction'])) {
                            Shm::error(I18n::get('channel_message_reaction_not_found'));
                        }

                        self::accessValidator($args['channel']);

                        $message = ShmChannelMessages::structure()->findOne([
                            "_id" => mDB::id($args['message']),
                            "channel" => mDB::id($args['channel']),

                        ]);

                        if (!$message) {
                            Shm::error(I18n::get('message_not_found'));
                        }

                        $reactionType = $args['reaction'];
                        $userIdObj = mDB::id(Auth::getAuthID());
                        $messageIdObj = mDB::id($args['message']);

                        $collection = ShmChannelMessages::structure();

                        // Проверяем, есть ли уже такая реакция от пользователя
                        $existing = $collection->findOne([
                            '_id' => $messageIdObj,
                            'reactions' => [
                                '$elemMatch' => [
                                    'user' => $userIdObj,
                                    'type' => $reactionType,
                                ]
                            ]
                        ]);

                        if ($existing) {
                            // Если есть — убираем реакцию (отжимаем)
                            $collection->updateOne(
                                ['_id' => $messageIdObj],
                                [
                                    '$pull' => [
                                        'reactions' => [
                                            'user' => $userIdObj,
                                            'type' => $reactionType,
                                        ]
                                    ]
                                ]
                            );
                        } else {
                            // Удаляем любые другие реакции от этого пользователя
                            $collection->updateOne(
                                ['_id' => $messageIdObj],
                                [
                                    '$pull' => [
                                        'reactions' => [
                                            'user' => $userIdObj
                                        ]
                                    ]
                                ]
                            );

                            // Добавляем новую реакцию
                            $collection->updateOne(
                                ['_id' => $messageIdObj],
                                [
                                    '$push' => [
                                        'reactions' => [
                                            'user' => $userIdObj,
                                            'type' => $reactionType,
                                            'created_at' => time()
                                        ]
                                    ]
                                ]
                            );
                        }


                        return true;
                    }
                ];
            }),



            'channelDeleteMessage' => ShmRPC::lazy(function () {
                return [
                    'type' => Shm::bool(),
                    'args' => [
                        "channel" => Shm::ID(),
                        "message" => Shm::ID(),
                    ],
                    'resolve' => function ($rootValue, array $args) {
                        if (!isset($args['channel']) || !isset($args['message'])) {
                            Shm::error(I18n::get('channel_or_message_not_found'));
                        }
                        self::accessValidator($args['channel']);


                        ShmChannelMessages::structure()->updateOne([
                            '_id' => mDB::id($args['message']),
                            'channel' => mDB::id($args['channel']),
                            'owner' => Auth::getAuthID(),
                            'ownerCollection' => Auth::getAuthCollection(),
                        ], ['$set' => ['deleted' => Auth::getAuthID()]]);

                        return true;
                    }
                ];
            }),

            'channelDocumentUpload' => ShmRPC::fileUpload()->document(),
            'channelVoiceUpload' => ShmRPC::fileUpload()->audio(),
        ];




        ShmRPC::init($methods);
    }
}