<?php

namespace App\Services\System;

use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Schema;
use Throwable;
use App\Services\Integrations\Sdk\ApiSdkStatusService;

class SystemHealthCheckService
{
    /**
     * @return array<string, array<int, array<string, string>>>
     */
    public function groupedChecks(): array
    {
        return [
            'Çekirdek Sistem' => $this->coreChecks(),
            'Veritabanı / Migration' => $this->databaseChecks(),
            'Dosya Sistemi' => $this->filesystemChecks(),
            'Modül Sınıfları' => $this->classChecks(),
            'Rapor / Mail / Cron' => $this->operationsChecks(),
            'API Bağlantı Sağlığı' => $this->connectionChecks(),
            'Resmi API SDK Paketleri' => $this->sdkPackageChecks(),
            'PHP Extension Kontrolleri' => $this->sdkExtensionChecks(),
        ];
    }

    /**
     * @return array{ok:int, warning:int, error:int, info:int, total:int}
     */
    public function summary(): array
    {
        $summary = ['ok' => 0, 'warning' => 0, 'error' => 0, 'info' => 0, 'total' => 0];

        foreach ($this->groupedChecks() as $checks) {
            foreach ($checks as $check) {
                $status = $check['status'] ?? 'info';
                $summary[$status] = ($summary[$status] ?? 0) + 1;
                $summary['total']++;
            }
        }

        return $summary;
    }


    /**
     * @return array<int, array<string, string>>
     */
    protected function sdkPackageChecks(): array
    {
        return collect(app(ApiSdkStatusService::class)->packages())
            ->map(fn (array $package) => [
                'status' => $package['status'] ? 'ok' : 'warning',
                'title' => $package['name'],
                'message' => ($package['status'] ? 'Kurulu: ' : 'Eksik: ').$package['package'],
                'hint' => $package['status'] ? ($package['notes'] ?? '') : ($package['install'] ?? 'Composer ile kurulmalı.'),
            ])
            ->all();
    }

    /**
     * @return array<int, array<string, string>>
     */
    protected function sdkExtensionChecks(): array
    {
        return collect(app(ApiSdkStatusService::class)->extensions())
            ->map(fn (array $extension) => [
                'status' => $extension['status'] ? 'ok' : (($extension['required'] ?? false) ? 'error' : 'info'),
                'title' => $extension['name'],
                'message' => ($extension['status'] ? 'Aktif: ' : 'Pasif: ').$extension['extension'],
                'hint' => $extension['notes'] ?? '',
            ])
            ->all();
    }

    /**
     * @return array<int, array<string, string>>
     */
    protected function coreChecks(): array
    {
        $checks = [];

        $checks[] = $this->make(
            version_compare(PHP_VERSION, '8.1.0', '>='),
            'PHP sürümü',
            'Aktif PHP: '.PHP_VERSION,
            'Laravel 10 için PHP 8.1+ gerekiyor.'
        );

        $checks[] = $this->make(
            filled(config('app.key')),
            'APP_KEY',
            filled(config('app.key')) ? 'APP_KEY tanımlı.' : 'APP_KEY boş görünüyor.',
            'php artisan key:generate çalıştırılmalı.'
        );

        $checks[] = $this->make(
            config('app.debug') === false,
            'Debug modu',
            config('app.debug') ? 'APP_DEBUG açık.' : 'APP_DEBUG kapalı.',
            'Canlı ortamda APP_DEBUG=false olmalı.',
            'warning'
        );

        $checks[] = [
            'status' => App::environment('production') ? 'ok' : 'info',
            'title' => 'Ortam',
            'message' => 'APP_ENV='.config('app.env'),
            'hint' => 'Canlı yayında production önerilir.',
        ];

        return $checks;
    }

