<?php

namespace App\Console\Commands;

use App\Mail\SubscriptionReminderMail;
use App\Models\Setting;
use App\Models\Subscription;
use App\Models\SubscriptionReminder;
use App\Services\Sms\SmsService;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;

/**
 * Abonelik bitiş tarihine (tamamlanma tarihi + kaç aylık sözleşme) belirli gün kala
 * müşteriye e-posta ve/veya SMS hatırlatması gönderir. Master Admin, Ayarlar sayfasından
 * hatırlatma günlerini, gönderim saatini, şablonları ve kanalları (e-posta/SMS) açıp
 * kapatabilir. Zamanlama routes/console.php içinde tanımlıdır.
 */
class SendSubscriptionReminders extends Command
{
    protected $signature = 'subscriptions:send-reminders {--force : Saat kontrolünü yok sayıp hemen çalıştır (test için)}';

    protected $description = 'Abonelik bitişine yaklaşan müşterilere e-posta/SMS hatırlatması gönderir.';

    public function handle(SmsService $sms): int
    {
        $emailEnabled = (bool) Setting::get('notif_email_enabled', false);
        $smsEnabled = (bool) Setting::get('notif_sms_enabled', false);

        if (! $emailEnabled && ! $smsEnabled) {
            $this->info('Hatırlatma bildirimleri (e-posta/SMS) devre dışı. İşlem yapılmadı.');

            return self::SUCCESS;
        }

        $reminderHour = str_pad((string) Setting::get('notif_reminder_hour', '09'), 2, '0', STR_PAD_LEFT);

        if (! $this->option('force') && now()->format('H') !== $reminderHour) {
            $this->info("Şu an gönderim saati değil (ayarlanan saat: {$reminderHour}:00). Atlandı.");

            return self::SUCCESS;
        }

        $days = collect(explode(',', (string) Setting::get('notif_reminder_days', '7,3,1')))
            ->map(fn ($d) => (int) trim($d))
            ->filter(fn ($d) => $d > 0)
            ->unique()
            ->values();

        if ($days->isEmpty()) {
            $this->warn('Hatırlatma günleri tanımlanmamış (Ayarlar sayfasından ekleyin).');

            return self::SUCCESS;
        }

        $emailSubjectTpl = (string) Setting::get('notif_email_subject', 'Aboneliğinizin Süresi Yaklaşıyor');
        $emailBodyTpl = (string) Setting::get('notif_email_template', $this->defaultEmailTemplate());
        $smsBodyTpl = (string) Setting::get('notif_sms_template', $this->defaultSmsTemplate());

        $sentEmail = 0;
        $sentSms = 0;
        $failed = 0;

        foreach ($days as $daysBefore) {
            $targetDate = now()->addDays($daysBefore)->toDateString();

            $subscriptions = Subscription::query()
                ->where('status', 'completed')
                ->whereNotNull('completed_at')
                ->whereRaw('DATE(DATE_ADD(completed_at, INTERVAL contract_months MONTH)) = ?', [$targetDate])
                ->with('package', 'company')
                ->get();

            foreach ($subscriptions as $subscription) {
                $placeholders = [
                    '{musteri_adi}' => $subscription->customer_name,
                    '{paket_adi}' => $subscription->package?->name ?? '-',
                    '{firma_adi}' => $subscription->company?->name ?? '-',
                    '{referans_no}' => $subscription->reference_no,
                    '{bitis_tarihi}' => \Illuminate\Support\Carbon::parse($targetDate)->format('d.m.Y'),
                    '{kalan_gun}' => (string) $daysBefore,
                ];

                if ($emailEnabled && $subscription->email) {
                    $alreadySent = SubscriptionReminder::where('subscription_id', $subscription->id)
                        ->where('days_before', $daysBefore)->where('channel', 'email')->exists();

                    if (! $alreadySent) {
                        $subject = strtr($emailSubjectTpl, $placeholders);
                        $body = nl2br(e(strtr($emailBodyTpl, $placeholders)));

                        try {
                            Mail::to($subscription->email)->send(new SubscriptionReminderMail($subscription, $subject, $body));
                            SubscriptionReminder::create([
                                'subscription_id' => $subscription->id, 'days_before' => $daysBefore,
                                'channel' => 'email', 'sent_at' => now(), 'success' => true,
                            ]);
                            $sentEmail++;
                        } catch (\Throwable $e) {
                            Log::error('Hatırlatma e-postası gönderilemedi: '.$e->getMessage());
                            SubscriptionReminder::create([
                                'subscription_id' => $subscription->id, 'days_before' => $daysBefore,
                                'channel' => 'email', 'sent_at' => now(), 'success' => false, 'error_message' => $e->getMessage(),
                            ]);
                            $failed++;
                        }
                    }
                }

                if ($smsEnabled && $subscription->phone) {
                    $alreadySent = SubscriptionReminder::where('subscription_id', $subscription->id)
                        ->where('days_before', $daysBefore)->where('channel', 'sms')->exists();

                    if (! $alreadySent) {
                        $message = strtr($smsBodyTpl, $placeholders);
                        $result = $sms->send($subscription->phone, $message);

                        SubscriptionReminder::create([
                            'subscription_id' => $subscription->id, 'days_before' => $daysBefore,
                            'channel' => 'sms', 'sent_at' => now(), 'success' => $result['success'],
                            'error_message' => $result['success'] ? null : $result['message'],
                        ]);

                        $result['success'] ? $sentSms++ : $failed++;
                    }
                }
            }
        }

        $this->info("Tamamlandı. E-posta: {$sentEmail}, SMS: {$sentSms}, Başarısız: {$failed}");

        return self::SUCCESS;
    }

    protected function defaultEmailTemplate(): string
    {
        return "Sayın {musteri_adi},\n\n"
            ."{paket_adi} paketiniz {bitis_tarihi} tarihinde sona erecektir ({kalan_gun} gün kaldı).\n"
            ."Aboneliğinizi yenilemek için bizimle iletişime geçebilirsiniz.\n\n"
            .'Referans No: {referans_no}';
    }

    protected function defaultSmsTemplate(): string
    {
        return 'Sayın {musteri_adi}, {paket_adi} paketiniz {bitis_tarihi} tarihinde sona eriyor ({kalan_gun} gün kaldı). Yenilemek icin bizi arayin.';
    }
}
