<?php
require_once __DIR__ . '/../Core.php';
require_once __DIR__ . '/../models/Message.php';
require_once __DIR__ . '/../models/Contact.php';
require_once __DIR__ . '/../models/Suppression.php';
require_once __DIR__ . '/../services.php';

class WebhookController extends Controller
{
    private function verifyTwilio(): void
    {
        $service = new TwilioService();
        $signature = $_SERVER['HTTP_X_TWILIO_SIGNATURE'] ?? null;
        if (!$service->validateRequest(get_current_request_url(), $_POST, $signature)) {
            http_response_code(403);
            exit('Invalid Twilio signature.');
        }
    }

    public function twilio(): void
    {
        $this->verifyTwilio();
        $from = $_POST['From'] ?? '';
        $to = $_POST['To'] ?? '';
        $body = $_POST['Body'] ?? '';
        $sid = $_POST['MessageSid'] ?? null;
        $mediaUrl = !empty($_POST['MediaUrl0']) ? $_POST['MediaUrl0'] : null;
        $contactModel = new Contact();
        $contact = $contactModel->findByAddress('sms', $from);
        if (in_array(strtoupper(trim($body)), ['STOP', 'STOPALL', 'UNSUBSCRIBE', 'CANCEL', 'END', 'QUIT'], true)) {
            $contactModel->setUnsubscribed('sms', $from, true);
            (new Suppression())->add('sms', $from, 'unsubscribe', $contact['id'] ?? null, null);
        }
        $messageId = (new Message())->create([
            'contact_id' => $contact['id'] ?? null,
            'channel' => 'sms',
            'direction' => 'inbound',
            'body' => $body,
            'from_address' => $from,
            'to_address' => $to,
            'status' => 'received',
            'external_id' => $sid,
            'media_url' => $mediaUrl,
            'metadata_json' => json_encode($_POST),
        ]);
        audit_log('webhook.twilio.inbound', 'message', $messageId, ['from' => $from]);
        header('Content-Type: text/xml');
        echo '<?xml version="1.0" encoding="UTF-8"?><Response></Response>';
        exit;
    }

    public function twilioStatus(): void
    {
        $this->verifyTwilio();
        $sid = $_POST['MessageSid'] ?? '';
        $status = $_POST['MessageStatus'] ?? 'updated';
        if ($sid) {
            $messageModel = new Message();
            $messageModel->updateStatusByExternalId($sid, $status, json_encode($_POST));
            if (in_array($status, ['failed', 'undelivered'], true)) {
                $message = Database::connection()->prepare('SELECT * FROM messages WHERE external_id = ? LIMIT 1');
                $message->execute([$sid]);
                $row = $message->fetch();
                if ($row && !empty($row['to_address'])) {
                    (new Suppression())->add('sms', $row['to_address'], 'delivery_failure', $row['contact_id'] ?: null, $row['id']);
                }
            }
        }
        http_response_code(204);
        exit;
    }

    public function emailEvent(): void
    {
        $messageId = (int)($_REQUEST['message_id'] ?? 0);
        $eventType = strtolower(trim((string)($_REQUEST['event'] ?? '')));
        $reason = trim((string)($_REQUEST['reason'] ?? 'provider_event'));
        if ($messageId && in_array($eventType, ['bounce', 'complaint', 'blocked'], true)) {
            $messageModel = new Message();
            $message = $messageModel->find($messageId);
            if ($message) {
                $messageModel->updateStatus($messageId, 'bounced', json_encode($_REQUEST));
                $messageModel->addEvent($messageId, $eventType, $reason, json_encode($_REQUEST));
                if (!empty($message['to_address'])) {
                    (new Suppression())->add('email', $message['to_address'], $eventType . ':' . $reason, $message['contact_id'] ?: null, $messageId);
                    (new Contact())->setUnsubscribed('email', $message['to_address'], true);
                }
                audit_log('webhook.email_event', 'message', $messageId, ['event' => $eventType, 'reason' => $reason]);
            }
        }
        http_response_code(204);
        exit;
    }

    public function trackOpen(): void
    {
        $messageId = (int)($_GET['message_id'] ?? 0);
        if ($messageId) {
            (new Message())->addEvent($messageId, 'open', null, json_encode(['ip' => $_SERVER['REMOTE_ADDR'] ?? null, 'ua' => $_SERVER['HTTP_USER_AGENT'] ?? null]));
        }
        header('Content-Type: image/gif');
        echo base64_decode('R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==');
        exit;
    }

    public function trackClick(): void
    {
        $messageId = (int)($_GET['message_id'] ?? 0);
        $url = $_GET['url'] ?? '';
        if ($messageId) {
            (new Message())->addEvent($messageId, 'click', $url, json_encode(['ip' => $_SERVER['REMOTE_ADDR'] ?? null]));
        }
        redirect_url($url ?: '/');
    }
}
