<?php

namespace App\Services\Notifications;

use App\Models\DwNotification;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Throwable;

class NotificationCenterService
{
    public function create(array $data): DwNotification
    {
        $fingerprint = $data['fingerprint'] ?? $this->fingerprint($data);

        return DwNotification::query()->updateOrCreate(
            ['fingerprint' => $fingerprint],
            [
                'client_id' => $data['client_id'] ?? null,
                'user_id' => $data['user_id'] ?? null,
                'category' => $data['category'] ?? 'system',
                'source_type' => $data['source_type'] ?? null,
                'source_id' => $data['source_id'] ?? null,
                'level' => $data['level'] ?? 'info',
                'title' => $data['title'] ?? 'Bildirim',
                'message' => $data['message'] ?? null,
                'action_label' => $data['action_label'] ?? null,
                'action_url' => $data['action_url'] ?? null,
                'payload' => $data['payload'] ?? null,
                'expires_at' => $data['expires_at'] ?? null,
                'dismissed_at' => null,
            ]
        );
    }

    public function unreadCount(?int $clientId = null): int
    {
        if (! Schema::hasTable('dw_notifications')) {
            return 0;
        }

        return DwNotification::query()
            ->visible()
            ->unread()
            ->when($clientId, fn ($q) => $q->where('client_id', $clientId))
            ->count();
    }

    public function recent(int $limit = 8, ?int $clientId = null)
    {
        if (! Schema::hasTable('dw_notifications')) {
            return collect();
        }

        return DwNotification::query()
            ->visible()
            ->when($clientId, fn ($q) => $q->where('client_id', $clientId))
            ->latest()
            ->limit($limit)
            ->get();
    }

    public function markAllRead(?int $clientId = null): int
    {
        if (! Schema::hasTable('dw_notifications')) {
            return 0;
        }

        return DwNotification::query()
            ->visible()
            ->unread()
            ->when($clientId, fn ($q) => $q->where('client_id', $clientId))
            ->update(['read_at' => now(), 'updated_at' => now()]);
    }

    public function buildFromSystem(int $days = 7, ?int $clientId = null): array
    {
        $created = [
            'api_errors' => 0,
            'mail_failures' => 0,
            'critical_alerts' => 0,
            'health_scores' => 0,
            'overdue_tasks' => 0,
        ];

        $created['api_errors'] = $this->buildApiErrorNotifications($days, $clientId);
        $created['mail_failures'] = $this->buildMailFailureNotifications($days, $clientId);
        $created['critical_alerts'] = $this->buildCriticalAlertNotifications($days, $clientId);
        $created['health_scores'] = $this->buildHealthScoreNotifications($clientId);
        $created['overdue_tasks'] = $this->buildOverdueTaskNotifications($clientId);

        return $created;
    }

    protected function buildApiErrorNotifications(int $days, ?int $clientId): int
    {
        if (! Schema::hasTable('api_request_logs')) {
            return 0;
        }

        $query = DB::table('api_request_logs')
            ->where('created_at', '>=', now()->subDays($days));

        if (Schema::hasColumn('api_request_logs', 'status')) {
            $query->where(function ($q) {
                $q->where('status', 'failed')->orWhere('status', 'error');
            });
        }

        if ($clientId && Schema::hasColumn('api_request_logs', 'client_id')) {
            $query->where('client_id', $clientId);
        }

        $rows = $query->latest('created_at')->limit(50)->get();
        $count = 0;

        foreach ($rows as $row) {
            $id = $row->id ?? md5(json_encode($row));
            $platform = $row->platform ?? $row->service ?? 'API';
            $this->create([
                'fingerprint' => 'api-error-'.$id,
                'client_id' => $row->client_id ?? null,
                'category' => 'api',
                'source_type' => 'api_request_logs',
                'source_id' => is_numeric($id) ? (int) $id : null,
                'level' => 'danger',
                'title' => $platform.' API hatası',
                'message' => $row->error_message ?? $row->message ?? 'API isteği başarısız oldu. Bağlantı ve token bilgileri kontrol edilmeli.',
                'action_label' => 'API Loglarını Gör',
                'action_url' => route('admin.system.logs'),
                'payload' => (array) $row,
            ]);
            $count++;
        }

        return $count;
    }

    protected function buildMailFailureNotifications(int $days, ?int $clientId): int
    {
        if (! Schema::hasTable('email_logs')) {
            return 0;
        }

        $query = DB::table('email_logs')->where('created_at', '>=', now()->subDays($days));

        if (Schema::hasColumn('email_logs', 'status')) {
            $query->whereIn('status', ['failed', 'error']);
        }

        if ($clientId && Schema::hasColumn('email_logs', 'client_id')) {
            $query->where('client_id', $clientId);
        }

        $rows = $query->latest('created_at')->limit(50)->get();
        $count = 0;

        foreach ($rows as $row) {
            $this->create([
                'fingerprint' => 'mail-failure-'.($row->id ?? md5(json_encode($row))),
                'client_id' => $row->client_id ?? null,
                'category' => 'mail',
                'source_type' => 'email_logs',
                'source_id' => isset($row->id) ? (int) $row->id : null,
                'level' => 'warning',
                'title' => 'Mail gönderimi başarısız',
                'message' => $row->error_message ?? $row->message ?? 'Bir rapor veya yönetim maili gönderilemedi.',
                'action_label' => 'Mail Logları',
                'action_url' => route('admin.mail.logs'),
                'payload' => (array) $row,
            ]);
            $count++;
        }

        return $count;
    }

