<?php

namespace App\Http\Controllers;

use App\Models\Contact;
use App\Models\Conversation;
use App\Models\Message;
use App\Models\Setting;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use Netflie\WhatsAppCloudApi\WhatsAppCloudApi;
use Netflie\WhatsAppCloudApi\Message\Media\MediaID;

class InboxApiController extends Controller
{
    // ── Conversation & Message ─────────────────────────────────────────────

    /**
     * GET /inbox/api/conversations
     */
    public function conversations(Request $request)
    {
        $user   = Auth::user();
        $filter = $request->query('filter', 'all');
        $search = $request->query('search', '');

        $conversations = Conversation::where('user_id', $user->id)
            ->when($filter === 'new',    fn($q) => $q->where('status', 'new'))
            ->when($filter === 'open',   fn($q) => $q->where('status', 'open'))
            ->when($filter === 'closed', fn($q) => $q->where('status', 'closed'))
            ->when($search, fn($q) => $q->where(function ($q2) use ($search) {
                $q2->where('contact_name', 'like', "%{$search}%")
                   ->orWhere('contact_phone', 'like', "%{$search}%");
            }))
            ->orderByDesc('last_message_at')
            ->get()
            ->map(fn($c) => $this->formatConversation($c));

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

    /**
     * GET /inbox/api/conversations/{conversation}/messages
     */
    public function messages(Conversation $conversation)
    {
        $user = Auth::user();
        abort_if($conversation->user_id !== $user->id, 403);

        $conversation->update(['unread_count' => 0]);

        $messages = Message::where('conversation_id', $conversation->id)
            ->orderBy('created_at')
            ->get()
            ->map(fn($m) => $this->formatMessage($m));

        return response()->json([
            'conversation' => $this->formatConversation($conversation->fresh()),
            'messages'     => $messages,
        ]);
    }

    /**
     * POST /inbox/api/conversations/{conversation}/send
     * Send a plain text message.
     */
    public function send(Request $request, Conversation $conversation)
    {
        $user = Auth::user();
        abort_if($conversation->user_id !== $user->id, 403);

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

        if (!$user->access_token || !$user->phone_number_id) {
            return response()->json(['error' => 'WhatsApp not configured.'], 422);
        }

        try {
            $whatsapp = $this->makeClient($user);
            $whatsapp->sendTextMessage($conversation->contact_phone, $request->message);

            $message = Message::create([
                'conversation_id' => $conversation->id,
                'user_id'         => $user->id,
                'direction'       => 'outgoing',
                'type'            => 'text',
                'content'         => $request->message,
                'status'          => 'sent',
            ]);

            $conversation->update([
                'last_message'    => $request->message,
                'last_message_at' => now(),
                'status'          => 'open',
            ]);

            return response()->json([
                'message'      => $this->formatMessage($message),
                'conversation' => $this->formatConversation($conversation->fresh()),
            ]);

        } catch (\Throwable $e) {
            Log::error('Inbox send error', ['conv' => $conversation->id, 'error' => $e->getMessage()]);
            return response()->json(['error' => 'Send failed: ' . $e->getMessage()], 500);
        }
    }

    /**
     * POST /inbox/api/conversations/{conversation}/send-media
     * Upload a file to WhatsApp servers, send it, and save the message.
     */
    public function sendMedia(Request $request, Conversation $conversation)
    {
        $user = Auth::user();
        abort_if($conversation->user_id !== $user->id, 403);

        $request->validate([
            'file'    => ['required', 'file', 'max:20480'],
            'type'    => ['required', 'in:image,video,audio,document,sticker'],
            'caption' => ['nullable', 'string', 'max:1024'],
        ]);

        if (!$user->access_token || !$user->phone_number_id) {
            return response()->json(['error' => 'WhatsApp not configured.'], 422);
        }

        $file     = $request->file('file');
        $type     = $request->input('type');
        $caption  = $request->input('caption', '');

        try {
            $whatsapp = $this->makeClient($user);
            $phone    = $conversation->contact_phone;

            // 1. Upload to WhatsApp media servers
            $uploadRes = $whatsapp->uploadMedia($file->getRealPath());
            $body      = $uploadRes->decodedBody();
            $mediaId   = $body['id'] ?? null;

            if (!$mediaId) {
                return response()->json(['error' => 'Media upload to WhatsApp failed.'], 500);
            }

            // 2. Send the media message
            switch ($type) {
                case 'image':
                    $whatsapp->sendImage($phone, new MediaID($mediaId), $caption);
                    break;
                case 'video':
                    $whatsapp->sendVideo($phone, new MediaID($mediaId), $caption);
                    break;
                case 'audio':
                    $whatsapp->sendAudio($phone, new MediaID($mediaId));
                    break;
                case 'document':
                    $whatsapp->sendDocument($phone, new MediaID($mediaId), $file->getClientOriginalName(), $caption);
                    break;
                case 'sticker':
                    $whatsapp->sendSticker($phone, new MediaID($mediaId));
                    break;
            }

            // 3. Also store locally so the sender can see it in the chat
            $ext      = $file->getClientOriginalExtension() ?: $this->typeToExt($type);
            $filename = 'out_' . uniqid() . '.' . $ext;
            $path     = "inbox/{$user->id}/{$filename}";
            $storage  = Setting::get('file_storage', 'local');

            if ($storage === 's3' || $storage === 'spaces') {
                Storage::disk('s3')->put($path, file_get_contents($file->getRealPath()), 'public');
                $mediaUrl = Storage::disk('s3')->url($path);
            } else {
                Storage::disk('public')->put($path, file_get_contents($file->getRealPath()));
                $mediaUrl = asset('storage/' . $path);
            }

            $preview = match ($type) {
                'image'    => '📷 Image',
                'video'    => '🎥 Video',
                'audio'    => '🎵 Audio',
                'document' => '📄 ' . $file->getClientOriginalName(),
                'sticker'  => '🎭 Sticker',
                default    => "[{$type}]",
            };

            $message = Message::create([
                'conversation_id' => $conversation->id,
                'user_id'         => $user->id,
                'direction'       => 'outgoing',
                'type'            => $type,
                'content'         => $caption ?: null,
                'media_url'       => $mediaUrl,
                'media_filename'  => $file->getClientOriginalName(),
                'status'          => 'sent',
            ]);

            $conversation->update([
                'last_message'    => $preview,
                'last_message_at' => now(),
                'status'          => 'open',
            ]);

            return response()->json([
                'message'      => $this->formatMessage($message),
                'conversation' => $this->formatConversation($conversation->fresh()),
            ]);

        } catch (\Throwable $e) {
            Log::error('Media send error', ['conv' => $conversation->id, 'error' => $e->getMessage()]);
            return response()->json(['error' => 'Failed to send: ' . $e->getMessage()], 500);
        }
    }

    /**
     * POST /inbox/api/conversations/{conversation}/send-location
     */
    public function sendLocation(Request $request, Conversation $conversation)
    {
        $user = Auth::user();
        abort_if($conversation->user_id !== $user->id, 403);

        $request->validate([
            'latitude'  => ['required', 'numeric', 'between:-90,90'],
            'longitude' => ['required', 'numeric', 'between:-180,180'],
            'name'      => ['nullable', 'string', 'max:255'],
            'address'   => ['nullable', 'string', 'max:255'],
        ]);

        if (!$user->access_token || !$user->phone_number_id) {
            return response()->json(['error' => 'WhatsApp not configured.'], 422);
        }

        try {
            $whatsapp = $this->makeClient($user);
            $whatsapp->sendLocation(
                $conversation->contact_phone,
                (float) $request->longitude,
                (float) $request->latitude,
                $request->name ?? '',
                $request->address ?? ''
            );

            $name    = $request->name ?: sprintf('%.5f, %.5f', $request->latitude, $request->longitude);
            $content = "📍 {$name}";

            $message = Message::create([
                'conversation_id' => $conversation->id,
                'user_id'         => $user->id,
                'direction'       => 'outgoing',
                'type'            => 'location',
                'content'         => $content,
                'status'          => 'sent',
            ]);

            $conversation->update([
                'last_message'    => $content,
                'last_message_at' => now(),
                'status'          => 'open',
            ]);

            return response()->json([
                'message'      => $this->formatMessage($message),
                'conversation' => $this->formatConversation($conversation->fresh()),
            ]);

        } catch (\Throwable $e) {
            Log::error('Location send error', ['error' => $e->getMessage()]);
            return response()->json(['error' => 'Failed to send location: ' . $e->getMessage()], 500);
        }
    }

    /**
     * POST /inbox/api/conversations/{conversation}/mark-read
     * Send read receipts to WhatsApp for incoming messages.
     */
    public function markRead(Request $request, Conversation $conversation)
    {
        $user = Auth::user();
        abort_if($conversation->user_id !== $user->id, 403);

        $request->validate(['wa_message_id' => ['required', 'string']]);

        if ($user->access_token && $user->phone_number_id) {
            try {
                $this->makeClient($user)->markMessageAsRead($request->wa_message_id);
            } catch (\Throwable $e) {
                Log::warning('Mark read failed', ['wa_id' => $request->wa_message_id, 'err' => $e->getMessage()]);
            }
        }

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

    /**
     * POST /inbox/api/conversations/{conversation}/typing
     * Send a typing indicator (also implicitly marks last message as read).
     */
    public function sendTyping(Request $request, Conversation $conversation)
    {
        $user = Auth::user();
        abort_if($conversation->user_id !== $user->id, 403);

        $request->validate(['wa_message_id' => ['required', 'string']]);

        if ($user->access_token && $user->phone_number_id) {
            try {
                $this->makeClient($user)->sendTypingIndicator($request->wa_message_id);
            } catch (\Throwable $e) {
                Log::warning('Typing indicator failed', ['err' => $e->getMessage()]);
            }
        }

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

    /**
     * PATCH /inbox/api/conversations/{conversation}/status
     */
    public function updateStatus(Request $request, Conversation $conversation)
    {
        $user = Auth::user();
        abort_if($conversation->user_id !== $user->id, 403);

        $request->validate(['status' => ['required', 'in:new,open,closed']]);
        $conversation->update(['status' => $request->status]);

        return response()->json(['conversation' => $this->formatConversation($conversation->fresh())]);
    }

    /**
     * PATCH /inbox/api/conversations/{conversation}/label
     */
    public function updateLabel(Request $request, Conversation $conversation)
    {
        $user = Auth::user();
        abort_if($conversation->user_id !== $user->id, 403);

        $conversation->update(['label' => $request->label]);

        return response()->json(['conversation' => $this->formatConversation($conversation->fresh())]);
    }

    /**
     * GET /inbox/api/contacts
     */
    public function contacts(Request $request)
    {
        $user   = Auth::user();
        $search = $request->query('search', '');

        return response()->json(
            Contact::where('user_id', $user->id)
                ->when($search, fn($q) => $q->where(function ($q2) use ($search) {
                    $q2->where('name', 'like', "%{$search}%")->orWhere('phone', 'like', "%{$search}%");
                }))
                ->orderBy('name')
                ->get()
                ->map(fn($c) => [
                    'id'       => $c->id,
                    'name'     => $c->name,
                    'phone'    => $c->phone,
                    'email'    => $c->email,
                    'initials' => $c->initials(),
                ])
        );
    }

    // ── Private helpers ────────────────────────────────────────────────────

    private function makeClient($user): WhatsAppCloudApi
    {
        return new WhatsAppCloudApi([
            'from_phone_number_id' => $user->phone_number_id,
            'access_token'         => $user->access_token,
        ]);
    }

    private function formatConversation(Conversation $c): array
    {
        return [
            'id'                       => $c->id,
            'contact_phone'            => $c->contact_phone,
            'contact_name'             => $c->contact_name,
            'contact_id'               => $c->contact_id,
            'assigned_to'              => $c->assigned_to,
            'status'                   => $c->status,
            'label'                    => $c->label,
            'last_message'             => $c->last_message,
            'last_message_at'          => $c->last_message_at?->toIso8601String(),
            'customer_last_message_at' => $c->customer_last_message_at?->toIso8601String(),
            'unread_count'             => $c->unread_count,
            'hours_left'               => $c->hoursLeftToReply(),
            'initials'                 => $c->initials(),
        ];
    }

    private function formatMessage(Message $m): array
    {
        return [
            'id'              => $m->id,
            'conversation_id' => $m->conversation_id,
            'direction'       => $m->direction,
            'type'            => $m->type,
            'content'         => $m->content,
            'media_url'       => $m->media_url,
            'media_filename'  => $m->media_filename,
            'wa_message_id'   => $m->wa_message_id,
            'status'          => $m->status,
            'created_at'      => $m->created_at->toIso8601String(),
        ];
    }

    private function typeToExt(string $type): string
    {
        return match ($type) {
            'image'    => 'jpg',
            'video'    => 'mp4',
            'audio'    => 'ogg',
            'document' => 'pdf',
            'sticker'  => 'webp',
            default    => 'bin',
        };
    }
}
