<?php
namespace App\Controllers;

use App\Core\Controller;
use App\Core\Request;
use App\Core\Response;
use App\Config\WhatsAppConfig;
use App\Models\Contact;
use App\Models\Conversation;
use App\Models\Message;
use App\Models\Setting;
use App\Services\WhatsAppService;
use App\Services\AutomationService;

class WebhookController extends Controller {

    /**
     * Webhook Entry Point (Supports QR Gateway & Meta Cloud API)
     */
    public function handle(): void {
        $method = Request::getMethod();

        // 1. Meta Webhook Verification Challenge (GET)
        if ($method === 'GET') {
            $mode = Request::get('hub_mode') ?? Request::get('hub.mode');
            $token = Request::get('hub_verify_token') ?? Request::get('hub.verify_token');
            $challenge = Request::get('hub_challenge') ?? Request::get('hub.challenge');

            $expectedToken = Setting::getVal('whatsapp_verify_token') ?: WhatsAppConfig::getVerifyToken();

            if ($mode === 'subscribe' && $token === $expectedToken) {
                http_response_code(200);
                echo $challenge;
                exit;
            }

            // Also support simple ping verification for QR gateways
            http_response_code(200);
            echo "Webhook Endpoint Active (WhatsApp CRM)";
            exit;
        }

        // 2. Incoming Event / Message Payload (POST)
        if ($method === 'POST') {
            $rawBody = Request::rawBody();
            $payload = json_decode($rawBody, true) ?: Request::post();

            if (!empty($payload)) {
                // Check if QR Code Gateway (UltraMsg / Universal) format
                if (isset($payload['event_type']) || isset($payload['data'])) {
                    $this->processQrGatewayPayload($payload);
                } 
                // Meta Cloud API format
                elseif (isset($payload['entry'])) {
                    $this->processMetaPayload($payload);
                }
                // Fallback direct format
                elseif (isset($payload['from']) && (isset($payload['body']) || isset($payload['text']))) {
                    $msgText = $payload['body'] ?? ($payload['text'] ?? '');
                    $profileName = $payload['name'] ?? ($payload['pushname'] ?? 'WhatsApp User');
                    $this->handleInboundMessage([
                        'from' => $payload['from'],
                        'id'   => $payload['id'] ?? ('in_' . uniqid()),
                        'type' => $payload['type'] ?? 'text',
                        'text' => ['body' => $msgText]
                    ], $profileName);
                }
            }

            http_response_code(200);
            echo json_encode(['status' => 'success', 'message' => 'EVENT_RECEIVED']);
            exit;
        }
    }

    /**
     * Process QR Gateway (UltraMsg / GreenAPI) Webhook Events
     */
    protected function processQrGatewayPayload(array $payload): void {
        $eventType = $payload['event_type'] ?? '';
        $data = $payload['data'] ?? [];

        // Ignore messages sent by ourselves
        if (!empty($data['fromMe']) && ($data['fromMe'] === true || $data['fromMe'] === 'true' || $data['fromMe'] === 1)) {
            return;
        }

        // 1. Message Received
        if ($eventType === 'message_received' || empty($eventType)) {
            $rawFrom = $data['from'] ?? '';
            // Remove WhatsApp suffix @c.us or @s.whatsapp.net
            $phone = preg_replace('/[^0-9]/', '', explode('@', $rawFrom)[0]);
            if (empty($phone)) return;

            $profileName = $data['pushname'] ?? ($data['author'] ?? 'WhatsApp User');
            $msgType = $data['type'] ?? 'text';
            if ($msgType === 'chat') $msgType = 'text';

            $msgPayload = [
                'from' => $phone,
                'id'   => $data['id'] ?? ('qr_' . uniqid()),
                'type' => $msgType
            ];

            if ($msgType === 'text') {
                $msgPayload['text'] = ['body' => $data['body'] ?? ''];
            } elseif ($msgType === 'image') {
                $msgPayload['image'] = ['link' => $data['media'] ?? null, 'caption' => $data['caption'] ?? ($data['body'] ?? '')];
            } elseif ($msgType === 'document') {
                $msgPayload['document'] = ['link' => $data['media'] ?? null, 'filename' => $data['filename'] ?? 'document'];
            } elseif ($msgType === 'audio' || $msgType === 'ptt') {
                $msgPayload['audio'] = ['link' => $data['media'] ?? null];
                $msgPayload['type'] = 'audio';
            }

            $this->handleInboundMessage($msgPayload, $profileName);
        }

        // 2. Message Status Update (delivered / viewed)
        if ($eventType === 'message_status' || $eventType === 'ack') {
            $metaId = $data['id'] ?? null;
            $rawStatus = strtolower($data['status'] ?? ($data['ack'] ?? ''));

            $status = 'sent';
            if (in_array($rawStatus, ['delivered', 'read', 'viewed', 'sent', 'failed'])) {
                $status = ($rawStatus === 'viewed') ? 'read' : $rawStatus;
            }

            if ($metaId) {
                Message::updateStatusByMetaId($metaId, $status);
            }
        }
    }

