<?php

declare(strict_types=1);

namespace App\Http\Controllers\Customer;

use App\Domain\Account\Models\Account;
use App\Domain\AppInstaller\Models\InstalledApp;
use App\Domain\Backup\Models\Backup;
use App\Domain\Database\Models\MysqlDatabase;
use App\Domain\Dns\Models\DnsZone;
use App\Domain\Domain\Enums\DomainStatus;
use App\Domain\Domain\Models\Domain;
use App\Domain\Email\Models\EmailAccount;
use App\Domain\Ftp\Models\FtpUser;
use App\Domain\Ssl\Models\SslCertificate;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Inertia\Inertia;
use Inertia\Response;

class DashboardController extends Controller
{
    public function index(Request $request): Response
    {
        /** @var Account $account */
        $account = $request->attributes->get('customer_account');
        $account->load('package');

        $domainsCount = Domain::where('account_id', $account->id)->count();
        $activeDomainsCount = Domain::where('account_id', $account->id)
            ->where('status', DomainStatus::Active)->count();
        $dbCount = MysqlDatabase::where('account_id', $account->id)->count();
        $ftpCount = FtpUser::where('account_id', $account->id)->count();
        $emailCount = EmailAccount::where('account_id', $account->id)->count();
        $sslCount = SslCertificate::whereHas('domain', fn ($q) => $q->where('account_id', $account->id))->count();
        $backupCount = Backup::where('account_id', $account->id)->count();
        $dnsZoneCount = DnsZone::where('account_id', $account->id)->count();
        $installedAppsCount = InstalledApp::where('account_id', $account->id)->whereNull('deleted_at')->count();
        $cronCount = DB::table('cron_jobs')->where('account_id', $account->id)->whereNull('deleted_at')->count();

        // SSL expiry alerts
        // Eager load domain — N+1 fix
        $expiringCerts = SslCertificate::with('domain:id,name')
            ->whereHas('domain', fn ($q) => $q->where('account_id', $account->id))
            ->where('expires_at', '<=', now()->addDays(30))
            ->where('expires_at', '>', now())
            ->orderBy('expires_at')
            ->take(5)
            ->get(['id', 'domain_id', 'expires_at'])
            ->map(fn ($c) => [
                'id' => $c->id,
                'domain' => $c->domain?->name,
                'expires_at' => $c->expires_at->format('d.m.Y'),
                'days_left' => now()->diffInDays($c->expires_at, false),
            ]);

        $latestBackups = Backup::where('account_id', $account->id)
            ->latest()
            ->take(3)
            ->get()
            ->map(fn ($b) => [
                'id' => $b->id,
                'created_at' => $b->created_at->format('d.m.Y H:i'),
                'size' => $b->size_bytes,
                'type' => $b->type,
            ]);

        $diskUsagePercent = $account->diskUsagePercent();
        $diskBytes = $account->disk_usage_bytes;
        $diskTotal = $account->quota_bytes;

        return Inertia::render('Customer/Dashboard', [
            'account' => $this->presentAccount($account),
            'stats' => [
                'domains' => [
                    'total' => $domainsCount,
                    'active' => $activeDomainsCount,
                    'limit' => $account->package?->limit('addon_domain_count'),
                ],
                'databases' => [
                    'total' => $dbCount,
                    'limit' => $account->package?->limit('db_count'),
                ],
                'ftp' => [
                    'total' => $ftpCount,
                    'limit' => $account->package?->limit('ftp_account_count'),
                ],
                'email' => [
                    'total' => $emailCount,
                    'limit' => $account->package?->limit('email_account_count') ?? 0,
                ],
                'ssl' => [
                    'total' => $sslCount,
                ],
                'backups' => [
                    'total' => $backupCount,
                ],
                'dns_zones' => [
                    'total' => $dnsZoneCount,
                ],
                'apps' => [
                    'total' => $installedAppsCount,
                ],
                'cron' => [
                    'total' => $cronCount,
                ],
            ],
            'disk' => [
                'used_bytes' => $diskBytes,
                'total_bytes' => $diskTotal,
                'percent' => $diskUsagePercent,
                'used_human' => $this->humanBytes($diskBytes),
                'total_human' => $this->humanBytes($diskTotal),
            ],
            'recent_domains' => Domain::where('account_id', $account->id)
                ->latest()
                ->take(5)
                ->get()
                ->map(fn ($d) => [
                    'id' => $d->id,
                    'name' => $d->name,
                    'type_label' => $d->type->label(),
                    'status' => $d->status->value,
                    'status_label' => $d->status->label(),
                    'ssl_enabled' => $d->ssl_enabled,
                    'created_at' => $d->created_at->format('d.m.Y'),
                ]),
            'recent_apps' => InstalledApp::where('account_id', $account->id)
                ->with('domain:id,name')
                ->whereNull('deleted_at')
                ->latest()
                ->take(3)
                ->get()
                ->map(fn ($a) => [
                    'id' => $a->id,
                    'app_type' => $a->app_type,
                    'site_title' => $a->site_title,
                    'install_url' => $a->install_url,
                    'version' => $a->version,
                    'installed_at' => $a->installed_at?->format('d.m.Y'),
                ]),
            'expiring_certs' => $expiringCerts,
            'latest_backups' => $latestBackups,
            'next_actions' => $this->buildNextActions($account, [
                'ssl_count' => $sslCount,
                'backup_count' => $backupCount,
                'email_count' => $emailCount,
                'disk_percent' => $diskUsagePercent,
                'domains_count' => $domainsCount,
            ]),
            // Kendi audit_log entries (sadece bu hesabın owner_user_id = current user)
            'activity_feed' => DB::table('audit_log')
                ->where('user_id', auth()->id())
                ->orderByDesc('created_at')
                ->limit(10)
                ->get(['id', 'action', 'outcome', 'target_type', 'target_id', 'created_at'])
                ->map(fn ($a) => [
                    'id' => $a->id,
                    'action' => $a->action,
                    'outcome' => $a->outcome,
                    'target' => $a->target_type ? class_basename($a->target_type).' #'.$a->target_id : null,
                    'created_at' => \Carbon\Carbon::parse($a->created_at)->diffForHumans(),
                ]),
            'server_info' => [
                'panel_version' => 'ONOXSOFT v0.1.0-beta',
                'php_version' => PHP_VERSION,
                'server_software' => $request->server('SERVER_SOFTWARE') ?? 'Apache/2.4',
                'os' => php_uname('s').' '.php_uname('r'),
                'mysql_version' => $this->mysqlVersion(),
            ],
        ]);
    }

