<?php

namespace App\Services\Operations;

use App\Models\AlertLog;
use App\Models\ApiRequestLog;
use App\Models\Client;
use App\Models\EmailLog;
use App\Models\GeneratedReport;
use App\Models\OperationTask;
use App\Models\PlatformConnection;
use App\Models\ReportSchedule;
use Carbon\Carbon;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Schema;

class OperationCenterService
{
    public function dashboard(array $filters = []): array
    {
        $clients = $this->filteredClients($filters)
            ->with(['platformConnections', 'generatedReports', 'reportSchedules', 'alertLogs'])
            ->orderBy('company_name')
            ->get();

        $cards = $clients->map(fn (Client $client) => $this->clientCard($client));

        if (! empty($filters['readiness'])) {
            $cards = $cards->filter(fn (array $card) => $card['readiness'] === $filters['readiness'])->values();
        }

        $summary = [
            'clients_total' => $clients->count(),
            'ready' => $cards->where('readiness', 'ready')->count(),
            'warning' => $cards->where('readiness', 'warning')->count(),
            'critical' => $cards->where('readiness', 'critical')->count(),
            'needs_first_report' => $cards->where('needs_first_report', true)->count(),
            'open_alerts' => (int) AlertLog::query()->where(function ($query) {
                $query->whereNull('resolved_at');
                if (Schema::hasColumn('alert_logs', 'status')) {
                    $query->where('status', '!=', 'resolved');
                }
            })->count(),
            'failed_mails_24h' => (int) EmailLog::query()
                ->where('status', 'failed')
                ->where('created_at', '>=', now()->subDay())
                ->count(),
            'api_errors_24h' => (int) ApiRequestLog::query()
                ->whereNotNull('error_message')
                ->where('created_at', '>=', now()->subDay())
                ->count(),
            'open_manual_tasks' => Schema::hasTable('operation_tasks') ? (int) OperationTask::open()->count() : 0,
        ];

        return [
            'summary' => $summary,
            'clients' => $cards,
            'critical_items' => $cards->filter(fn (array $card) => $card['readiness'] === 'critical')->take(10)->values(),
            'upcoming_reports' => $this->upcomingReports(),
            'recent_mail_failures' => $this->recentMailFailures(),
            'recent_api_errors' => $this->recentApiErrors(),
            'manual_tasks' => $this->manualTasks(),
        ];
    }

    public function clientDetail(Client $client): array
    {
        $client->load(['platformConnections', 'generatedReports', 'reportSchedules', 'alertLogs']);

        return [
            'client' => $client,
            'card' => $this->clientCard($client),
            'connections' => $client->platformConnections()->orderBy('platform')->get()->map(fn (PlatformConnection $connection) => [
                'model' => $connection,
                'status_label' => $this->connectionStatusLabel($connection->status),
                'quality' => $this->extractQuality($connection),
                'last_error' => $connection->last_error,
                'last_api_error' => ApiRequestLog::where('client_id', $client->id)
                    ->where('platform', $connection->platform)
                    ->whereNotNull('error_message')
                    ->latest('created_at')
                    ->first(),
            ]),
            'reports' => GeneratedReport::where('client_id', $client->id)->latest()->limit(10)->get(),
            'schedules' => ReportSchedule::where('client_id', $client->id)->orderBy('next_run_at')->get(),
            'alerts' => AlertLog::where('client_id', $client->id)->latest('triggered_at')->latest()->limit(20)->get(),
            'emails' => EmailLog::where('client_id', $client->id)->latest()->limit(20)->get(),
            'api_errors' => ApiRequestLog::where('client_id', $client->id)->whereNotNull('error_message')->latest()->limit(20)->get(),
            'manual_tasks' => Schema::hasTable('operation_tasks')
                ? OperationTask::where('client_id', $client->id)->latest()->limit(20)->get()
                : collect(),
        ];
    }