    /**
     * Parse and process Meta Cloud API webhook events
     */
    protected function processMetaPayload(array $payload): void {
        $entries = $payload['entry'] ?? [];

        foreach ($entries as $entry) {
            $changes = $entry['changes'] ?? [];
            foreach ($changes as $change) {
                $value = $change['value'] ?? [];

                // Status updates
                if (!empty($value['statuses'])) {
                    foreach ($value['statuses'] as $statusUpdate) {
                        $metaMsgId = $statusUpdate['id'] ?? null;
                        $status = $statusUpdate['status'] ?? null;
                        if ($metaMsgId && $status) {
                            Message::updateStatusByMetaId($metaMsgId, $status);
                        }
                    }
                }

                // Inbound messages
                if (!empty($value['messages'])) {
                    $senderProfileName = $value['contacts'][0]['profile']['name'] ?? 'WhatsApp User';

                    foreach ($value['messages'] as $incoming) {
                        $this->handleInboundMessage($incoming, $senderProfileName, $value);
                    }
                }
            }
        }
    }

    /**
     * Handle single incoming WhatsApp message
     */
    public function handleInboundMessage(array $msg, string $profileName, array $fullContext = []): void {
        $fromWaId = $msg['from'] ?? null;
        $fromWaId = preg_replace('/[^0-9]/', '', $fromWaId);
        $metaMsgId = $msg['id'] ?? ('in_' . uniqid());
        $msgType = $msg['type'] ?? 'text';

        if (empty($fromWaId)) {
            return;
        }

        // Avoid duplicate message processing
        $existing = Message::firstWhere('meta_message_id', $metaMsgId);
        if ($existing) {
            return;
        }

        // 1. Get or Create Contact
        $existingContact = Contact::findByWhatsAppId($fromWaId);
        $isNewContact = ($existingContact === null);

        $contact = Contact::getOrCreateByWhatsAppId($fromWaId, $profileName);
        if (!$isNewContact && $contact['name'] === 'WhatsApp User' && !empty($profileName)) {
            Contact::update((int)$contact['id'], ['name' => $profileName]);
            $contact['name'] = $profileName;
        }

        // 2. Get or Create Conversation
        $conversation = Conversation::getOrCreateForContact((int)$contact['id'], $contact['assigned_to'] ?? null);

        // 3. Extract Content
        $contentText = '';
        $mediaUrl = null;
        $mediaFilename = null;

        switch ($msgType) {
            case 'text':
                $contentText = $msg['text']['body'] ?? ($msg['body'] ?? '');
                break;

            case 'image':
                $contentText = $msg['image']['caption'] ?? '[Photo]';
                $mediaUrl = $msg['image']['link'] ?? null;
                break;

            case 'audio':
                $contentText = '[Voice / Audio Message]';
                $mediaUrl = $msg['audio']['link'] ?? null;
                break;

            case 'document':
                $contentText = $msg['document']['caption'] ?? ($msg['document']['filename'] ?? '[Document]');
                $mediaUrl = $msg['document']['link'] ?? null;
                $mediaFilename = $msg['document']['filename'] ?? null;
                break;

            case 'video':
                $contentText = $msg['video']['caption'] ?? '[Video]';
                $mediaUrl = $msg['video']['link'] ?? null;
                break;

            case 'interactive':
                if (isset($msg['interactive']['button_reply'])) {
                    $contentText = $msg['interactive']['button_reply']['title'] ?? '[Button Reply]';
                } elseif (isset($msg['interactive']['list_reply'])) {
                    $contentText = $msg['interactive']['list_reply']['title'] ?? '[List Selection]';
                }
                break;

            default:
                $contentText = $msg['body'] ?? "[Received {$msgType} message]";
                break;
        }

        // 4. Save Inbound Message
        Message::create([
            'conversation_id' => (int)$conversation['id'],
            'contact_id'      => (int)$contact['id'],
            'user_id'         => null,
            'direction'       => 'inbound',
            'message_type'    => $msgType,
            'content'         => $contentText,
            'media_url'       => $mediaUrl,
            'media_filename'  => $mediaFilename,
            'meta_message_id' => $metaMsgId,
            'status'          => 'delivered',
            'raw_payload'     => json_encode($msg),
            'created_at'      => date('Y-m-d H:i:s')
        ]);

        // 5. Update Conversation unread count and preview
        Conversation::updateLastMessage((int)$conversation['id'], $contentText, 'inbound');

        // 6. Trigger Automations / Chatbot
        AutomationService::processIncoming($contact, $conversation, $contentText, $isNewContact);
    }
}