    private function presentAccount(Account $account): array
    {
        return [
            'id' => $account->id,
            'username' => $account->username,
            'email' => $account->email,
            'primary_domain' => $account->primary_domain,
            'status' => $account->status->value,
            'status_label' => $account->status->label(),
            'status_color' => $account->status->color(),
            'is_provisioned' => $account->isProvisioned(),
            'quota_bytes' => $account->quota_bytes,
            'disk_usage_bytes' => $account->disk_usage_bytes,
            'disk_usage_percent' => $account->diskUsagePercent(),
            'package' => $account->package ? [
                'name' => $account->package->name,
                'slug' => $account->package->slug,
                'limits' => $account->package->limits,
            ] : null,
            'created_at' => $account->created_at->format('d.m.Y'),
        ];
    }

    private function humanBytes(int $bytes): string
    {
        if ($bytes < 1024) {
            return $bytes.' B';
        }
        if ($bytes < 1024 ** 2) {
            return number_format($bytes / 1024, 1).' KB';
        }
        if ($bytes < 1024 ** 3) {
            return number_format($bytes / 1024 ** 2, 1).' MB';
        }

        return number_format($bytes / 1024 ** 3, 2).' GB';
    }

    /**
     * Hesap durumunu analiz edip 3-5 öneri döner.
     * UI'daki NextActions widget'ında listelenir.
     *
     * @param  array{ssl_count:int,backup_count:int,email_count:int,disk_percent:int,domains_count:int}  $stats
     * @return array<int, array{key:string, severity:string, title:string, detail:string, href:?string}>
     */
    private function buildNextActions(Account $account, array $stats): array
    {
        $actions = [];

        // 1) Yedek
        $lastBackup = Backup::where('account_id', $account->id)->latest()->first();
        if (! $lastBackup || $lastBackup->created_at->lt(now()->subDays(30))) {
            $actions[] = [
                'key' => 'backup',
                'severity' => 'warning',
                'title' => 'Yedek alın',
                'detail' => $lastBackup
                    ? 'Son yedek '.$lastBackup->created_at->diffForHumans().' alındı.'
                    : 'Henüz yedeğiniz yok — verilerinizi korumak için ilk yedeği alın.',
                'href' => route('customer.backups.index'),
            ];
        }

        // 2) SSL eksik domain
        if ($stats['domains_count'] > 0) {
            $sslMissing = Domain::where('account_id', $account->id)
                ->where('status', DomainStatus::Active)
                ->where(function ($q) {
                    $q->where('ssl_enabled', false)->orWhereNull('ssl_enabled');
                })
                ->count();
            if ($sslMissing > 0) {
                $actions[] = [
                    'key' => 'ssl_missing',
                    'severity' => 'warning',
                    'title' => $sslMissing.' domain SSL\'siz',
                    'detail' => 'Let\'s Encrypt ile ücretsiz SSL kurabilirsiniz.',
                    'href' => route('customer.ssl.index'),
                ];
            }
        }

        // 3) Disk kullanımı
        if ($stats['disk_percent'] >= 85) {
            $actions[] = [
                'key' => 'disk_high',
                'severity' => 'danger',
                'title' => 'Disk %'.$stats['disk_percent'].' dolu',
                'detail' => 'Kotanız doluyor — eski dosyaları temizleyin veya paketinizi yükseltin.',
                'href' => route('customer.disk-usage.index'),
            ];
        } elseif ($stats['disk_percent'] >= 70) {
            $actions[] = [
                'key' => 'disk_warn',
                'severity' => 'info',
                'title' => 'Disk %'.$stats['disk_percent'].' dolu',
                'detail' => 'Yakında kotanın dolacak — büyük dosyaları gözden geçirin.',
                'href' => route('customer.disk-usage.index'),
            ];
        }

        // 4) Email 2FA eksik (account düzeyinde 2FA bayrağı)
        if ($stats['email_count'] >= 3 && empty($account->two_factor_secret)) {
            $actions[] = [
                'key' => '2fa',
                'severity' => 'info',
                'title' => '2FA önerilir',
                'detail' => 'Hesabınızda '.$stats['email_count'].' email hesabı var — 2FA ile koruyun.',
                'href' => route('profile.edit'),
            ];
        }

        // 5) SSL bitiş yaklaşıyor (zaten expiring_certs ayrı, kısa metin)
        $expiringSoon = SslCertificate::whereHas('domain', fn ($q) => $q->where('account_id', $account->id))
            ->where('expires_at', '<=', now()->addDays(14))
            ->where('expires_at', '>', now())
            ->count();
        if ($expiringSoon > 0) {
            $actions[] = [
                'key' => 'ssl_expiring',
                'severity' => 'warning',
                'title' => $expiringSoon.' SSL sertifikası 14 gün içinde bitecek',
                'detail' => 'Otomatik yenileme aktif değilse manuel yenileyin.',
                'href' => route('customer.ssl.index'),
            ];
        }

        // 6) Domain eklemediyse onboarding hint
        if ($stats['domains_count'] === 0) {
            $actions[] = [
                'key' => 'onboarding_domain',
                'severity' => 'info',
                'title' => 'İlk alan adınızı ekleyin',
                'detail' => 'Hosting hesabınız aktif — ilk domaini ekleyerek sitenizi yayına alın.',
                'href' => route('customer.domains.index'),
            ];
        }

        return array_slice($actions, 0, 5);
    }

    private function mysqlVersion(): string
    {
        try {
            $result = DB::select('SELECT VERSION() as v');

            return $result[0]->v ?? 'MariaDB/MySQL';
        } catch (\Throwable) {
            return 'MariaDB/MySQL';
        }
    }
}