    public function clientCard(Client $client): array
    {
        $connections = $client->platformConnections instanceof Collection
            ? $client->platformConnections
            : $client->platformConnections()->get();

        $reports = $client->generatedReports instanceof Collection
            ? $client->generatedReports
            : $client->generatedReports()->get();

        $schedules = $client->reportSchedules instanceof Collection
            ? $client->reportSchedules
            : $client->reportSchedules()->get();

        $alerts = $client->alertLogs instanceof Collection
            ? $client->alertLogs
            : $client->alertLogs()->get();

        $openAlerts = $alerts->filter(function ($alert) {
            if (isset($alert->status) && $alert->status === 'resolved') {
                return false;
            }

            return $alert->resolved_at === null;
        });

        $criticalAlerts = $openAlerts->whereIn('severity', ['critical', 'danger', 'high'])->count();
        $activeSchedules = $schedules->where('is_active', true)->count();
        $lastReport = $reports->sortByDesc('created_at')->first();
        $lastSentReport = $reports->filter(fn ($report) => $report->sent_at !== null)->sortByDesc('sent_at')->first();
        $failedReports = $reports->whereIn('status', ['failed', 'error'])->count();
        $failedMail = EmailLog::where('client_id', $client->id)->where('status', 'failed')->latest()->first();
        $latestApiError = ApiRequestLog::where('client_id', $client->id)->whereNotNull('error_message')->latest()->first();
        $connectionProblems = $connections->filter(fn ($connection) => $this->connectionHasProblem($connection));
        $qualityScores = $connections->map(fn ($connection) => $this->extractQuality($connection)['score'])->filter(fn ($score) => $score !== null);
        $avgQuality = $qualityScores->count() ? round($qualityScores->avg()) : null;
        $lastSyncAt = $connections->pluck('last_sync_at')->filter()->max();
        $needsFirstReport = $reports->count() === 0 || $lastReport === null;

        $actions = $this->buildActionItems(
            client: $client,
            connections: $connections,
            activeSchedules: $activeSchedules,
            needsFirstReport: $needsFirstReport,
            criticalAlerts: $criticalAlerts,
            openAlertsCount: $openAlerts->count(),
            avgQuality: $avgQuality,
            latestApiError: $latestApiError,
            failedMail: $failedMail,
            failedReports: $failedReports
        );

        $readiness = $this->readinessFromActions($actions);

        return [
            'client' => $client,
            'readiness' => $readiness,
            'readiness_label' => $this->readinessLabel($readiness),
            'badge_class' => $this->readinessBadgeClass($readiness),
            'connections_total' => $connections->count(),
            'connections_active' => $connections->where('status', 'active')->count(),
            'connection_problems' => $connectionProblems->count(),
            'platforms' => $connections->pluck('platform')->unique()->values()->all(),
            'avg_quality' => $avgQuality,
            'last_sync_at' => $lastSyncAt,
            'last_report' => $lastReport,
            'last_sent_report' => $lastSentReport,
            'active_schedules' => $activeSchedules,
            'open_alerts' => $openAlerts->count(),
            'critical_alerts' => $criticalAlerts,
            'failed_reports' => $failedReports,
            'failed_mail' => $failedMail,
            'latest_api_error' => $latestApiError,
            'needs_first_report' => $needsFirstReport,
            'actions' => $actions,
            'manual_open_tasks' => Schema::hasTable('operation_tasks')
                ? OperationTask::where('client_id', $client->id)->open()->count()
                : 0,
        ];
    }

    protected function filteredClients(array $filters)
    {
        return Client::query()
            ->when(! empty($filters['q']), function ($query) use ($filters) {
                $term = '%'.trim($filters['q']).'%';
                $query->where(function ($sub) use ($term) {
                    $sub->where('company_name', 'like', $term)
                        ->orWhere('contact_person', 'like', $term)
                        ->orWhere('email', 'like', $term)
                        ->orWhere('website', 'like', $term);
                });
            })
            ->when(! empty($filters['platform']), function ($query) use ($filters) {
                $query->whereHas('platformConnections', fn ($sub) => $sub->where('platform', $filters['platform']));
            })
            ->when(! empty($filters['status']), fn ($query) => $query->where('status', $filters['status']));
    }