    /**
     * @return array<int, array<string, string>>
     */
    protected function databaseChecks(): array
    {
        $checks = [];

        try {
            DB::connection()->getPdo();
            $checks[] = $this->ok('Veritabanı bağlantısı', 'DB bağlantısı başarılı.');
        } catch (Throwable $e) {
            $checks[] = $this->error('Veritabanı bağlantısı', 'DB bağlantısı kurulamadı.', $e->getMessage());
            return $checks;
        }

        $requiredTables = [
            'clients',
            'client_user',
            'platform_connections',
            'secure_credentials',
            'report_templates',
            'report_schedules',
            'generated_reports',
            'email_logs',
            'alert_rules',
            'alert_logs',
            'api_request_logs',
            'settings',
            'google_campaign_snapshots',
            'google_keyword_snapshots',
            'google_search_term_snapshots',
            'meta_campaign_snapshots',
            'meta_adset_snapshots',
            'meta_ad_snapshots',
            'search_console_query_snapshots',
            'search_console_page_snapshots',
            'ga4_traffic_snapshots',
        ];

        foreach ($requiredTables as $table) {
            $checks[] = $this->make(
                Schema::hasTable($table),
                $table,
                Schema::hasTable($table) ? 'Tablo mevcut.' : 'Tablo eksik.',
                'php artisan migrate komutunu çalıştır.'
            );
        }

        $columns = [
            'generated_reports' => ['html_path', 'csv_path', 'excel_path', 'pdf_path', 'ai_summary', 'ai_action_items'],
            'report_schedules' => ['last_run_at', 'next_run_at', 'recipients', 'include_pdf', 'include_excel'],
            'alert_rules' => ['platform', 'metric', 'operator', 'threshold_value', 'cooldown_minutes'],
            'client_user' => ['portal_enabled', 'portal_role', 'last_portal_login_at'],
        ];

        foreach ($columns as $table => $tableColumns) {
            if (! Schema::hasTable($table)) {
                continue;
            }

            foreach ($tableColumns as $column) {
                $checks[] = $this->make(
                    Schema::hasColumn($table, $column),
                    $table.'.'.$column,
                    Schema::hasColumn($table, $column) ? 'Kolon mevcut.' : 'Kolon eksik.',
                    'İlgili faz migration dosyası uygulanmalı.'
                );
            }
        }

        return $checks;
    }

    /**
     * @return array<int, array<string, string>>
     */
    protected function filesystemChecks(): array
    {
        $checks = [];

        $paths = [
            storage_path(),
            storage_path('app'),
            storage_path('app/public'),
            storage_path('framework'),
            storage_path('logs'),
            bootstrap_path('cache'),
        ];

        foreach ($paths as $path) {
            $checks[] = $this->make(
                is_dir($path) && is_writable($path),
                str_replace(base_path().'/', '', $path),
                is_dir($path) ? 'Klasör mevcut.' : 'Klasör eksik.',
                'Klasör yazılabilir olmalı.'
            );
        }

        $checks[] = $this->make(
            file_exists(public_path('storage')),
            'public/storage symlink',
            file_exists(public_path('storage')) ? 'Storage link mevcut.' : 'Storage link yok.',
            'php artisan storage:link çalıştır.'
        );

        return $checks;
    }

    /**
     * @return array<int, array<string, string>>
     */
    protected function classChecks(): array
    {
        $classes = [
            'DashboardController' => \App\Http\Controllers\Admin\DashboardController::class,
            'ClientController' => \App\Http\Controllers\Admin\ClientController::class,
            'ReportController' => \App\Http\Controllers\Admin\ReportController::class,
            'ReportScheduleController' => \App\Http\Controllers\Admin\ReportScheduleController::class,
            'AlertRuleController' => \App\Http\Controllers\Admin\AlertRuleController::class,
            'PortalDashboardController' => \App\Http\Controllers\Portal\PortalDashboardController::class,
            'PlatformConnectionTester' => \App\Services\Integrations\PlatformConnectionTester::class,
            'PlatformSyncManager' => \App\Services\Sync\PlatformSyncManager::class,
            'ReportGenerator' => \App\Services\Reports\ReportGenerator::class,
            'ReportMailer' => \App\Services\Mail\ReportMailer::class,
            'AlertEngine' => \App\Services\Alerts\AlertEngine::class,
            'ReportAiInsightGenerator' => \App\Services\Ai\ReportAiInsightGenerator::class,
        ];

        $checks = [];
        foreach ($classes as $label => $class) {
            $checks[] = $this->make(
                class_exists($class),
                $label,
                class_exists($class) ? 'Sınıf yüklendi.' : 'Sınıf bulunamadı.',
                'Patch dosyaları eksik kopyalanmış olabilir.'
            );
        }

        return $checks;
    }

