<?php

namespace App\Http\Controllers;

use App\Models\User;
use App\Models\WhatsAppConversation;
use App\Models\WhatsAppMessage;
use App\Services\WhatsAppMessageLogger;
use App\Services\WhatsAppService;
use Carbon\Carbon;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Schema;
use Throwable;

class WhatsAppInboxController extends Controller
{
    public function __construct(
        protected WhatsAppService $whatsapp
    ) {}

    /** Tablas/columnas del take over (migración 2026_04_17_*). */
    protected function inboxSchemaReady(): bool
    {
        return Schema::hasTable('whatsapp_messages')
            && Schema::hasColumn('whatsapp_conversations', 'human_takeover');
    }

    /**
     * Sin columna `data` (JSON del flujo del bot): si está corrupta, hidratar el modelo no falla en el inbox.
     *
     * @return list<string>
     */
    protected function conversationColumnsForInbox(): array
    {
        return [
            'id',
            'phone',
            'state',
            'human_takeover',
            'human_takeover_at',
            'human_takeover_by',
            'last_message_at',
            'created_at',
            'updated_at',
        ];
    }

    protected static function messageCreatedIso(mixed $created): ?string
    {
        if ($created === null) {
            return null;
        }
        try {
            return $created instanceof Carbon
                ? $created->toIso8601String()
                : Carbon::parse($created)->toIso8601String();
        } catch (Throwable) {
            return null;
        }
    }

    /**
     * Texto del último mensaje por conversación (para lista tipo inbox).
     *
     * @param  list<string>  $phones
     * @return array<string, string>
     */
    protected function lastMessagePreviewByPhones(array $phones): array
    {
        if ($phones === []) {
            return [];
        }

        $sub = WhatsAppMessage::query()
            ->selectRaw('phone, MAX(id) as max_id')
            ->whereIn('phone', $phones)
            ->groupBy('phone');

        $q = WhatsAppMessage::query()
            ->joinSub($sub, 'last_msg', function ($join) {
                $join->on('whatsapp_messages.phone', '=', 'last_msg.phone')
                    ->on('whatsapp_messages.id', '=', 'last_msg.max_id');
            });

        $out = [];
        foreach ($q->get(['whatsapp_messages.phone', 'whatsapp_messages.body']) as $m) {
            $b = $m->body;
            $text = is_string($b) ? trim($b) : '';
            if (strlen($text) > 160) {
                $text = substr($text, 0, 157).'…';
            }
            $out[$m->phone] = $text;
        }

        return $out;
    }

    /**
     * Nombre de perfil de WhatsApp (Meta envía `contact_name` en meta del último mensaje entrante).
     *
     * @param  list<string>  $phones
     * @return array<string, string>
     */
    protected function waProfileNameFromLatestClientMessage(array $phones): array
    {
        if ($phones === []) {
            return [];
        }

        $sub = WhatsAppMessage::query()
            ->selectRaw('phone, MAX(id) as max_id')
            ->whereIn('phone', $phones)
            ->where('sender_type', 'client')
            ->groupBy('phone');

        $q = WhatsAppMessage::query()
            ->joinSub($sub, 'last_in', function ($join) {
                $join->on('whatsapp_messages.phone', '=', 'last_in.phone')
                    ->on('whatsapp_messages.id', '=', 'last_in.max_id');
            });

        $out = [];
        foreach ($q->get(['whatsapp_messages.phone', 'whatsapp_messages.meta']) as $m) {
            $meta = $m->meta;
            if (! is_array($meta)) {
                continue;
            }
            $n = $meta['contact_name'] ?? null;
            if (is_string($n) && trim($n) !== '') {
                $out[$m->phone] = trim($n);
            }
        }

        return $out;
    }

    public function index(Request $request): JsonResponse
    {
        if (! $this->inboxSchemaReady()) {
            return response()->json([
                'conversations' => [],
                'setup_required' => 'En el servidor (raíz Laravel): php artisan migrate --force',
            ]);
        }

        $rows = WhatsAppConversation::query()
            ->select($this->conversationColumnsForInbox())
            ->with('takeoverUser')
            ->orderByDesc(DB::raw('COALESCE(last_message_at, updated_at)'))
            ->limit(100)
            ->get();

        $clientNames = [];
        $users = User::query()
            ->where('role', 'client')
            ->whereNotNull('phone')
            ->get(['name', 'phone']);
        foreach ($users as $u) {
            $d = WhatsAppMessageLogger::normalizePhone($u->phone ?? '');
            if ($d !== '') {
                $clientNames[$d] = $u->name;
            }
        }

        $phones = $rows->pluck('phone')->all();
        $lastPreviews = $this->lastMessagePreviewByPhones($phones);
        $waContactNames = $this->waProfileNameFromLatestClientMessage($phones);

        $list = $rows->map(function ($c) use ($clientNames, $lastPreviews, $waContactNames) {
            return [
                'phone' => $c->phone,
                'human_takeover' => $c->human_takeover,
                'human_takeover_at' => $c->human_takeover_at?->toIso8601String(),
                'takeover_user_name' => $c->takeoverUser?->name,
                'last_message_at' => $c->last_message_at?->toIso8601String(),
                'last_message' => $lastPreviews[$c->phone] ?? null,
                'state' => $c->state,
                'client_name' => $clientNames[$c->phone] ?? null,
                'wa_contact_name' => $waContactNames[$c->phone] ?? null,
            ];
        });

        return response()
            ->json(['conversations' => $list])
            ->header('Cache-Control', 'private, no-store, no-cache, must-revalidate')
            ->header('Pragma', 'no-cache');
    }

