<?php

declare(strict_types=1);

namespace App\Domain\Notification\Listeners;

use App\Domain\Account\Events\AccountQuotaExceeded;
use App\Domain\Account\Events\AccountResourceLimitHit;
use App\Domain\Account\Models\Account;
use App\Mail\QuotaExceededMail;
use App\Mail\QuotaWarningMail;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;

class SendQuotaMails
{
    /**
     * Triggered when quota reaches 85% threshold.
     * NOTE: AccountQuotaWarning event yok — bu method bir cron/service'ten doğrudan çağrılabilir
     * ya da AccountResourceLimitHit üzerinden tetiklenebilir.
     */
    public function handleWarning(Account $account): void
    {
        $owner = $account->owner;
        if (! $owner || ! $account->quota_bytes) {
            return;
        }

        Mail::to($owner)->queue(
            new QuotaWarningMail($account, $account->quota_bytes, $account->disk_usage_bytes)
        );
    }

    public function handleExceeded(AccountQuotaExceeded $event): void
    {
        $owner = $event->account->owner;
        if (! $owner) {
            return;
        }

        Mail::to($owner)->queue(
            new QuotaExceededMail($event->account, $event->quotaBytes, $event->usageBytes)
        );
    }

    /**
     * AccountResourceLimitHit — snapshot cron'u her 5 dakikada bir limit aşımında
     * event fırlatır. Burada idempotency cache ile saatte bir bildirim atılır
     * (aynı hesap+fault için 1 saat içinde tekrar mail gitmez).
     *
     * Mail göndermenin yanında audit_log'a da yazılır — admin dashboard'ında
     * "son 24h fault" grafiği bunu okur.
     */
    public function handleResourceLimitHit(AccountResourceLimitHit $event): void
    {
        $cacheKey = "resource_limit_hit:{$event->account->id}:{$event->faultType}";

        if (Cache::has($cacheKey)) {
            return;  // 1 saat içinde zaten bildirildi
        }
        Cache::put($cacheKey, true, now()->addHour());

        // Audit log
        try {
            if (\Illuminate\Support\Facades\Schema::hasTable('audit_log')) {
                DB::table('audit_log')->insert([
                    'user_id' => $event->account->owner_user_id ?? null,
                    'action' => 'resource.limit_hit',
                    'target_type' => 'account',
                    'target_id' => $event->account->id,
                    'ip_address' => null,
                    'outcome' => 'warning',
                    'metadata' => json_encode([
                        'fault_type' => $event->faultType,
                        'limit_value' => $event->limitValue,
                        'actual_value' => $event->actualValue,
                        'username' => $event->account->username,
                    ], JSON_UNESCAPED_UNICODE),
                    'created_at' => now(),
                ]);
            }
        } catch (\Throwable $e) {
            Log::warning('audit_log insert failed in handleResourceLimitHit', ['error' => $e->getMessage()]);
        }

        // Mail (best-effort; QuotaWarningMail'i resource-limit için generic kullan)
        $owner = $event->account->owner;
        if ($owner && $event->account->quota_bytes) {
            try {
                Mail::to($owner)->queue(
                    new QuotaWarningMail($event->account, $event->account->quota_bytes, $event->account->disk_usage_bytes ?? 0)
                );
            } catch (\Throwable $e) {
                Log::warning('Resource limit mail dispatch failed', [
                    'account_id' => $event->account->id,
                    'fault' => $event->faultType,
                    'error' => $e->getMessage(),
                ]);
            }
        }
    }
}
