<?php
/**
 * whatsapp_alerts.php
 * Place: /rooms/modules/reports/whatsapp_alerts.php
 *
 * WhatsApp notification helper for PMS.
 *
 * Supports:
 * 1. WhatsApp Cloud API
 * 2. Generic webhook provider fallback
 * 3. Safe test mode
 *
 * IMPORTANT:
 * - This file does not expose secrets on screen.
 * - Store credentials in a table called settings if available:
 *
 * setting_key                  setting_value
 * whatsapp_provider            cloud
 * whatsapp_cloud_token         YOUR_META_ACCESS_TOKEN
 * whatsapp_phone_number_id     YOUR_PHONE_NUMBER_ID
 * whatsapp_default_country     263
 * whatsapp_alert_numbers       263771234567,263772345678
 *
 * Browser test:
 * /rooms/modules/reports/whatsapp_alerts.php?test=1&to=263771234567&message=Hello
 */

if (!function_exists('wa_table_exists')) {
    function wa_table_exists(PDO $pdo, string $tableName): bool
    {
        $stmt = $pdo->prepare("
            SELECT COUNT(*)
            FROM information_schema.tables
            WHERE table_schema = DATABASE()
              AND table_name = :table_name
        ");
        $stmt->execute([':table_name' => $tableName]);
        return (int)$stmt->fetchColumn() > 0;
    }
}

if (!function_exists('wa_column_exists')) {
    function wa_column_exists(PDO $pdo, string $tableName, string $columnName): bool
    {
        $stmt = $pdo->prepare("
            SELECT COUNT(*)
            FROM information_schema.columns
            WHERE table_schema = DATABASE()
              AND table_name = :table_name
              AND column_name = :column_name
        ");
        $stmt->execute([
            ':table_name' => $tableName,
            ':column_name' => $columnName,
        ]);
        return (int)$stmt->fetchColumn() > 0;
    }
}

if (!function_exists('wa_setting')) {
    function wa_setting(PDO $pdo, string $key, $default = '')
    {
        if (!wa_table_exists($pdo, 'settings')) {
            return $default;
        }

        $keyColumns = ['setting_key', 'name', 'setting_name'];
        $valueColumns = ['setting_value', 'value', 'setting'];

        foreach ($keyColumns as $keyCol) {
            if (!wa_column_exists($pdo, 'settings', $keyCol)) {
                continue;
            }

            foreach ($valueColumns as $valueCol) {
                if (!wa_column_exists($pdo, 'settings', $valueCol)) {
                    continue;
                }

                try {
                    $stmt = $pdo->prepare("SELECT $valueCol FROM settings WHERE $keyCol = :k LIMIT 1");
                    $stmt->execute([':k' => $key]);
                    $value = $stmt->fetchColumn();

                    if ($value !== false && trim((string)$value) !== '') {
                        return $value;
                    }
                } catch (Throwable $e) {
                    continue;
                }
            }
        }

        return $default;
    }
}

if (!function_exists('wa_normalize_phone')) {
    function wa_normalize_phone(string $phone, string $defaultCountryCode = '263'): string
    {
        $phone = trim($phone);
        $phone = preg_replace('/[^0-9+]/', '', $phone);

        if ($phone === '') {
            return '';
        }

        if (str_starts_with($phone, '+')) {
            return preg_replace('/[^0-9]/', '', $phone);
        }

        if (str_starts_with($phone, '00')) {
            return substr($phone, 2);
        }

        if (str_starts_with($phone, '0')) {
            return $defaultCountryCode . substr($phone, 1);
        }

        return $phone;
    }
}

if (!function_exists('wa_json_response')) {
    function wa_json_response(array $payload): void
    {
        if (PHP_SAPI === 'cli') {
            echo json_encode($payload, JSON_PRETTY_PRINT) . PHP_EOL;
            return;
        }

        header('Content-Type: application/json; charset=utf-8');
        echo json_encode($payload, JSON_PRETTY_PRINT);
    }
}

if (!function_exists('wa_create_log_table')) {
    function wa_create_log_table(PDO $pdo): void
    {
        $pdo->exec("
            CREATE TABLE IF NOT EXISTS whatsapp_send_log (
                id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
                recipient_phone VARCHAR(30) NOT NULL,
                message_type VARCHAR(60) NOT NULL DEFAULT 'general',
                message_body TEXT NOT NULL,
                provider VARCHAR(50) NOT NULL DEFAULT 'cloud',
                provider_response TEXT NULL,
                status VARCHAR(30) NOT NULL DEFAULT 'pending',
                related_table VARCHAR(80) NULL,
                related_id INT UNSIGNED NULL,
                sent_at DATETIME NULL,
                created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
                INDEX idx_whatsapp_phone (recipient_phone),
                INDEX idx_whatsapp_status (status),
                INDEX idx_whatsapp_related (related_table, related_id)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
        ");
    }
}

if (!function_exists('wa_http_post_json')) {
    function wa_http_post_json(string $url, array $payload, array $headers = [], int $timeout = 25): array
    {
        $ch = curl_init($url);

        $finalHeaders = array_merge([
            'Content-Type: application/json',
        ], $headers);

        curl_setopt_array($ch, [
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => json_encode($payload),
            CURLOPT_HTTPHEADER => $finalHeaders,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => $timeout,
        ]);

        $body = curl_exec($ch);
        $error = curl_error($ch);
        $status = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);

        curl_close($ch);

        return [
            'ok' => $error === '' && $status >= 200 && $status < 300,
            'status' => $status,
            'body' => (string)$body,
            'error' => $error,
        ];
    }
}

if (!function_exists('wa_send_cloud_api')) {
    function wa_send_cloud_api(PDO $pdo, string $to, string $message): array
    {
        $token = (string)wa_setting($pdo, 'whatsapp_cloud_token', '');
        $phoneNumberId = (string)wa_setting($pdo, 'whatsapp_phone_number_id', '');

        if ($token === '' || $phoneNumberId === '') {
            return [
                'ok' => false,
                'error' => 'WhatsApp Cloud API credentials are missing. Add whatsapp_cloud_token and whatsapp_phone_number_id to settings.',
            ];
        }

        $url = 'https://graph.facebook.com/v19.0/' . rawurlencode($phoneNumberId) . '/messages';

        $payload = [
            'messaging_product' => 'whatsapp',
            'recipient_type' => 'individual',
            'to' => $to,
            'type' => 'text',
            'text' => [
                'preview_url' => false,
                'body' => $message,
            ],
        ];

        $response = wa_http_post_json($url, $payload, [
            'Authorization: Bearer ' . $token,
        ]);

        return [
            'ok' => $response['ok'],
            'provider' => 'cloud',
            'status' => $response['status'],
            'response' => $response['body'],
            'error' => $response['error'],
        ];
    }
}

if (!function_exists('wa_send_webhook')) {
    function wa_send_webhook(PDO $pdo, string $to, string $message): array
    {
        $url = (string)wa_setting($pdo, 'whatsapp_webhook_url', '');
        $token = (string)wa_setting($pdo, 'whatsapp_webhook_token', '');

        if ($url === '') {
            return [
                'ok' => false,
                'error' => 'Webhook URL missing. Add whatsapp_webhook_url to settings.',
            ];
        }

        $payload = [
            'to' => $to,
            'message' => $message,
        ];

        $headers = [];
        if ($token !== '') {
            $headers[] = 'Authorization: Bearer ' . $token;
        }

        $response = wa_http_post_json($url, $payload, $headers);

        return [
            'ok' => $response['ok'],
            'provider' => 'webhook',
            'status' => $response['status'],
            'response' => $response['body'],
            'error' => $response['error'],
        ];
    }
}

if (!function_exists('wa_send_message')) {
    function wa_send_message(PDO $pdo, string $to, string $message, array $meta = []): array
    {
        wa_create_log_table($pdo);

        $defaultCountry = (string)wa_setting($pdo, 'whatsapp_default_country', '263');
        $to = wa_normalize_phone($to, $defaultCountry);

        if ($to === '') {
            return [
                'ok' => false,
                'error' => 'Invalid WhatsApp number.',
            ];
        }

        $message = trim($message);
        if ($message === '') {
            return [
                'ok' => false,
                'error' => 'Message body cannot be blank.',
            ];
        }

        $provider = strtolower((string)wa_setting($pdo, 'whatsapp_provider', 'cloud'));

        if (!in_array($provider, ['cloud', 'webhook'], true)) {
            $provider = 'cloud';
        }

        $stmt = $pdo->prepare("
            INSERT INTO whatsapp_send_log
            (recipient_phone, message_type, message_body, provider, status, related_table, related_id)
            VALUES
            (:recipient_phone, :message_type, :message_body, :provider, 'pending', :related_table, :related_id)
        ");
        $stmt->execute([
            ':recipient_phone' => $to,
            ':message_type' => (string)($meta['message_type'] ?? 'general'),
            ':message_body' => $message,
            ':provider' => $provider,
            ':related_table' => $meta['related_table'] ?? null,
            ':related_id' => isset($meta['related_id']) ? (int)$meta['related_id'] : null,
        ]);

        $logId = (int)$pdo->lastInsertId();

        $result = $provider === 'webhook'
            ? wa_send_webhook($pdo, $to, $message)
            : wa_send_cloud_api($pdo, $to, $message);

        $stmt = $pdo->prepare("
            UPDATE whatsapp_send_log
            SET
                status = :status,
                provider_response = :provider_response,
                sent_at = CASE WHEN :sent_ok = 1 THEN NOW() ELSE sent_at END
            WHERE id = :id
        ");
        $stmt->execute([
            ':status' => !empty($result['ok']) ? 'sent' : 'failed',
            ':provider_response' => json_encode($result),
            ':sent_ok' => !empty($result['ok']) ? 1 : 0,
            ':id' => $logId,
        ]);

        $result['log_id'] = $logId;
        $result['to'] = $to;

        return $result;
    }
}

if (!function_exists('wa_alert_numbers')) {
    function wa_alert_numbers(PDO $pdo): array
    {
        $raw = (string)wa_setting($pdo, 'whatsapp_alert_numbers', '');
        if ($raw === '') {
            return [];
        }

        $numbers = preg_split('/[,;]+/', $raw);
        $clean = [];
        $defaultCountry = (string)wa_setting($pdo, 'whatsapp_default_country', '263');

        foreach ($numbers as $number) {
            $number = wa_normalize_phone((string)$number, $defaultCountry);
            if ($number !== '') {
                $clean[] = $number;
            }
        }

        return array_values(array_unique($clean));
    }
}

if (!function_exists('wa_send_to_alert_group')) {
    function wa_send_to_alert_group(PDO $pdo, string $message, array $meta = []): array
    {
        $numbers = wa_alert_numbers($pdo);
        $results = [];

        foreach ($numbers as $number) {
            $results[] = wa_send_message($pdo, $number, $message, $meta);
        }

        return $results;
    }
}

if (!function_exists('wa_booking_confirmation_message')) {
    function wa_booking_confirmation_message(array $booking): string
    {
        $guest = trim((string)($booking['guest_name'] ?? 'Guest'));
        $orderNo = (string)($booking['order_no'] ?? ($booking['id'] ?? ''));
        $checkIn = (string)($booking['check_in'] ?? '');
        $checkOut = (string)($booking['check_out'] ?? '');
        $property = (string)($booking['property_name'] ?? '');

        return "Hello {$guest}, your booking {$orderNo} is confirmed.\n\n"
            . "Property: {$property}\n"
            . "Check-in: {$checkIn}\n"
            . "Check-out: {$checkOut}\n\n"
            . "Thank you.";
    }
}

if (!function_exists('wa_payment_reminder_message')) {
    function wa_payment_reminder_message(array $booking): string
    {
        $guest = trim((string)($booking['guest_name'] ?? 'Guest'));
        $orderNo = (string)($booking['order_no'] ?? ($booking['id'] ?? ''));
        $balance = number_format((float)($booking['balance'] ?? 0), 2);

        return "Hello {$guest}, this is a friendly payment reminder for booking {$orderNo}.\n\n"
            . "Outstanding balance: {$balance}\n\n"
            . "Please contact reservations if you need assistance.";
    }
}

if (!function_exists('wa_forecast_alert_message')) {
    function wa_forecast_alert_message(array $forecastAlerts): string
    {
        $critical = $forecastAlerts['critical'] ?? [];
        $warning = $forecastAlerts['warning'] ?? [];
        $all = array_merge($critical, $warning);

        if (!$all) {
            return "PMS Forecast Alerts\n\nNo forecast alerts for the next 14 days.";
        }

        $lines = [];
        $lines[] = "⚠️ PMS Forecast Alerts";
        $lines[] = date('Y-m-d');
        $lines[] = "";

        foreach (array_slice($all, 0, 12) as $alert) {
            $lines[] = "• " . ($alert['date'] ?? '') . " - " . ($alert['title'] ?? 'Alert');
            $lines[] = "  " . ($alert['message'] ?? '');
            $lines[] = "  Occupancy: " . number_format((float)($alert['occupancy_percent'] ?? 0), 2) . "% | Rooms left: " . (int)($alert['rooms_left'] ?? 0);
        }

        return implode("\n", $lines);
    }
}

/**
 * Optional direct browser/CLI test runner.
 * It only runs if this file is accessed directly.
 */
if (basename((string)($_SERVER['SCRIPT_FILENAME'] ?? '')) === basename(__FILE__)) {
    require_once __DIR__ . '/../../includes/bootstrap.php';

    $payload = [
        'ok' => false,
        'message' => 'No action.',
    ];

    try {
        $test = isset($_GET['test']) || (PHP_SAPI === 'cli' && in_array('--test', $argv ?? [], true));

        if (!$test) {
            $payload['message'] = 'Use ?test=1&to=263771234567&message=Hello to test.';
            wa_json_response($payload);
            exit;
        }

        $to = (string)($_GET['to'] ?? '');
        $message = (string)($_GET['message'] ?? 'Hello from PMS WhatsApp alerts.');

        if (PHP_SAPI === 'cli') {
            foreach (($argv ?? []) as $arg) {
                if (str_starts_with($arg, '--to=')) {
                    $to = substr($arg, 5);
                }
                if (str_starts_with($arg, '--message=')) {
                    $message = substr($arg, 10);
                }
            }
        }

        $result = wa_send_message($pdo, $to, $message, [
            'message_type' => 'test',
        ]);

        $payload = $result;
    } catch (Throwable $e) {
        http_response_code(500);
        $payload = [
            'ok' => false,
            'error' => $e->getMessage(),
        ];
    }

    wa_json_response($payload);
}
