<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Conversation;
use App\Models\Message;
use App\Events\MessageSent;
use App\Events\MessagesRead;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class ChatController extends Controller
{
    public function index(Request $request)
    {
        $perPage = min((int) ($request->get('per_page', 20)), 50);
        $page = max(1, (int) $request->get('page', 1));

        $query = Auth::user()->conversations()
            ->with(['participants', 'lastMessage', 'listing.coverImage'])
            ->orderByRaw('(SELECT MAX(created_at) FROM messages WHERE messages.conversation_id = conversations.id) DESC');

        $total = $query->count();
        $conversations = $query
            ->skip(($page - 1) * $perPage)
            ->take($perPage)
            ->get();

        return response()->json([
            'conversations' => $conversations,
            'pagination' => [
                'current_page' => $page,
                'per_page' => $perPage,
                'total' => $total,
                'has_more' => ($page * $perPage) < $total,
            ],
        ]);
    }

    public function findByParticipant(Request $request)
    {
        $request->validate([
            'receiver_id' => 'required|exists:users,id',
            'listing_id' => 'nullable|exists:listings,id',
        ]);

        $receiverId = (int) $request->receiver_id;
        $listingId = $request->listing_id ? (int) $request->listing_id : null;

        $query = Auth::user()->conversations()
            ->whereHas('participants', fn ($q) => $q->where('user_id', $receiverId));

        if ($listingId !== null) {
            $query->where('listing_id', $listingId);
        } else {
            $query->whereNull('listing_id');
        }

        $conversation = $query->first();

        return response()->json([
            'conversation_id' => $conversation?->id,
        ]);
    }

    public function show(Request $request, Conversation $conversation)
    {
        // Check if user is participant
        if (!$conversation->participants()->where('user_id', Auth::id())->exists()) {
            return response()->json(['message' => 'Unauthorized'], 403);
        }

        $perPage = min((int) ($request->get('per_page', 20)), 50);
        $page = max(1, (int) $request->get('page', 1));

        $query = $conversation->messages()
            ->with(['sender', 'post.user:id,name,username,avatar', 'post.images'])
            ->orderBy('created_at', 'desc');
        $total = $query->count();
        $messages = $query->skip(($page - 1) * $perPage)->take($perPage)->get()->reverse()->values();

        $payload = [
            'messages' => $messages,
            'pagination' => [
                'current_page' => $page,
                'per_page' => $perPage,
                'total' => $total,
                'has_more' => ($page * $perPage) < $total,
            ],
        ];

        if ($page === 1) {
            $conversation->load(['participants', 'listing.coverImage']);
            $payload['conversation'] = $conversation;
        }

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

    public function store(Request $request)
    {
        $request->validate([
            'content' => 'nullable|string',
            'conversation_id' => 'nullable|exists:conversations,id',
            'receiver_id' => 'required_without:conversation_id|exists:users,id',
            'listing_id' => 'nullable|exists:listings,id',
            'post_id' => 'nullable|exists:posts,id',
        ]);

        // Kullanıcı kendine mesaj gönderemez
        if ($request->receiver_id && $request->receiver_id == Auth::id()) {
            return response()->json([
                'message' => 'Kendinize mesaj gönderemezsiniz.',
            ], 422);
        }

        $conversationId = $request->conversation_id;
        $content = $request->content ?? '';

        // If no conversation_id, find or create one between sender and receiver
        if (!$conversationId) {
            $receiverId = $request->receiver_id;
            $conversation = Auth::user()->conversations()
                ->whereHas('participants', function ($query) use ($receiverId) {
                    $query->where('user_id', $receiverId);
                })
                ->where('listing_id', $request->listing_id)
                ->first();

            if (!$conversation) {
                $conversation = Conversation::create([
                    'listing_id' => $request->listing_id
                ]);
                $conversation->participants()->attach(array_unique([Auth::id(), $receiverId]));
            }
            $conversationId = $conversation->id;
        } else {
            $conversation = Conversation::findOrFail($conversationId);
        }

        $message = null;
        $postId = $request->post_id;
        $hasContent = !empty($content) || $postId;

        if ($hasContent) {
            $message = Message::create([
                'conversation_id' => $conversationId,
                'sender_id' => Auth::id(),
                'content' => $content,
                'type' => $postId ? 'shared_post' : 'text',
                'post_id' => $postId,
            ]);

            // Tüm katılımcılara broadcast et (toOthers() yerine)
            // toOthers() gönderen kişiye göndermez, ama aynı kullanıcının farklı cihazlarında görünmesi gerekir
            broadcast(new MessageSent($message));

            // Notify specific user about new message for unread count + in-app banner
            $conversation->load('participants');
            foreach ($conversation->participants as $participant) {
                if ($participant->id !== Auth::id()) {
                    try {
                        \Log::info('Broadcasting UserNotificationsUpdated', [
                            'to_user' => $participant->id,
                            'channel' => 'private-user.' . $participant->id,
                            'conversation_id' => $conversationId,
                            'sender' => Auth::user()->name,
                        ]);
                        broadcast(new \App\Events\UserNotificationsUpdated(
                            userId: $participant->id,
                            type: 'new_message',
                            conversationId: $conversationId,
                            senderName: Auth::user()->name,
                            messagePreview: strlen($content) > 50 ? substr($content, 0, 50) . '...' : $content,
                        ));
                        \Log::info('UserNotificationsUpdated broadcast BAŞARILI', ['to_user' => $participant->id]);
                    } catch (\Throwable $e) {
                        \Log::error('UserNotificationsUpdated broadcast HATASI', [
                            'to_user' => $participant->id,
                            'error' => $e->getMessage(),
                            'trace' => $e->getTraceAsString(),
                        ]);
                    }
                }
            }

            // Send OneSignal Push Notification
            $receiverId = $conversation->participants()->where('user_id', '!=', Auth::id())->first()?->id;
            if ($receiverId && $message) {
                try {
                    app(\App\Services\OneSignalService::class)->sendToUser(
                        userId: $receiverId,
                        title: Auth::user()->name,
                        message: $content,
                        data: [
                            'type' => 'chat',
                            'conversation_id' => $conversationId,
                        ],
                        idempotencyKey: static::idempotencyKeyForChat($conversationId, $message->id),
                    );
                } catch (\Throwable $e) {
                    \Illuminate\Support\Facades\Log::error('Chat push bildirim hatası', ['error' => $e->getMessage()]);
                }
            }
        }

        // Eğer mesaj oluşturulmadıysa, sadece conversation bilgisini döndür
        if (!$message) {
            return response()->json([
                'conversation_id' => $conversationId,
                'message' => null,
            ]);
        }

        $message->load(['sender', 'post.user:id,name,username,avatar', 'post.images']);

        return response()->json([
            'message' => $message,
        ]);
    }

    public function unreadCount()
    {
        $count = Message::whereHas('conversation.participants', function ($query) {
            $query->where('user_id', Auth::id());
        })
            ->where('sender_id', '!=', Auth::id())
            ->where('is_read', false)
            ->count();

        return response()->json(['count' => $count]);
    }


    public function markAsRead(Conversation $conversation)
    {
        $conversation->messages()
            ->where('sender_id', '!=', Auth::id())
            ->where('is_read', false)
            ->update([
                'is_read' => true,
                'read_at' => now()
            ]);

        broadcast(new MessagesRead($conversation->id, Auth::id()));

        return response()->json(['message' => 'Messages marked as read']);
    }

    /** OneSignal idempotency için UUID formatında deterministik anahtar */
    private static function idempotencyKeyForChat(int $conversationId, int $messageId): string
    {
        $h = hash('sha256', 'kaptango:chat:' . $conversationId . ':' . $messageId);
        return substr($h, 0, 8) . '-' . substr($h, 8, 4) . '-' . substr($h, 12, 4) . '-' . substr($h, 16, 4) . '-' . substr($h, 20, 12);
    }
}
