<?php

namespace App\Console\Commands;

use App\Person;
use App\Setting;
use App\Services\WasenderApi;
use Carbon\Carbon;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;

class SendWhatsappMarketingCampaigns extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'whatsapp:marketing-send';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Send WhatsApp marketing campaigns in controlled batches (cron).';

    public function handle()
    {
        // مفاتيح التفعيل
        if ((int) Setting::findByKey('whatsapp_enabled', '0') !== 1) {
            return 0;
        }

        if ((int) Setting::findByKey('whatsapp_marketing_enabled', '0') !== 1) {
            return 0;
        }

        $now = Carbon::now();

        // إعدادات التوقيت
        $delay = max(0, (int) Setting::findByKey('whatsapp_marketing_delay', '1')); // seconds
        $jitter = max(0, (int) Setting::findByKey('whatsapp_marketing_delay_jitter', '0')); // seconds
        $batchSize = max(1, (int) Setting::findByKey('whatsapp_marketing_batch', '10'));
        $pause = max(0, (int) Setting::findByKey('whatsapp_marketing_pause', '10')); // seconds
        $maxRetries = max(0, (int) Setting::findByKey('whatsapp_marketing_max_retries', '2'));
        $retryDelay = max(1, (int) Setting::findByKey('whatsapp_marketing_retry_delay', '10')); // seconds
        $timeout = max(5, (int) Setting::findByKey('whatsapp_marketing_timeout', '25')); // seconds
        $maxPerRun = max(1, (int) Setting::findByKey('whatsapp_marketing_max_per_run', '100'));
        $sessionPause = max(0, (int) Setting::findByKey('whatsapp_marketing_session_pause', '900')); // seconds

        // حملة واحدة فقط في كل تشغيل (لتفادي اختلاط التوقيت)
        $campaign = DB::table('whatsapp_campaigns')
            ->where('context', 'marketing')
            ->where('status_label', 'RUNNING')
            ->where(function ($q) use ($now) {
                $q->whereNull('next_run_at')->orWhere('next_run_at', '<=', $now);
            })
            ->orderBy('id', 'asc')
            ->first();

        if (!$campaign) {
            return 0;
        }

        // جلب مستلمين (Pending) أو (Failed + ready for retry)
        $recipients = DB::table('whatsapp_campaign_recipients')
            ->where('campaign_id', $campaign->id)
            ->where(function ($q) use ($now, $maxRetries) {
                $q->where('status_code', 1) // PENDING
                    ->orWhere(function ($q2) use ($now, $maxRetries) {
                        $q2->where('status_code', 3) // FAILED
                            ->where('attempts', '<', $maxRetries)
                            ->where(function ($q3) use ($now) {
                                $q3->whereNull('next_attempt_at')->orWhere('next_attempt_at', '<=', $now);
                            });
                    });
            })
            ->orderBy('id', 'asc')
            ->limit($maxPerRun)
            ->get();

        if ($recipients->count() === 0) {
            // لا يوجد شيء للإرسال -> إنهاء الحملة
            DB::table('whatsapp_campaigns')->where('id', $campaign->id)->update([
                'status_code' => 4,
                'status_label' => 'DONE',
                'next_run_at' => null,
                'updated_at' => $now,
            ]);
            return 0;
        }

        try {
            $api = new WasenderApi($timeout);
        } catch (\Exception $e) {
            // خلّها PAUSED لحين إصلاح الإعدادات
            DB::table('whatsapp_campaigns')->where('id', $campaign->id)->update([
                'status_code' => 3,
                'status_label' => 'PAUSED',
                'next_run_at' => $now->copy()->addMinutes(10),
                'updated_at' => $now,
            ]);
            return 0;
        }

        $sentInThisRun = 0;
        $sentInBatch = 0;

        foreach ($recipients as $r) {
            // حماية إضافية: لو تم إيقاف الحملة يدويًا
            $currentCampaign = DB::table('whatsapp_campaigns')->where('id', $campaign->id)->first();
            if (!$currentCampaign || $currentCampaign->status_label !== 'RUNNING') {
                break;
            }

            $person = $r->person_id ? Person::find($r->person_id) : null;
            $text = $this->renderText((string) $campaign->body, $person);

            $success = false;
            $msgId = null;
            $keyId = null;
            $payloadJson = null;
            $responseJson = null;
            $errorText = null;

            try {
                $res = $api->sendText($r->to, $text);

                $payloadJson = json_encode($res['payload'] ?? [], JSON_UNESCAPED_UNICODE);
                $responseJson = json_encode($res['body'] ?? [], JSON_UNESCAPED_UNICODE);

                $success = (isset($res['body']['success']) && $res['body']['success'] === true);
                // حسب توثيق Wasender: data.msgId
                $msgId = $res['body']['data']['msgId'] ?? null;
                // احتياط: لو رجّع key.id
                $keyId = $res['body']['data']['key']['id'] ?? null;

                if (!$success) {
                    $errorText = 'HTTP ' . ($res['http_code'] ?? '');
                }

                // تحديث recipient
                $update = [
                    'attempts' => ((int)$r->attempts) + 1,
                    'updated_at' => Carbon::now(),
                ];

                if ($success) {
                    $update['status_code'] = 2;
                    $update['status_label'] = 'SENT';
                    $update['sent_at'] = Carbon::now();
                    $update['api_msg_id'] = $msgId ?: $keyId;

                    // خزن الرقم الموحد لو توفر
                    if (!empty($res['payload']['to'])) {
                        $update['to'] = $res['payload']['to'];
                    }

                    $update['error'] = null;
                    $update['next_attempt_at'] = null;
                } else {
                    $update['status_code'] = 3;
                    $update['status_label'] = 'FAILED';
                    $update['error'] = $errorText;
                    $update['next_attempt_at'] = ((((int)$r->attempts) + 1) < $maxRetries)
                        ? Carbon::now()->addSeconds($retryDelay)
                        : null;
                }

                DB::table('whatsapp_campaign_recipients')->where('id', $r->id)->update($update);

                // إدخال log
                DB::table('whatsapp_logs')->insert([
                    'context'       => 'marketing',
                    'model_type'    => $person ? 'App\\Person' : null,
                    'model_id'      => $person ? $person->id : null,
                    'to'            => $res['payload']['to'] ?? $r->to,
                    'message_type'  => 'text',
                    'text'          => $text,
                    'document_url'  => null,
                    'file_name'     => null,
                    'api_msg_id'    => $msgId,
                    'api_key_id'    => $keyId,
                    'status_code'   => $success ? 2 : 0,
                    'status_label'  => $success ? 'SENT' : 'FAILED',
                    'payload'       => $payloadJson,
                    'response'      => $responseJson,
                    'error'         => $success ? null : $errorText,
                    'created_by'    => $campaign->created_by,
                    'created_at'    => Carbon::now(),
                    'updated_at'    => Carbon::now(),
                ]);

            } catch (\Exception $e) {
                $errorText = $e->getMessage();

                DB::table('whatsapp_campaign_recipients')->where('id', $r->id)->update([
                    'attempts' => ((int)$r->attempts) + 1,
                    'status_code' => 3,
                    'status_label' => 'FAILED',
                    'error' => $errorText,
                    'next_attempt_at' => ((((int)$r->attempts) + 1) < $maxRetries)
                        ? Carbon::now()->addSeconds($retryDelay)
                        : null,
                    'updated_at' => Carbon::now(),
                ]);

                DB::table('whatsapp_logs')->insert([
                    'context'       => 'marketing',
                    'model_type'    => $r->person_id ? 'App\\Person' : null,
                    'model_id'      => $r->person_id,
                    'to'            => $r->to,
                    'message_type'  => 'text',
                    'text'          => $text,
                    'status_code'   => 0,
                    'status_label'  => 'FAILED',
                    'payload'       => null,
                    'response'      => null,
                    'error'         => $errorText,
                    'created_by'    => $campaign->created_by,
                    'created_at'    => Carbon::now(),
                    'updated_at'    => Carbon::now(),
                ]);
            }

            $sentInThisRun++;
            $sentInBatch++;

            // Delay (مع jitter بسيط لتقليل البلوك)
            $sleepSec = $delay;
            if ($jitter > 0) {
                $sleepSec = $sleepSec + random_int(-$jitter, $jitter);
                if ($sleepSec < 0) $sleepSec = 0;
            }
            if ($sleepSec > 0) {
                sleep($sleepSec);
            }

            // Pause بعد كل دفعة
            if ($sentInBatch >= $batchSize) {
                $sentInBatch = 0;
                if ($pause > 0) {
                    sleep($pause);
                }
            }

            // Session pause بعد MaxPerRun (بدون sleep طويل)
            if ($sentInThisRun >= $maxPerRun) {
                DB::table('whatsapp_campaigns')->where('id', $campaign->id)->update([
                    'next_run_at' => Carbon::now()->addSeconds($sessionPause),
                    'updated_at' => Carbon::now(),
                ]);
                return 0;
            }
        }

        // شغّل مرة ثانية بعد دقيقة
        DB::table('whatsapp_campaigns')->where('id', $campaign->id)->update([
            'next_run_at' => Carbon::now()->addSeconds(60),
            'updated_at' => Carbon::now(),
        ]);

        return 0;
    }

    private function renderText($template, $person = null)
    {
        $name = $person ? trim((string) $person->name) : '';
        if ($name === '') {
            $name = 'عميلنا الكريم';
        }

        $business = (string) Setting::findByKey('SiteName', '');
        $today = Carbon::now()->format('d/m/Y');

        return str_replace(
            ['{name}', '{business_name}', '{today}'],
            [$name, $business, $today],
            (string) $template
        );
    }
}
