<?php
declare(strict_types=1);

namespace App\Modules\Notifications\Services;

use App\Core\App;
use App\Core\Logger;
use App\Modules\Notifications\Models\SmsLog;
use App\Modules\Notifications\Models\SmsTemplate;
use App\Modules\Notifications\Models\NotificationQueue;

final class SmsService
{
    public static function send(string $phone, string $message, ?int $memberId = null, ?int $templateId = null): array
    {
        $employee = App::getInstance()->currentEmployee();
        $smsConfig = config('sms', []);
        $enabled = $smsConfig['enabled'] ?? false;

        $logId = SmsLog::create([
            'member_id'    => $memberId,
            'phone_number' => $phone,
            'template_id'  => $templateId,
            'message_text' => $message,
            'message_type' => 'single',
            'status'       => 'queued',
            'sent_by'      => $employee ? (int) $employee->id : null,
            'created_at'   => date('Y-m-d H:i:s'),
        ]);

        if (!$enabled || empty($smsConfig['api_key'])) {
            // SMS not configured — mark as sent for dev/testing
            $db = App::getInstance()->db();
            $db->update('sms_log', [
                'status'  => 'sent',
                'sent_at' => date('Y-m-d H:i:s'),
                'provider_response' => 'SMS_DISABLED_DEV_MODE',
            ], '`id` = ?', [$logId]);

            Logger::info("SMS (dev mode): {$phone} — {$message}");
            return ['success' => true, 'log_id' => $logId, 'dev_mode' => true];
        }

        // Real SMS sending via HTTP API
        try {
            $response = self::callProvider($phone, $message, $smsConfig);
            $db = App::getInstance()->db();
            $db->update('sms_log', [
                'status'              => 'sent',
                'sent_at'             => date('Y-m-d H:i:s'),
                'provider_message_id' => $response['message_id'] ?? null,
                'provider_response'   => json_encode($response),
                'cost'                => $response['cost'] ?? null,
            ], '`id` = ?', [$logId]);

            return ['success' => true, 'log_id' => $logId];
        } catch (\Throwable $e) {
            $db = App::getInstance()->db();
            $db->update('sms_log', [
                'status'         => 'failed',
                'failed_at'      => date('Y-m-d H:i:s'),
                'failure_reason' => $e->getMessage(),
                'retry_count'    => 1,
            ], '`id` = ?', [$logId]);

            Logger::error("SMS send failed: {$phone} — {$e->getMessage()}");
            return ['success' => false, 'error' => $e->getMessage(), 'log_id' => $logId];
        }
    }

    public static function queue(string $phone, string $message, ?int $memberId = null, ?int $templateId = null): int
    {
        return NotificationQueue::add([
            'type'          => 'sms',
            'recipient_type'=> 'member',
            'recipient_id'  => $memberId ?? 0,
            'template_id'   => $templateId,
            'message'       => $message,
            'data_json'     => json_encode(['phone' => $phone]),
            'priority'      => 0,
        ]);
    }

    public static function sendFromTemplate(string $templateCode, string $phone, array $variables, ?int $memberId = null): array
    {
        $template = SmsTemplate::findByCode($templateCode);
        if (!$template) {
            return ['success' => false, 'error' => "Template not found: {$templateCode}"];
        }

        $message = SmsTemplate::renderMessage($template['message_template_ar'], $variables);
        return self::send($phone, $message, $memberId, (int) $template['id']);
    }

    public static function processQueue(int $batchSize = 50): array
    {
        $pending = NotificationQueue::getPending($batchSize);
        $results = ['sent' => 0, 'failed' => 0];

        foreach ($pending as $item) {
            $data = json_decode($item['data_json'] ?? '{}', true) ?? [];
            $phone = $data['phone'] ?? '';
            if ($phone === '') {
                NotificationQueue::markFailed((int) $item['id']);
                $results['failed']++;
                continue;
            }

            $result = self::send($phone, $item['message'], (int) $item['recipient_id'] ?: null, $item['template_id'] ? (int) $item['template_id'] : null);
            if ($result['success']) {
                NotificationQueue::markProcessed((int) $item['id']);
                $results['sent']++;
            } else {
                NotificationQueue::markFailed((int) $item['id']);
                $results['failed']++;
            }
        }

        return $results;
    }

    private static function callProvider(string $phone, string $message, array $config): array
    {
        $url = $config['api_url'] ?? '';
        $apiKey = $config['api_key'] ?? '';
        $senderId = $config['sender_id'] ?? 'THECLUB';

        if ($url === '' || $apiKey === '') {
            throw new \RuntimeException('SMS provider not configured');
        }

        $postData = http_build_query([
            'api_key'   => $apiKey,
            'to'        => $phone,
            'message'   => $message,
            'sender_id' => $senderId,
        ]);

        $ctx = stream_context_create([
            'http' => [
                'method'  => 'POST',
                'header'  => "Content-Type: application/x-www-form-urlencoded\r\n",
                'content' => $postData,
                'timeout' => 30,
            ],
        ]);

        $response = @file_get_contents($url, false, $ctx);
        if ($response === false) {
            throw new \RuntimeException('Failed to connect to SMS provider');
        }

        $decoded = json_decode($response, true);
        if (!$decoded) {
            return ['raw' => $response, 'message_id' => null, 'cost' => null];
        }

        return $decoded;
    }
}