<?php

namespace App\Repositories\General;

use Exception;
use Throwable;
use App\Models\User;
use App\Models\Message;
use App\Models\Conversation;
use Illuminate\Http\Request;
use App\Services\ImageService;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class ConversationRepository
{
    protected $imageService;

    public function __construct(ImageService $imageService)
    {
        $this->imageService = $imageService;
    }

    public function getAll()
    {
        $conversations = auth()->user()->conversations()->with([
            'participants.image',
            'messages.user',
            'messages.images',
        ])
            ->latest('updated_at')
            ->paginate(12)
            ->withQueryString();

        return compact('conversations');
    }

    protected function getOldConversation(User $user)
    {
        $oldConversations = auth()->user()->conversations;
        $conversation = null;
        $conversationList = [];
        if ($oldConversations->count() > 0) {
            foreach ($oldConversations as $oldConversation) {
                $result = $oldConversation->participants->filter(function ($participant) use ($user) {
                    return $participant->id == $user->id;
                });

                if (count($result) > 0) {
                    $conversationList[] = $oldConversation;
                }
            }
        }
        if (count($conversationList) > 0) {
            foreach ($conversationList as $filteredConversation) {
                $participantCount = $filteredConversation->participants->count();

                if ($participantCount > 0) {
                    $conversation = $filteredConversation;
                    break;
                }
            }
        }

        return $conversation;
    }

    protected function getOldGroupConversation(User $user)
    {
    }

    public function show(User $user)
    {
        $conversation = $this->getOldConversation($user);

        return compact('conversation');
    }

    public function save(Request $request, User $user)
    {
        try {
            DB::beginTransaction();

            $conversation = $this->getOldConversation($user);

            $loginUser = auth()->user();
            if (!$conversation) {
                $conversation = Conversation::create([]);
                $conversation->participants()->saveMany([$loginUser, $user]);
            }
            $message = $conversation->messages()->updateOrCreate([
                'message_id' => $request->message_id,
            ], [
                'user_id' => $loginUser->id,
                'content' => $request->content,
            ]);

            if (count($request->images) > 0) {
                $images = $this->imageService->uploadMany($request->images, Message::class, $message->id);
                $message->images()->saveMany($images);
            }

            DB::commit();
        } catch (Throwable $e) {
            DB::rollBack();

            Log::error(__CLASS__ . '::' . __FUNCTION__ . '[line: ' . __LINE__ . ']Message: ' . $e->getMessage());

            throw new Exception('Message saved failed.');
        }
    }

    public function seen(User $user, $messageId)
    {
        $conversation = $this->getOldConversation($user);

        abort_if($conversation == null, 404, 'Not Found.');
        if ($conversation) {
            $message = $conversation->messages()->findOrFail($messageId);
        }

        $message->seenUsers()->sync([auth()->id()]);
    }

    public function deleteMessage(User $user, $messageId)
    {
        $conversation = $this->getOldConversation($user);

        abort_if($conversation == null, 404, 'Not Found.');
        if ($conversation) {
            $message = $conversation->messages()->findOrFail($messageId);
            $message->delete();
        }
    }

    public function saveGroup(Request $request)
    {
        try {
            DB::beginTransaction();
            DB::commit();
        } catch (Throwable $e) {
            DB::rollBack();

            Log::error(__CLASS__ . '::' . __FUNCTION__ . '[line: ' . __LINE__ . ']Message: ' . $e->getMessage());

            throw new Exception('Conversation Group saved failed.');
        }
    }

    public function showGroup($conversationId)
    {
    }

    public function saveGroupMessage(Request $request, $conversationId)
    {
    }

    public function seenGroup($conversationId, $messageId)
    {
    }

    public function deleteGroupMessage($conversationId, $messageId)
    {
    }

    public function deleteConversation($conversationId)
    {
        $loginUserId = auth()->id();
        $conversation = Conversation::findOrFail($conversationId);

        if ($conversation->participants->count > 2) {
            abort_unless($conversation->user_id == $loginUserId, 403, 'Unauthorized action.');
        } else {
            abort_unless($conversation->participants()->find($loginUserId)?->exists(), 403, 'Unauthorized action.');
        }
        $conversation->delete();
    }
}
