<?php

namespace App\Http\Controllers\Api;

use App\Events\MessageSent;
use App\Http\Controllers\Controller;
use App\Models\ChatRoom;
use App\Models\ChatRequest;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class ChatController extends Controller
{
    public function index(Request $request): JsonResponse
    {
        $user = $request->user();

        $chats = ChatRoom::forUser($user->id)
            ->active()
            ->with([
                'creator:id,name',
                'lastMessage:id,message,sent_at,sender_id,is_read',
                'participants' => fn ($q) => $q->where('user_id', $user->id),
            ])
            ->withUnreadCount($user->id)
            ->latest('updated_at')
            ->limit(20)
            ->get();

        return response()->json($chats);
    }

    public function show(Request $request, ChatRoom $chat): JsonResponse
    {
        $user = $request->user();

        if (! $chat->participants()->where('user_id', $user->id)->where('is_blocked', false)->exists()) {
            return response()->json(['error' => 'Forbidden'], 403);
        }

        $chat->participants()->where('user_id', $user->id)->first()?->updateLastSeen();

        return response()->json($chat->load([
            'participants.user:id,name,status',
            'lastMessage:id,message,sent_at,sender_id,is_read',
        ]));
    }

    /**
     * GET /api/v1/chat/rooms/{chat}/messages
     *
     * Returns paginated messages for a chat room, oldest-first.
     * Also bulk-marks unread messages as read for the auth user.
     */
    public function getMessages(Request $request, ChatRoom $chat): JsonResponse
    {
        $user = $request->user();

        if (! $chat->participants()->where('user_id', $user->id)->where('is_blocked', false)->exists()) {
            return response()->json(['error' => 'Forbidden'], 403);
        }

        // Bulk mark as read — single UPDATE query, no N+1
        $chat->messages()
            ->where('sender_id', '!=', $user->id)
            ->where('is_read', false)
            ->update(['is_read' => true, 'read_at' => now()]);

        $chat->participants()->where('user_id', $user->id)->first()?->updateLastSeen();

        // oldest-first so the frontend renders top-to-bottom correctly
        $messages = $chat->messages()
            ->with('senderUser:id,name')     // renamed relationship from our ChatMessage fix
            ->orderBy('sent_at', 'asc')
            ->paginate(50);

        return response()->json($messages);
    }

    /**
     * POST /api/v1/chat/rooms/{chat}/messages
     */
    public function storeMessage(Request $request, ChatRoom $chat): JsonResponse
    {
        $user = $request->user();

        if (! $chat->participants()->where('user_id', $user->id)->where('is_blocked', false)->exists()) {
            return response()->json(['error' => 'Forbidden'], 403);
        }

        $validated = $request->validate([
            'message'      => 'required|string|max:5000',
            'message_type' => 'sometimes|string|in:text,image,file,audio,video',
        ]);

        $message = $chat->messages()->create([
            'sender_id'    => $user->id,
            'message_type' => $validated['message_type'] ?? 'text',
            'message'      => $validated['message'],
            'sent_at'      => now(),
        ]);

        $chat->update(['last_message_id' => $message->message_id]);
        $chat->touch();

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

        // Broadcast — wrapped in try/catch so a missing Pusher key
        // does not crash the response with a 500. The message is already
        // saved; broadcasting is best-effort.
        try {
            broadcast(new MessageSent($message))->toOthers();
        } catch (\Throwable $e) {
            \Log::warning('[chat] broadcast failed: ' . $e->getMessage());
        }

        return response()->json($message, 201);
    }

    /**
     * POST /api/v1/chat/rooms/private
     */
    public function privateRoom(Request $request): JsonResponse
    {
        $request->validate([
            'receiver_id' => 'required|integer|exists:users,id',
        ]);

        $user       = $request->user();
        $receiverId = (int) $request->receiver_id;

        if ($receiverId === $user->id) {
            return response()->json(['error' => 'Cannot create a chat with yourself'], 400);
        }

        // FIX — getOrCreatePrivate now requires creatorId as 3rd argument
        $room = ChatRoom::getOrCreatePrivate($user->id, $receiverId, $user->id);

        $room->load([
            'participants.user:id,name,status',
            'lastMessage:id,message,sent_at,sender_id,is_read',
        ]);

        return response()->json($room);
    }

    public function contacts(Request $request): JsonResponse  { return $this->comingSoonResponse(); }
    public function requests(Request $request): JsonResponse  { return $this->comingSoonResponse(); }
    public function storeRequest(Request $request): JsonResponse { return $this->comingSoonResponse(); }
    public function updateRequest(Request $request, ChatRequest $chatRequest): JsonResponse { return $this->comingSoonResponse(); }
    public function settings(Request $request): JsonResponse  { return $this->comingSoonResponse(); }
    public function updateSettings(Request $request): JsonResponse { return $this->comingSoonResponse(); }
    public function comingSoon(): JsonResponse                { return $this->comingSoonResponse(); }

    private function comingSoonResponse(): JsonResponse
    {
        return response()->json(['message' => 'Coming Soon'], 501);
    }
}