<?php

namespace App\Http\Controllers;

use App\Models\Customer;
use App\Models\Message;
use App\Models\MessageThread;
use App\Models\ThreadParticipant;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\RateLimiter;

class CommunityController extends Controller
{
    public function lounge()
    {
        $thread = $this->loungeThread();

        $messages = $thread->messages()
            ->orderByDesc('id')
            ->limit(100)
            ->get()
            ->reverse()
            ->values();

        $memberCount = ThreadParticipant::where('message_thread_id', $thread->id)->count();

        // Auto-join authenticated user
        if (Auth::check()) {
            $u = Auth::user();
            $existing = ThreadParticipant::where('message_thread_id', $thread->id)
                ->where(function ($q) use ($u) {
                    $q->where('user_id', $u->id);
                    if ($customerId = optional($u->customerProfile)->id) {
                        $q->orWhere('customer_id', $customerId);
                    }
                })
                ->first();

            if (! $existing) {
                ThreadParticipant::create([
                    'message_thread_id' => $thread->id,
                    'user_id' => $u->isStaff() ? $u->id : null,
                    'customer_id' => ! $u->isStaff() ? optional($u->customerProfile)->id : null,
                    'joined_at' => now(),
                    'last_read_at' => now(),
                    'hotel_id' => $thread->hotel_id,
                ]);
                $memberCount++;
            }
        }

        return view('site.chat.lounge', [
            'thread' => $thread,
            'messages' => $messages,
            'memberCount' => $memberCount,
        ]);
    }

    public function post(Request $request)
    {
        $thread = $this->loungeThread();

        $rules = [
            'body' => 'required|string|max:1000',
        ];

        if (! Auth::check()) {
            $rules['name'] = 'required|string|max:60';
        }

        $data = $request->validate($rules);

        // Rate limit: 5 per minute per session
        $key = 'chat:' . ($request->session()->getId() ?: $request->ip());

        if (RateLimiter::tooManyAttempts($key, 5)) {
            $seconds = RateLimiter::availableIn($key);

            if ($request->wantsJson()) {
                return response()->json(['error' => "Please wait {$seconds}s before sending another message."], 429);
            }

            return back()->with('error', "Please wait {$seconds}s before sending another message.");
        }

        RateLimiter::hit($key, 60);

        $senderUserId = null;
        $senderCustomerId = null;
        $senderName = $data['name'] ?? 'Guest';

        if (Auth::check()) {
            $u = Auth::user();
            $senderName = $u->name;

            if ($u->isStaff()) {
                $senderUserId = $u->id;
            } else {
                $senderCustomerId = optional($u->customerProfile)->id;
            }
        } else {
            // Try to match anon guest to an existing customer by name
            $existing = Customer::where('hotel_id', $thread->hotel_id)
                ->where('name', $senderName)
                ->first();
            if ($existing) {
                $senderCustomerId = $existing->id;
            }
        }

        $message = Message::create([
            'message_thread_id' => $thread->id,
            'sender_user_id' => $senderUserId,
            'sender_customer_id' => $senderCustomerId,
            'sender_name' => $senderName,
            'body' => $data['body'],
            'hotel_id' => $thread->hotel_id,
        ]);

        $thread->update(['last_message_at' => now()]);

        if ($request->wantsJson()) {
            return response()->json([
                'id' => $message->id,
                'name' => $message->displayName(),
                'body' => $message->body,
                'at' => $message->created_at->toIso8601String(),
                'is_staff' => $message->isFromStaff(),
            ]);
        }

        return redirect()->route('site.chat.lounge');
    }

    public function feed(Request $request)
    {
        $thread = $this->loungeThread();

        $query = $thread->messages()->orderBy('id');

        if ($since = $request->input('since')) {
            $ts = is_numeric($since)
                ? Carbon::createFromTimestamp((int) $since)
                : Carbon::parse($since);
            $query->where('created_at', '>', $ts);
        } else {
            $query->latest('id')->limit(30);
        }

        $messages = $query->get();

        if ($request->input('since')) {
            $messages = $messages->sortBy('id')->values();
        } else {
            $messages = $messages->sortBy('id')->values();
        }

        return response()->json([
            'messages' => $messages->map(fn ($m) => [
                'id' => $m->id,
                'name' => $m->displayName(),
                'body' => $m->body,
                'at' => $m->created_at->toIso8601String(),
                'is_staff' => $m->isFromStaff(),
            ])->values(),
            'server_time' => now()->toIso8601String(),
        ]);
    }

    /**
     * Resolve (or create) the single public guest chat thread for the current hotel.
     */
    protected function loungeThread(): MessageThread
    {
        $hotelId = \App\Support\Tenancy::id()
            ?: optional(\App\Models\Hotel::first())->id;

        // Bypass tenant global scope so a fresh install without tenancy still works
        $thread = MessageThread::withoutGlobalScope('hotel')
            ->where('kind', 'guest_chat')
            ->where('is_public', true)
            ->where(function ($q) use ($hotelId) {
                $q->where('hotel_id', $hotelId)->orWhereNull('hotel_id');
            })
            ->orderByDesc('id')
            ->first();

        if ($thread) {
            return $thread;
        }

        return MessageThread::create([
            'subject' => 'Epelcon Community Lounge',
            'kind' => 'guest_chat',
            'is_public' => true,
            'last_message_at' => now(),
            'hotel_id' => $hotelId,
        ]);
    }
}
