<?php

namespace App\Services;

/**
 * WhatsappService
 * Mengirim pesan WhatsApp via Sidobe API v1.
 * Official Docs: https://docs.sidobe.com/
 */
class WhatsappService
{
    protected string $apiKey;
    protected string $sender;
    protected bool $enabled = false;
    protected string $baseUrl = 'https://api.sidobe.com/wa/v1/send-message';
    protected string $provider = 'sidobe';
    protected string $fonnteToken = '';
    protected string $groupIdAttendance = '';
    protected string $groupIdJournal = '';
    protected array $features = [];

    public function __construct()
    {
        $db   = \Config\Database::connect();
        $keys = [
            'wa_sidobe_api_key', 'wa_sidobe_sender', 'wa_enabled', 'wa_provider', 'wa_fonnte_token',
            'wa_enable_tahfidz', 'wa_enable_schedule', 'wa_enable_attendance', 'wa_enable_journal',
            'wa_enable_tabungan',
            'wa_group_id_attendance', 'wa_group_id_journal'
        ];
        $rows = $db->table('settings')
                   ->whereIn('setting_key', $keys)
                   ->get()->getResultArray();
        $map = array_column($rows, 'setting_value', 'setting_key');

        $this->apiKey  = $map['wa_sidobe_api_key'] ?? '';
        $this->sender  = $map['wa_sidobe_sender']  ?? '';
        $this->enabled = ($map['wa_enabled'] ?? '0') == '1';
        $this->provider = $map['wa_provider'] ?? 'sidobe';
        $this->fonnteToken = $map['wa_fonnte_token'] ?? '';
        $this->groupIdAttendance = $map['wa_group_id_attendance'] ?? '';
        $this->groupIdJournal = $map['wa_group_id_journal'] ?? '';

        $this->features = [
            'tahfidz'    => ($map['wa_enable_tahfidz'] ?? '0') == '1',
            'schedule'   => ($map['wa_enable_schedule'] ?? '0') == '1',
            'attendance' => ($map['wa_enable_attendance'] ?? '0') == '1',
            'journal'    => ($map['wa_enable_journal'] ?? '0') == '1',
            'tabungan'   => ($map['wa_enable_tabungan'] ?? '0') == '1',
        ];

        log_message('debug', 'WhatsappService Init: enabled=' . ($this->enabled ? '1' : '0') . ', provider=' . $this->provider . ', has_sidobe_key=' . (!empty($this->apiKey) ? '1' : '0') . ', has_fonnte_token=' . (!empty($this->fonnteToken) ? '1' : '0'));
    }

    /**
     * Cek apakah fitur tertentu aktif dan WhatsApp secara global aktif.
     */
    public function isFeatureEnabled(string $feature): bool
    {
        $featEnabled = $this->features[$feature] ?? false;
        log_message('debug', "WhatsappService isFeatureEnabled('{$feature}'): enabled=" . ($this->enabled ? '1' : '0') . ", feature_enabled=" . ($featEnabled ? '1' : '0'));
        if (!$this->enabled) {
            return false;
        }
        return $featEnabled;
    }

    /**
     * Ambil ID Grup WhatsApp Absensi Siswa yang dikonfigurasi di pengaturan.
     */
    public function getGroupIdAttendance(): string
    {
        return $this->groupIdAttendance;
    }

    /**
     * Ambil ID Grup WhatsApp Jurnal Mengajar yang dikonfigurasi di pengaturan.
     */
    public function getGroupIdJournal(): string
    {
        return $this->groupIdJournal;
    }

    /**
     * Cek apakah konfigurasi sudah lengkap dan aktif.
     */
    public function isConfigured(): bool
    {
        log_message('debug', "WhatsappService isConfigured: enabled=" . ($this->enabled ? '1' : '0') . ", provider=" . $this->provider . ", has_fonnte_token=" . (!empty($this->fonnteToken) ? '1' : '0') . ", has_sidobe_key=" . (!empty($this->apiKey) ? '1' : '0'));
        if (!$this->enabled) return false;
        
        if ($this->provider === 'fonnte') {
            return !empty($this->fonnteToken);
        }
        return !empty($this->apiKey);
    }

    /**
     * Kirim pesan ke satu nomor / group_id.
     *
     * @param string $target  Nomor WA (+628xxx) atau Group ID WA
     * @param string $message Isi pesan
     * @param bool   $isGroup true jika target adalah Group ID WA
     * @return array ['success' => bool, 'message' => string]
     */
    public function send(string $target, string $message, bool $isGroup = false): array
    {
        if (!$this->isConfigured()) {
            log_message('error', 'WhatsappService: Konfigurasi API Key WhatsApp belum lengkap.');
            return ['success' => false, 'message' => 'Konfigurasi API Key WhatsApp belum lengkap.'];
        }

        if (empty($target)) {
            log_message('error', 'WhatsappService: Tujuan pengiriman kosong.');
            return ['success' => false, 'message' => 'Tujuan pengiriman kosong.'];
        }

        if ($this->provider === 'fonnte') {
            $res = $this->sendFonnte($target, $message, $isGroup);
        } else {
            $res = $this->sendSidobe($target, $message, $isGroup);
        }

        if (!$res['success']) {
            log_message('error', 'WhatsappService: Gagal mengirim ke ' . $target . ' - Alasan: ' . $res['message']);
        } else {
            log_message('info', 'WhatsappService: Berhasil mengirim ke ' . $target);
        }

        return $res;
    }

