<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Http\Resources\MessengerMessageResource;
use App\Models\MessengerConversation;
use App\Models\MessengerMessage;
use App\Support\AccessControl;
use App\Support\CrmModuleManager;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;

class MessengerMessageController extends Controller
{
    public function index(Request $request, MessengerConversation $conversation)
    {
        $this->authorize('view', $conversation);

        $direction = trim((string) $request->input('direction', ''));
        $status = trim((string) $request->input('status', ''));
        $dateFrom = trim((string) $request->input('date_from', ''));
        $dateTo = trim((string) $request->input('date_to', ''));

        $messages = MessengerMessage::query()
            ->with('user:id,name,email')
            ->where('conversation_id', $conversation->id)
            ->when($direction !== '', fn ($query) => $query->where('direction', $direction))
            ->when($status !== '', fn ($query) => $query->where('status', $status))
            ->when($dateFrom !== '', fn ($query) => $query->whereDate('sent_at', '>=', $dateFrom))
            ->when($dateTo !== '', fn ($query) => $query->whereDate('sent_at', '<=', $dateTo))
            ->orderBy('sent_at')
            ->orderBy('id')
            ->paginate(50)
            ->withQueryString();

        return MessengerMessageResource::collection($messages);
    }

    public function store(Request $request, MessengerConversation $conversation, CrmModuleManager $moduleManager): MessengerMessageResource
    {
        $this->authorize('view', $conversation);
        $this->authorize('create', MessengerMessage::class);

        $validated = $request->validate([
            'external_id' => ['nullable', 'string', 'max:255'],
            'direction' => ['required', Rule::in(['inbound', 'outbound'])],
            'body' => ['nullable', 'string', 'max:5000'],
            'attachments' => ['nullable', 'array'],
            'status' => ['required', Rule::in(['new', 'sent', 'delivered', 'read', 'failed'])],
            'sent_at' => ['nullable', 'date'],
            'user_id' => ['nullable', 'exists:users,id'],
            'meta' => ['nullable', 'array'],
        ]);

        if (! AccessControl::isElevated($request->user())) {
            $validated['user_id'] = $request->user()->id;
        }

        $payload = [
            'conversation_id' => $conversation->id,
            'external_id' => $this->nullableText($validated['external_id'] ?? null),
            'direction' => (string) $validated['direction'],
            'body' => $this->nullableText($validated['body'] ?? null),
            'attachments' => $validated['attachments'] ?? null,
            'status' => (string) $validated['status'],
            'sent_at' => $validated['sent_at'] ?? now(),
            'user_id' => $validated['user_id'] ?? null,
            'meta' => $validated['meta'] ?? null,
        ];

        if ($payload['external_id']) {
            $exists = MessengerMessage::query()
                ->where('conversation_id', $conversation->id)
                ->where('external_id', $payload['external_id'])
                ->exists();

            if ($exists) {
                abort(422, 'Message external ID must be unique for this conversation.');
            }
        }

        $payload = $moduleManager->applyPayloadHooks('messengers.messages.store', $payload, [
            'hook' => 'messengers.messages.store',
            'user_id' => $request->user()->id,
            'conversation_id' => $conversation->id,
            'source' => 'api',
        ], array_keys($payload));

        $message = MessengerMessage::query()->create($payload);
        $conversation->update(['last_message_at' => $payload['sent_at'] ?? now()]);

        return MessengerMessageResource::make($message->load('user'));
    }

    public function show(MessengerMessage $message): MessengerMessageResource
    {
        $this->authorize('view', $message);

        return MessengerMessageResource::make($message->load('user'));
    }

    public function update(Request $request, MessengerMessage $message, CrmModuleManager $moduleManager): MessengerMessageResource
    {
        $this->authorize('update', $message);

        $validated = $request->validate([
            'external_id' => ['nullable', 'string', 'max:255'],
            'direction' => ['required', Rule::in(['inbound', 'outbound'])],
            'body' => ['nullable', 'string', 'max:5000'],
            'attachments' => ['nullable', 'array'],
            'status' => ['required', Rule::in(['new', 'sent', 'delivered', 'read', 'failed'])],
            'sent_at' => ['nullable', 'date'],
            'user_id' => ['nullable', 'exists:users,id'],
            'meta' => ['nullable', 'array'],
        ]);

        if (! AccessControl::isElevated($request->user())) {
            $validated['user_id'] = $request->user()->id;
        }

        $payload = [
            'external_id' => $this->nullableText($validated['external_id'] ?? $message->external_id),
            'direction' => (string) $validated['direction'],
            'body' => $this->nullableText($validated['body'] ?? $message->body),
            'attachments' => $validated['attachments'] ?? $message->attachments,
            'status' => (string) $validated['status'],
            'sent_at' => $validated['sent_at'] ?? $message->sent_at,
            'user_id' => $validated['user_id'] ?? $message->user_id,
            'meta' => $validated['meta'] ?? $message->meta,
        ];

        if ($payload['external_id']) {
            $exists = MessengerMessage::query()
                ->where('conversation_id', $message->conversation_id)
                ->where('external_id', $payload['external_id'])
                ->whereKeyNot($message->id)
                ->exists();

            if ($exists) {
                abort(422, 'Message external ID must be unique for this conversation.');
            }
        }

        $payload = $moduleManager->applyPayloadHooks('messengers.messages.update', $payload, [
            'hook' => 'messengers.messages.update',
            'user_id' => $request->user()->id,
            'message_id' => $message->id,
            'source' => 'api',
        ], array_keys($payload));

        $message->update($payload);
        $message->conversation?->update(['last_message_at' => $payload['sent_at'] ?? now()]);

        return MessengerMessageResource::make($message->load('user'));
    }

    public function destroy(MessengerMessage $message)
    {
        $this->authorize('delete', $message);

        $message->delete();

        return response()->noContent();
    }

    private function nullableText(mixed $value): ?string
    {
        $value = trim((string) $value);

        return $value === '' ? null : $value;
    }
}