    protected function buildCriticalAlertNotifications(int $days, ?int $clientId): int
    {
        if (! Schema::hasTable('alert_logs')) {
            return 0;
        }

        $query = DB::table('alert_logs')->where('created_at', '>=', now()->subDays($days));

        if (Schema::hasColumn('alert_logs', 'severity')) {
            $query->whereIn('severity', ['critical', 'danger', 'high']);
        } elseif (Schema::hasColumn('alert_logs', 'level')) {
            $query->whereIn('level', ['critical', 'danger', 'high']);
        }

        if ($clientId && Schema::hasColumn('alert_logs', 'client_id')) {
            $query->where('client_id', $clientId);
        }

        $rows = $query->latest('created_at')->limit(50)->get();
        $count = 0;

        foreach ($rows as $row) {
            $this->create([
                'fingerprint' => 'critical-alert-'.($row->id ?? md5(json_encode($row))),
                'client_id' => $row->client_id ?? null,
                'category' => 'alert',
                'source_type' => 'alert_logs',
                'source_id' => isset($row->id) ? (int) $row->id : null,
                'level' => 'danger',
                'title' => $row->title ?? 'Kritik uyarı tetiklendi',
                'message' => $row->message ?? 'Kritik uyarı kuralı tetiklendi. Müşteri performansı veya bağlantı sağlığı kontrol edilmeli.',
                'action_label' => 'Uyarı Geçmişi',
                'action_url' => route('admin.alert-logs.index'),
                'payload' => (array) $row,
            ]);
            $count++;
        }

        return $count;
    }

    protected function buildHealthScoreNotifications(?int $clientId): int
    {
        if (! Schema::hasTable('client_health_scores')) {
            return 0;
        }

        $query = DB::table('client_health_scores')
            ->where('created_at', '>=', now()->subDays(2));

        if (Schema::hasColumn('client_health_scores', 'score')) {
            $query->where('score', '<', 65);
        }

        if ($clientId && Schema::hasColumn('client_health_scores', 'client_id')) {
            $query->where('client_id', $clientId);
        }

        $rows = $query->latest('created_at')->limit(50)->get();
        $count = 0;

        foreach ($rows as $row) {
            $score = (int) ($row->score ?? 0);
            $this->create([
                'fingerprint' => 'health-score-'.$row->client_id.'-'.($row->created_at ?? now()->toDateString()),
                'client_id' => $row->client_id ?? null,
                'category' => 'health',
                'source_type' => 'client_health_scores',
                'source_id' => isset($row->id) ? (int) $row->id : null,
                'level' => $score < 45 ? 'danger' : 'warning',
                'title' => 'Müşteri sağlık skoru düştü',
                'message' => 'Sağlık skoru '.$score.'/100 seviyesinde. API, mail, rapor ve görev durumu kontrol edilmeli.',
                'action_label' => 'Sağlık Skoru',
                'action_url' => isset($row->client_id) ? route('admin.health-scores.show', $row->client_id) : route('admin.health-scores.index'),
                'payload' => (array) $row,
            ]);
            $count++;
        }

        return $count;
    }

    protected function buildOverdueTaskNotifications(?int $clientId): int
    {
        if (! Schema::hasTable('operation_tasks')) {
            return 0;
        }

        $query = DB::table('operation_tasks');

        if (Schema::hasColumn('operation_tasks', 'due_at')) {
            $query->whereNotNull('due_at')->where('due_at', '<', now());
        } elseif (Schema::hasColumn('operation_tasks', 'due_date')) {
            $query->whereNotNull('due_date')->where('due_date', '<', now()->toDateString());
        }

        if (Schema::hasColumn('operation_tasks', 'status')) {
            $query->whereNotIn('status', ['done', 'completed', 'tamamlandi', 'tamamlandı']);
        }

        if ($clientId && Schema::hasColumn('operation_tasks', 'client_id')) {
            $query->where('client_id', $clientId);
        }

        $rows = $query->latest('created_at')->limit(50)->get();
        $count = 0;

        foreach ($rows as $row) {
            $this->create([
                'fingerprint' => 'overdue-task-'.($row->id ?? md5(json_encode($row))),
                'client_id' => $row->client_id ?? null,
                'category' => 'operation',
                'source_type' => 'operation_tasks',
                'source_id' => isset($row->id) ? (int) $row->id : null,
                'level' => 'warning',
                'title' => 'Geciken operasyon görevi',
                'message' => $row->title ?? 'Bir operasyon görevi termin tarihini geçti.',
                'action_label' => 'Görev Panosu',
                'action_url' => route('admin.task-board.index'),
                'payload' => (array) $row,
            ]);
            $count++;
        }

        return $count;
    }

    protected function fingerprint(array $data): string
    {
        return md5(implode('|', [
            $data['category'] ?? 'system',
            $data['source_type'] ?? 'manual',
            $data['source_id'] ?? '',
            $data['client_id'] ?? '',
            $data['title'] ?? '',
        ]));
    }
}