    /**
     * @return array<int, array<string, string>>
     */
    protected function operationsChecks(): array
    {
        $checks = [];

        $checks[] = [
            'status' => config('queue.default') === 'sync' ? 'warning' : 'ok',
            'title' => 'Queue bağlantısı',
            'message' => 'QUEUE_CONNECTION='.config('queue.default'),
            'hint' => config('queue.default') === 'sync'
                ? 'Canlıda database/redis queue ve supervisor önerilir.'
                : 'Arka plan işleri için uygun.',
        ];

        $checks[] = [
            'status' => filled(config('mail.mailers.smtp.host')) ? 'ok' : 'warning',
            'title' => 'SMTP host',
            'message' => filled(config('mail.mailers.smtp.host')) ? config('mail.mailers.smtp.host') : 'SMTP host boş.',
            'hint' => 'Mail ayarları panelden kaydedildikten sonra test maili gönderilmeli.',
        ];

        $checks[] = [
            'status' => class_exists(\Barryvdh\DomPDF\Facade\Pdf::class) ? 'ok' : 'info',
            'title' => 'PDF motoru',
            'message' => class_exists(\Barryvdh\DomPDF\Facade\Pdf::class) ? 'DomPDF kurulu.' : 'DomPDF bulunamadı.',
            'hint' => 'PDF için composer require barryvdh/laravel-dompdf komutu çalıştırılabilir. HTML/XLS/CSV yine çalışır.',
        ];

        $commands = [
            'dw:sync-platform',
            'dw:generate-report',
            'dw:run-scheduled-reports',
            'dw:evaluate-alerts',
            'dw:generate-ai-insights',
            'dw:doctor',
            'dw:check-api-sdks',
        ];

        foreach ($commands as $command) {
            $checks[] = [
                'status' => 'info',
                'title' => 'Artisan komutu',
                'message' => $command,
                'hint' => 'php artisan '.$command.' ile manuel kontrol edilebilir.',
            ];
        }

        return $checks;
    }

    /**
     * @return array<int, array<string, string>>
     */
    protected function connectionChecks(): array
    {
        $checks = [];

        if (! Schema::hasTable('platform_connections')) {
            return [$this->warning('API bağlantıları', 'platform_connections tablosu yok.', 'Migration tamamlanmalı.')];
        }

        try {
            $total = DB::table('platform_connections')->count();
            $active = Schema::hasColumn('platform_connections', 'is_active')
                ? DB::table('platform_connections')->where('is_active', true)->count()
                : $total;

            $checks[] = [
                'status' => $total > 0 ? 'ok' : 'info',
                'title' => 'API bağlantı sayısı',
                'message' => $total.' bağlantı, '.$active.' aktif kayıt.',
                'hint' => 'Müşteri hesapları eklendikçe burada bağlantı sağlığı izlenir.',
            ];

            if (Schema::hasColumn('platform_connections', 'last_error')) {
                $withErrors = DB::table('platform_connections')
                    ->whereNotNull('last_error')
                    ->where('last_error', '!=', '')
                    ->count();

                $checks[] = [
                    'status' => $withErrors > 0 ? 'warning' : 'ok',
                    'title' => 'Bağlantı hata kayıtları',
                    'message' => $withErrors.' bağlantıda son hata kaydı var.',
                    'hint' => 'Hatalı bağlantılarda Bağlantıyı Test Et butonu kullanılmalı.',
                ];
            }
        } catch (Throwable $e) {
            $checks[] = $this->warning('API bağlantıları', 'Bağlantı özetleri okunamadı.', $e->getMessage());
        }

        if (Schema::hasTable('api_request_logs')) {
            try {
                $recentErrors = DB::table('api_request_logs')
                    ->when(Schema::hasColumn('api_request_logs', 'created_at'), fn ($query) => $query->where('created_at', '>=', now()->subDay()))
                    ->when(Schema::hasColumn('api_request_logs', 'status'), fn ($query) => $query->where('status', 'error'))
                    ->count();

                $checks[] = [
                    'status' => $recentErrors > 0 ? 'warning' : 'ok',
                    'title' => 'Son 24 saat API hatası',
                    'message' => $recentErrors.' hata kaydı.',
                    'hint' => 'Log ekranından detay incelenmeli.',
                ];
            } catch (Throwable $e) {
                $checks[] = $this->warning('API log kontrolü', 'API logları okunamadı.', $e->getMessage());
            }
        }

        return $checks;
    }

    protected function make(bool $condition, string $title, string $okMessage, string $hint, string $failureStatus = 'error'): array
    {
        return [
            'status' => $condition ? 'ok' : $failureStatus,
            'title' => $title,
            'message' => $condition ? $okMessage : $okMessage,
            'hint' => $condition ? '' : $hint,
        ];
    }

    protected function ok(string $title, string $message, string $hint = ''): array
    {
        return ['status' => 'ok', 'title' => $title, 'message' => $message, 'hint' => $hint];
    }

    protected function warning(string $title, string $message, string $hint = ''): array
    {
        return ['status' => 'warning', 'title' => $title, 'message' => $message, 'hint' => $hint];
    }

    protected function error(string $title, string $message, string $hint = ''): array
    {
        return ['status' => 'error', 'title' => $title, 'message' => $message, 'hint' => $hint];
    }
}
