<?php

namespace App\Http\Controllers\Api\V1;

use App\Events\Chat\MessageDeleted;
use App\Events\Chat\MessagePinned;
use App\Events\Chat\MessageSent;
use App\Http\Controllers\Controller;
use App\Models\ChatGroup;
use App\Models\ChatGroupMember;
use App\Models\ChatMessage;
use App\Models\User;
use App\Services\FirebaseService;
use Illuminate\Http\Request;

class ChatController extends Controller
{
    public function __construct(private FirebaseService $firebase) {}

    public function groups(Request $request)
    {
        $groups = ChatGroup::with(['event:id,name'])
            ->whereHas('members', function ($q) use ($request) {
                $q->where('user_id', $request->user()->id);
            })
            ->where('status', 'active')
            ->withCount('members')
            ->latest()
            ->get();

        return $this->success($groups);
    }

    public function messages(Request $request, ChatGroup $group)
    {
        $this->authorizeMembership($request, $group);

        $query = ChatMessage::with('user:id,name,profile_photo')
            ->where('chat_group_id', $group->id);

        if ($request->filled('before_id')) {
            $query->where('id', '<', (int) $request->before_id);
        }

        $messages = $query->orderBy('id', 'desc')->paginate(30);

        return $this->paginated($messages);
    }

    public function sendMessage(Request $request, ChatGroup $group)
    {
        $this->authorizeMembership($request, $group);

        $data = $request->validate([
            'body' => ['required', 'string', 'max:2000'],
        ]);

        $message = ChatMessage::create([
            'chat_group_id' => $group->id,
            'user_id'       => $request->user()->id,
            'body'          => $data['body'],
            'type'          => 'text',
        ]);

        $message->load('user:id,name,profile_photo');

        MessageSent::dispatch($message);

        $this->pushToGroupMembers(
            $group,
            $request->user()->id,
            $group->name,
            $request->user()->name . ': ' . mb_strimwidth($data['body'], 0, 100, '…'),
        );

        return $this->created($message, 'Message sent.');
    }

    public function sendImage(Request $request, ChatGroup $group)
    {
        $this->authorizeMembership($request, $group);

        $request->validate([
            'image' => ['required', 'image', 'mimes:jpg,jpeg,png', 'max:5120'],
        ]);

        $path = $request->file('image')->store('chat/' . $group->id, 'public');

        $message = ChatMessage::create([
            'chat_group_id' => $group->id,
            'user_id'       => $request->user()->id,
            'image_path'    => $path,
            'type'          => 'image',
        ]);

        $message->load('user:id,name,profile_photo');

        MessageSent::dispatch($message);

        $this->pushToGroupMembers(
            $group,
            $request->user()->id,
            $group->name,
            $request->user()->name . ' sent an image',
        );

        return $this->created($message, 'Image sent.');
    }

    public function pinMessage(Request $request, ChatMessage $message)
    {
        $group  = ChatGroup::findOrFail($message->chat_group_id);
        $member = $this->authorizeMembership($request, $group);

        if (! in_array($member->role, ['group_admin', 'agency_admin'])) {
            return $this->forbidden('Only group admins can pin messages.');
        }

        $message->update([
            'is_pinned'         => true,
            'pinned_by_user_id' => $request->user()->id,
            'pinned_at'         => now(),
        ]);

        MessagePinned::dispatch($message->fresh());

        return $this->success($message, 'Message pinned.');
    }

    public function deleteMessage(Request $request, ChatMessage $message)
    {
        $group  = ChatGroup::findOrFail($message->chat_group_id);
        $member = $this->authorizeMembership($request, $group);

        $isAdmin = in_array($member->role, ['group_admin', 'agency_admin']);

        if ($message->user_id !== $request->user()->id && ! $isAdmin) {
            return $this->forbidden('You can only delete your own messages.');
        }

        $groupId = $message->chat_group_id;
        $messageId = $message->id;

        $message->delete();

        MessageDeleted::dispatch($messageId, $groupId);

        return $this->noContent('Message deleted.');
    }

    public function members(Request $request, ChatGroup $group)
    {
        $this->authorizeMembership($request, $group);

        $members = $group->members()
            ->with('user:id,name,profile_photo,its_number')
            ->get();

        return $this->success($members);
    }

    private function pushToGroupMembers(ChatGroup $group, int $senderId, string $title, string $body): void
    {
        $memberIds = ChatGroupMember::where('chat_group_id', $group->id)
            ->where('user_id', '!=', $senderId)
            ->pluck('user_id');

        $tokens = User::whereIn('id', $memberIds)
            ->whereNotNull('fcm_token')
            ->pluck('fcm_token')
            ->toArray();

        $this->firebase->sendToTokens(
            $tokens,
            $title,
            $body,
            ['type' => 'chat_message', 'group_id' => (string) $group->id],
        );
    }

    private function authorizeMembership(Request $request, ChatGroup $group): ChatGroupMember
    {
        $member = ChatGroupMember::where('chat_group_id', $group->id)
            ->where('user_id', $request->user()->id)
            ->first();

        if (! $member) {
            abort(403, 'You are not a member of this chat group.');
        }

        return $member;
    }
}
