<?php

namespace App\Services;

use App\Models\SystemSettingModel;
use App\Models\OrderItemModel;
use Config\Services;

class NotificationService
{
    private const WHATSAPP_INTERVAL_SECONDS = 30;
    private const WHATSAPP_LAST_SENT_CACHE_KEY = 'fonnte_last_invoice_sent_at';
    private array $errors = [];

    /**
     * Kirim notifikasi invoice hanya melalui WhatsApp.
     * Kegagalan pengiriman tidak membatalkan transaksi atau pembuatan invoice.
     */
    public function sendOrderNotifications(array $order, ?array $invoice = null): array
    {
        $this->errors = [];

        return [
            'whatsapp' => $this->sendWhatsApp($order, $invoice),
            'errors' => $this->errors,
        ];
    }

    /**
     * Kirim WhatsApp Text
     */
    public function sendWhatsApp(array $order, ?array $invoice = null): bool
    {
        $apiKey = env('fonnte.apiKey', null);
        if (empty($apiKey)) {
            $setting = (new SystemSettingModel())->first();
            $apiKey = $setting['wa_api_key'] ?? null;
        }

        $target = preg_replace('/\D+/', '', (string) ($order['customer_phone'] ?? ''));
        if (empty($target)) {
            $this->errors[] = 'Nomor WhatsApp pelanggan belum diisi.';
            return false;
        }

        if (str_starts_with($target, '0')) {
            $target = '62' . substr($target, 1);
        } elseif (str_starts_with($target, '8')) {
            $target = '62' . $target;
        }

        if (empty($target)) {
            return false;
        }

        if (empty($apiKey)) {
            $this->errors[] = 'Token Fonnte belum diatur.';
            log_message('warning', 'Token Fonnte belum diatur, WhatsApp notification dilewati untuk order {order}.', ['order' => $order['order_number'] ?? '-']);
            return false;
        }

        $this->waitForWhatsAppSlot();

        $message = $this->buildInvoiceMessage($order, $invoice);
        [$response, $error, $httpCode] = $this->postToFonnte($apiKey, $target, $message);

        if ($response === false || ! empty($error) || $httpCode >= 400) {
            $this->errors[] = 'Fonnte tidak dapat mengirim pesan. Periksa token dan koneksi internet.';
            log_message('error', 'WhatsApp Fonnte gagal untuk order {order}: {error}', [
                'order' => $order['order_number'] ?? '-', 
                'error' => $error ?: $response,
            ]);
            return false;
        }

        $payload = json_decode($response, true);
        $sent = is_array($payload) && ! empty($payload['status']);
        if (! $sent) {
            $this->errors[] = 'Fonnte menolak pesan WhatsApp untuk nomor pelanggan.';
            log_message('error', 'WhatsApp Fonnte ditolak untuk order {order}: {response}', [
                'order' => $order['order_number'] ?? '-',
                'response' => $response,
            ]);
        }

        return $sent;
    }