    public function messages(Request $request, string $phone): JsonResponse
    {
        if (! $this->inboxSchemaReady()) {
            return response()->json([
                'conversation' => null,
                'messages' => [],
                'setup_required' => 'En el servidor (raíz Laravel): php artisan migrate --force',
            ]);
        }

        $digits = preg_replace('/\D/', '', $phone);
        if ($digits === '') {
            return response()->json(['message' => 'Teléfono inválido.'], 422);
        }

        try {
            /* Últimos N más recientes (orden desc + limit, luego asc para el cliente). Query ?limit= máx. 200. */
            $limit = (int) $request->query('limit', 60);
            $limit = max(1, min(200, $limit));

            $msgs = WhatsAppMessage::query()
                ->where('phone', $digits)
                ->with('senderUser')
                ->orderByDesc('id')
                ->limit($limit)
                ->get()
                ->sortBy('id')
                ->values();

            $conv = WhatsAppConversation::query()
                ->select($this->conversationColumnsForInbox())
                ->with('takeoverUser')
                ->where('phone', $digits)
                ->first();

            $clientName = null;
            foreach (User::query()->where('role', 'client')->whereNotNull('phone')->get(['name', 'phone']) as $u) {
                if (WhatsAppMessageLogger::normalizePhone($u->phone ?? '') === $digits) {
                    $clientName = $u->name;
                    break;
                }
            }

            $waFromThread = $this->waProfileNameFromLatestClientMessage([$digits]);

            $payload = [
                'conversation' => $conv ? [
                    'phone' => $conv->phone,
                    'human_takeover' => $conv->human_takeover,
                    'human_takeover_at' => $conv->human_takeover_at?->toIso8601String(),
                    'takeover_user_name' => $conv->takeoverUser?->name,
                    'state' => $conv->state,
                    'client_name' => $clientName,
                    'wa_contact_name' => $waFromThread[$digits] ?? null,
                ] : null,
                'messages' => $msgs->map(function ($m) {
                    return [
                        'id' => $m->id,
                        'sender_type' => $m->sender_type,
                        'message_type' => $m->message_type,
                        'body' => $m->body,
                        'meta' => $m->meta,
                        'created_at' => self::messageCreatedIso($m->created_at),
                        'staff_name' => $m->senderUser?->name,
                    ];
                })->values()->all(),
            ];

            return response()
                ->json($payload)
                ->header('Cache-Control', 'private, no-store, no-cache, must-revalidate')
                ->header('Pragma', 'no-cache');
        } catch (Throwable $e) {
            Log::error('WhatsAppInboxController::messages failed', [
                'phone' => $digits,
                'exception' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
            ]);

            return response()->json([
                'conversation' => null,
                'messages' => [],
                'message' => 'Error al cargar mensajes. Revisá storage/logs/laravel.log en el servidor.',
                'detail' => config('app.debug') ? $e->getMessage() : null,
            ], 500);
        }
    }

    public function storeTakeover(Request $request, string $phone): JsonResponse
    {
        if (! $this->inboxSchemaReady()) {
            return response()->json([
                'message' => 'Ejecutá php artisan migrate --force en el servidor (faltan tablas de conversaciones WhatsApp).',
            ], 503);
        }

        $digits = preg_replace('/\D/', '', $phone);
        if ($digits === '') {
            return response()->json(['message' => 'Teléfono inválido.'], 422);
        }

        $request->validate([
            'takeover' => 'required|boolean',
        ]);

        $conv = WhatsAppConversation::getOrCreate($digits);
        if ($request->boolean('takeover')) {
            $conv->enableHumanTakeover((int) $request->user()->id);
        } else {
            $conv->releaseHumanTakeover();
        }
        $conv->load('takeoverUser:id,name');

        return response()->json([
            'conversation' => [
                'phone' => $conv->phone,
                'human_takeover' => $conv->human_takeover,
                'human_takeover_at' => $conv->human_takeover_at?->toIso8601String(),
                'takeover_user_name' => $conv->takeoverUser?->name,
                'state' => $conv->state,
            ],
        ]);
    }

    public function sendMessage(Request $request, string $phone): JsonResponse
    {
        if (! $this->inboxSchemaReady()) {
            return response()->json([
                'message' => 'Ejecutá php artisan migrate --force en el servidor (faltan tablas de conversaciones WhatsApp).',
            ], 503);
        }

        $digits = preg_replace('/\D/', '', $phone);
        if ($digits === '') {
            return response()->json(['message' => 'Teléfono inválido.'], 422);
        }

        $validated = $request->validate([
            'body' => 'required|string|max:4096',
        ]);

        $conv = WhatsAppConversation::where('phone', $digits)->first();
        if (! $conv) {
            return response()->json(['message' => 'No hay conversación para este número.'], 404);
        }
        if (! $conv->human_takeover) {
            return response()->json([
                'message' => 'Activá el take over antes de enviar mensajes manuales.',
            ], 422);
        }
        if (! $this->whatsapp->isConfigured()) {
            return response()->json(['message' => 'WhatsApp no está configurado.'], 503);
        }

        $ok = $this->whatsapp->sendText($digits, $validated['body'], false);
        if (! $ok) {
            return response()->json([
                'message' => $this->whatsapp->getLastError() ?: 'No se pudo enviar el mensaje.',
            ], 422);
        }

        WhatsAppMessageLogger::outboundStaff($digits, $validated['body'], (int) $request->user()->id);

        return response()->json(['success' => true]);
    }
}