    /**
     * Kirim via Fonnte.
     */
    protected function sendFonnte(string $target, string $message, bool $isGroup = false): array
    {
        $targetFormatted = trim($target);
        if ($isGroup) {
            if (!str_contains($targetFormatted, '@')) {
                $targetFormatted .= '@g.us';
            }
        } else {
            $cleanNumber = preg_replace('/\D/', '', $targetFormatted);
            if (str_starts_with($cleanNumber, '0')) {
                $cleanNumber = '62' . substr($cleanNumber, 1);
            }
            $targetFormatted = $cleanNumber;
        }

        $payload = [
            'target' => $targetFormatted,
            'message' => $message,
            'countryCode' => '62'
        ];

        $ch = curl_init('https://api.fonnte.com/send');
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POST           => true,
            CURLOPT_POSTFIELDS     => http_build_query($payload),
            CURLOPT_HTTPHEADER     => [
                'Authorization: ' . $this->fonnteToken
            ],
            CURLOPT_IPRESOLVE      => CURL_IPRESOLVE_V4,
            CURLOPT_CONNECTTIMEOUT => 15,
            CURLOPT_TIMEOUT        => 30,
            CURLOPT_SSL_VERIFYPEER => false,
        ]);

        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $curlErr  = curl_error($ch);
        curl_close($ch);

        if ($curlErr) {
            return ['success' => false, 'message' => 'cURL error (Fonnte): ' . $curlErr];
        }

        $result = json_decode($response, true);
        if (isset($result['status']) && $result['status'] === true) {
            return ['success' => true, 'message' => 'Pesan berhasil dikirim via Fonnte.'];
        }

        $errMsg = $result['reason'] ?? ($result['message'] ?? ('HTTP ' . $httpCode . ': ' . $response));
        return ['success' => false, 'message' => 'Gagal kirim via Fonnte: ' . $errMsg];
    }

    /**
     * Kirim via Sidobe.
     */
    protected function sendSidobe(string $target, string $message, bool $isGroup = false): array
    {
        $data = [
            'message' => $message
        ];

        if ($isGroup) {
            $target = trim($target);
            if (!str_contains($target, '@')) {
                $target .= '@g.us';
            }
            $data['group_id'] = $target;
        } else {
            $formattedPhone = $this->formatE164($target);
            if (strlen($formattedPhone) < 8) {
                return ['success' => false, 'message' => 'Format nomor telepon tidak valid: ' . $target];
            }
            $data['phone'] = $formattedPhone;
        }

        if (!empty($this->sender)) {
            $formattedSender = $this->formatE164($this->sender);
            if (!empty($formattedSender) && strlen($formattedSender) >= 8) {
                $data['sender_phone'] = $formattedSender;
            }
        }

        $payload = json_encode($data);

        $ch = curl_init($this->baseUrl);
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POST           => true,
            CURLOPT_POSTFIELDS     => $payload,
            CURLOPT_HTTPHEADER     => [
                'Content-Type: application/json',
                'X-Secret-Key: ' . $this->apiKey
            ],
            CURLOPT_IPRESOLVE      => CURL_IPRESOLVE_V4,
            CURLOPT_CONNECTTIMEOUT => 15,
            CURLOPT_TIMEOUT        => 30,
            CURLOPT_SSL_VERIFYPEER => false,
        ]);

        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $curlErr  = curl_error($ch);
        curl_close($ch);

        if ($curlErr) {
            return ['success' => false, 'message' => 'cURL error: ' . $curlErr];
        }

        $result = json_decode($response, true);
        if ($httpCode === 200 && isset($result['is_success']) && $result['is_success'] === true) {
            return ['success' => true, 'message' => 'Pesan berhasil dikirim.'];
        }

        $errMsg = $result['message'] ?? ($result['error'] ?? ('HTTP ' . $httpCode . ': ' . $response));
        return ['success' => false, 'message' => 'Gagal kirim: ' . $errMsg];
    }

    /**
     * Kirim ke banyak nomor sekaligus.
     */
    public function sendBulk(array $targets, string $message): array
    {
        $sent = 0; $failed = 0; $errors = [];

        foreach ($targets as $target) {
            $res = $this->send($target, $message, false);
            if ($res['success']) {
                $sent++;
            } else {
                $failed++;
                $errors[] = $target . ': ' . $res['message'];
            }
            usleep(500000);
        }

        return ['sent' => $sent, 'failed' => $failed, 'errors' => $errors];
    }

    /**
     * Format nomor tujuan ke E.164 (cth: +628xxxxxxxx)
     */
    protected function formatE164(string $number): string
    {
        $number = trim(preg_replace('/\s+/', '', $number));
        if (empty($number)) {
            return '';
        }

        // Jika sudah ada plus, biarkan
        if (str_starts_with($number, '+')) {
            return $number;
        }

        // Hilangkan non-digit
        $digits = preg_replace('/\D/', '', $number);
        if (empty($digits)) {
            return '';
        }

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

        return '+' . $digits;
    }
}