    /** Build a WhatsApp-friendly invoice summary, including its itemized prices. */
    private function buildInvoiceMessage(array $order, ?array $invoice = null): string
    {
        $totalAmount = (float) ($invoice['total_tagihan'] ?? $order['total'] ?? 0);
        $remainingAmount = (float) ($invoice['sisa_tagihan'] ?? $order['remaining_amount'] ?? 0);

        $invoiceNumber = $invoice['nomor_invoice'] ?? $order['order_number'] ?? '-';
        $customerName = trim((string) ($order['customer_name'] ?? 'Pelanggan'));
        $orderNumber = $order['order_number'] ?? '-';

        $items = ! empty($order['id_order'])
            ? (new OrderItemModel())->getItems((int) $order['id_order'])
            : [];

        // ===========================
        // Link Invoice
        // ===========================
        $invoiceUrl = null;
        $pdfUrl = null;

        if (! empty($invoice['access_token'])) {
            $invoiceUrl = base_url('invoice/' . $invoice['access_token']);
            $pdfUrl = base_url('invoice/' . $invoice['access_token'] . '/pdf');
        }

        $lines = [
            "Halo {$customerName},",
            '',
            "Berikut rincian invoice *#{$invoiceNumber}*",
            "No. Pesanan: {$orderNumber}",
            '',
            '*RINCIAN PESANAN*',
        ];

        foreach ($items as $index => $item) {

            $name = trim((string) ($item['product_name'] ?? $item['nama_product'] ?? 'Produk'));

            $qty = (float) ($item['qty'] ?? 0);

            $price = (float) ($item['price'] ?? $item['harga'] ?? 0);

            $subtotal = (float) ($item['subtotal'] ?? ($qty * $price));

            $quantity = fmod($qty, 1.0) === 0.0
                ? (string) (int) $qty
                : rtrim(rtrim(number_format($qty, 2, ',', '.'), '0'), ',');

            $lines[] = sprintf(
                "%d. %s\n   %s x Rp %s = Rp %s",
                $index + 1,
                $name,
                $quantity,
                $this->formatCurrency($price),
                $this->formatCurrency($subtotal)
            );
        }

        if (empty($items)) {
            $lines[] = '- Rincian item tidak tersedia.';
        }

        $lines[] = '';
        $lines[] = '*Total Tagihan : Rp ' . $this->formatCurrency($totalAmount) . '*';
        $lines[] = '*Sisa Tagihan : Rp ' . $this->formatCurrency($remainingAmount) . '*';

        if (! empty($invoice['tanggal_jatuh_tempo'])) {
            $lines[] = 'Jatuh Tempo : ' . date('d-m-Y', strtotime($invoice['tanggal_jatuh_tempo']));
        }

        if ($invoiceUrl) {

            $lines[] = '';
            $lines[] = '📄 *Lihat Detail Invoice*';
            $lines[] = $invoiceUrl;

            $lines[] = '';
            $lines[] = '⬇️ *Download PDF Invoice*';
            $lines[] = $pdfUrl;
        }

        $lines[] = '';
        $lines[] = 'Terima kasih atas pesanan Anda.';

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

    private function formatCurrency(float $amount): string
    {
        return number_format($amount, 0, ',', '.');
    }

    /** Mengirim ke Fonnte lewat cURL, atau stream HTTP bila ekstensi cURL belum aktif. */
    private function postToFonnte(string $apiKey, string $target, string $message): array
    {
        if (function_exists('curl_init')) {
            $curl = curl_init();
            curl_setopt_array($curl, [
                CURLOPT_URL => 'https://api.fonnte.com/send',
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_TIMEOUT => 15,
                CURLOPT_POSTFIELDS => [
                    'target' => $target,
                    'message' => $message,
                ],
                CURLOPT_HTTPHEADER => ['Authorization: ' . $apiKey],
            ]);

            $response = curl_exec($curl);
            $error = curl_error($curl);
            $httpCode = (int) curl_getinfo($curl, CURLINFO_HTTP_CODE);
            curl_close($curl);

            return [$response, $error, $httpCode];
        }

        if (! filter_var(ini_get('allow_url_fopen'), FILTER_VALIDATE_BOOLEAN)) {
            return [false, 'Ekstensi cURL dan allow_url_fopen tidak tersedia.', 0];
        }

        $context = stream_context_create([
            'http' => [
                'method' => 'POST',
                'header' => "Authorization: {$apiKey}\r\nContent-Type: application/x-www-form-urlencoded\r\n",
                'content' => http_build_query(['target' => $target, 'message' => $message]),
                'timeout' => 15,
                'ignore_errors' => true,
            ],
        ]);
        $response = @file_get_contents('https://api.fonnte.com/send', false, $context);
        $headers = $http_response_header ?? [];
        $httpCode = 0;

        foreach ($headers as $header) {
            if (preg_match('#^HTTP/\\S+\\s+(\\d{3})#', $header, $matches)) {
                $httpCode = (int) $matches[1];
            }
        }

        return [$response, $response === false ? (error_get_last()['message'] ?? 'Permintaan HTTP ke Fonnte gagal.') : '', $httpCode];
    }

    /** Keeps Fonnte invoice messages at least 30 seconds apart across requests. */
    private function waitForWhatsAppSlot(): void
    {
        $cache = Services::cache();
        $lastSentAt = (int) ($cache->get(self::WHATSAPP_LAST_SENT_CACHE_KEY) ?: 0);
        $waitSeconds = self::WHATSAPP_INTERVAL_SECONDS - (time() - $lastSentAt);

        if ($waitSeconds > 0) {
            log_message('info', 'Menunda WhatsApp invoice selama {seconds} detik untuk menjaga jeda pengiriman.', ['seconds' => $waitSeconds]);
            sleep($waitSeconds);
        }

        // Simpan sebelum request API agar request berikutnya juga menghormati jeda,
        // termasuk saat Fonnte sedang lambat atau tidak dapat dihubungi.
        $cache->save(self::WHATSAPP_LAST_SENT_CACHE_KEY, time(), self::WHATSAPP_INTERVAL_SECONDS + 60);
    }

    public function fixEmptyTokens()
    {
        $invoiceModel = new InvoiceModel();
        
        // Ambil semua invoice yang access_token-nya masih NULL atau string kosong
        $invoices = $invoiceModel->groupStart()
                                 ->where('access_token', null)
                                 ->orWhere('access_token', '')
                                 ->groupEnd()
                                 ->findAll();

        if (empty($invoices)) {
            return "Tidak ada invoice yang perlu diperbarui. Semua sudah memiliki token.";
        }

        $updatedCount = 0;
        helper('text'); // Memuat helper text CI4 untuk random_string()

        foreach ($invoices as $inv) {
            // Generate token acak (bisa gunakan alnum 32 karakter)
            // Atau opsi native PHP: bin2hex(random_bytes(16))
            $newToken = random_string('alnum', 32); 

            // Asumsi primary key di tabel Anda adalah 'id_invoice'
            $invoiceModel->update($inv['id_invoice'], [
                'access_token' => $newToken
            ]);
            
            $updatedCount++;
        }

        return "Berhasil. {$updatedCount} invoice lama kini memiliki access_token.";
    }
}