    protected function buildActionItems(
        Client $client,
        Collection $connections,
        int $activeSchedules,
        bool $needsFirstReport,
        int $criticalAlerts,
        int $openAlertsCount,
        ?int $avgQuality,
        ?ApiRequestLog $latestApiError,
        ?EmailLog $failedMail,
        int $failedReports
    ): array {
        $items = [];

        if ($client->status !== 'active') {
            $items[] = $this->action('Müşteri pasif durumda', 'Müşteri aktif değilse otomatik rapor ve takip akışı aksayabilir.', 'medium', 'client');
        }

        if (method_exists($client, 'onboardingIsComplete') && ! $client->onboardingIsComplete()) {
            $items[] = $this->action('Onboarding tamamlanmamış', 'Müşteri kurulum adımlarını tamamlayıp ilk rapor sürecine geçin.', 'high', 'onboarding', route('admin.onboarding.summary', $client));
        }

        if ($connections->count() === 0) {
            $items[] = $this->action('API bağlantısı yok', 'Google Ads, Meta, Search Console veya GA4 bağlantısı eklenmeli.', 'critical', 'connection', route('admin.onboarding.integrations', $client));
        }

        foreach ($connections as $connection) {
            if ($this->connectionHasProblem($connection)) {
                $items[] = $this->action(
                    $this->platformLabel($connection->platform).' bağlantısı kontrol istiyor',
                    $connection->last_error ?: 'Bağlantı durumu aktif değil veya son kontrolde sorun görünüyor.',
                    'critical',
                    'connection',
                    $this->connectionUrl($connection)
                );
            }
        }

        if ($avgQuality !== null && $avgQuality < 70) {
            $items[] = $this->action('Veri kalite skoru düşük', 'Ortalama kalite skoru '.$avgQuality.'. Eksik gün veya boş metrik kontrol edilmeli.', 'high', 'quality', route('admin.sync.quality', ['client_id' => $client->id]));
        }

        if ($activeSchedules === 0) {
            $items[] = $this->action('Otomatik rapor planı yok', 'Günlük, haftalık veya aylık rapor planı oluşturulmalı.', 'medium', 'schedule', route('admin.report-schedules.create', ['client_id' => $client->id]));
        }

        if ($needsFirstReport) {
            $items[] = $this->action('İlk rapor bekliyor', 'Müşteri için ilk rapor sihirbazı çalıştırılmalı.', 'high', 'first_report', route('admin.first-report.show', $client));
        }

        if ($criticalAlerts > 0) {
            $items[] = $this->action('Kritik uyarı var', $criticalAlerts.' kritik uyarı çözüm bekliyor.', 'critical', 'alert', route('admin.alert-logs.index', ['client_id' => $client->id]));
        } elseif ($openAlertsCount > 0) {
            $items[] = $this->action('Açık uyarılar var', $openAlertsCount.' uyarı takip edilmeli.', 'medium', 'alert', route('admin.alert-logs.index', ['client_id' => $client->id]));
        }

        if ($latestApiError) {
            $items[] = $this->action('Son API hatası var', str($latestApiError->error_message)->limit(180)->toString(), 'high', 'api', route('admin.system.logs'));
        }

        if ($failedMail) {
            $items[] = $this->action('Mail gönderim hatası var', str($failedMail->error_message ?: 'Son mail başarısız oldu.')->limit(180)->toString(), 'high', 'mail', route('admin.mail.logs'));
        }

        if ($failedReports > 0) {
            $items[] = $this->action('Başarısız rapor var', $failedReports.' rapor hata durumunda. Rapor arşivinden kontrol edilmeli.', 'medium', 'report', route('admin.reports.archive', ['client_id' => $client->id]));
        }

        return $items;
    }

    protected function action(string $title, string $description, string $priority, string $category, ?string $url = null): array
    {
        return compact('title', 'description', 'priority', 'category', 'url');
    }

    protected function readinessFromActions(array $actions): string
    {
        $priorities = collect($actions)->pluck('priority');

        if ($priorities->contains('critical')) {
            return 'critical';
        }

        if ($priorities->contains('high') || $priorities->contains('medium')) {
            return 'warning';
        }

        return 'ready';
    }

    protected function readinessLabel(string $readiness): string
    {
        return match ($readiness) {
            'ready' => 'Hazır',
            'warning' => 'Kontrol Gerekli',
            'critical' => 'Kritik',
            default => 'Bilinmiyor',
        };
    }

    protected function readinessBadgeClass(string $readiness): string
    {
        return match ($readiness) {
            'ready' => 'badge-success',
            'warning' => 'badge-warning',
            'critical' => 'badge-danger',
            default => 'badge-secondary',
        };
    }

    protected function connectionHasProblem(PlatformConnection $connection): bool
    {
        if (filled($connection->last_error)) {
            return true;
        }

        return in_array($connection->status, ['error', 'failed', 'expired', 'revoked', 'inactive'], true);
    }

    protected function extractQuality(PlatformConnection $connection): array
    {
        $meta = $connection->meta ?? [];
        $quality = $meta['last_quality'] ?? $meta['quality'] ?? null;

        if (! is_array($quality)) {
            return ['status' => null, 'score' => null, 'checked_at' => null];
        }

        return [
            'status' => $quality['status'] ?? $quality['readiness'] ?? null,
            'score' => isset($quality['score']) ? (int) $quality['score'] : null,
            'checked_at' => $quality['checked_at'] ?? $quality['created_at'] ?? null,
        ];
    }

    protected function upcomingReports(): Collection
    {
        return ReportSchedule::with('client')
            ->where('is_active', true)
            ->whereNotNull('next_run_at')
            ->where('next_run_at', '>=', now()->subHour())
            ->orderBy('next_run_at')
            ->limit(12)
            ->get();
    }

    protected function recentMailFailures(): Collection
    {
        return EmailLog::with('client')
            ->where('status', 'failed')
            ->latest()
            ->limit(8)
            ->get();
    }

    protected function recentApiErrors(): Collection
    {
        return ApiRequestLog::with('client')
            ->whereNotNull('error_message')
            ->latest()
            ->limit(8)
            ->get();
    }

    protected function manualTasks(): Collection
    {
        if (! Schema::hasTable('operation_tasks')) {
            return collect();
        }

        return OperationTask::with(['client', 'assignee'])
            ->open()
            ->orderByRaw("FIELD(priority, 'critical', 'high', 'medium', 'low')")
            ->latest()
            ->limit(12)
            ->get();
    }

    public function platformLabel(?string $platform): string
    {
        return match ($platform) {
            'google_ads' => 'Google Ads',
            'meta_ads' => 'Meta Ads',
            'search_console' => 'Search Console',
            'ga4' => 'GA4',
            default => $platform ? str_replace('_', ' ', ucfirst($platform)) : 'Platform',
        };
    }

    protected function connectionStatusLabel(?string $status): string
    {
        return match ($status) {
            'active' => 'Aktif',
            'draft' => 'Taslak',
            'error' => 'Hatalı',
            'failed' => 'Başarısız',
            'inactive' => 'Pasif',
            default => $status ?: 'Bilinmiyor',
        };
    }

    protected function connectionUrl(PlatformConnection $connection): ?string
    {
        return match ($connection->platform) {
            'google_ads' => route('admin.accounts.google-ads.show', $connection),
            'meta_ads' => route('admin.accounts.meta-ads.show', $connection),
            'search_console' => route('admin.accounts.search-console.show', $connection),
            'ga4' => route('admin.accounts.ga4.show', $connection),
            default => null,
        };
    }
}
