<?php

declare(strict_types=1);

namespace App\Http\Controllers\Admin;

use App\Domain\Account\Models\Account;
use App\Domain\Email\Models\EmailAccount;
use App\Domain\Email\Models\EmailAutoresponder;
use App\Domain\Email\Models\EmailForwarder;
use App\Domain\MailLogs\Services\MailboxActivityParser;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Schema;
use Inertia\Inertia;
use Inertia\Response;

/**
 * Mail Storage Report — Admin operasyonel rapor.
 *
 * 4 view:
 *  - Overview (top stats + domain breakdown)
 *  - All accounts (paginated, search, sort, filter)
 *  - Near quota (>= 80% kullanım — uyarı listesi)
 *  - By customer (per-hosting-account aggregat)
 */
class MailStorageController extends Controller
{
    public function index(Request $request): Response
    {
        if (! Schema::hasTable('email_accounts')) {
            return Inertia::render('Admin/Mail/Storage', [
                'overview' => $this->emptyOverview(),
                'accounts' => collect(),
                'near_quota' => collect(),
                'by_customer' => collect(),
                'filters' => $this->emptyFilters($request),
                'is_windows_dev' => PHP_OS_FAMILY === 'Windows',
            ]);
        }

        $filters = [
            'search' => $request->string('search')->trim()->value(),
            'sort' => $request->string('sort')->value() ?: 'usage_desc',
            'domain' => $request->string('domain')->value(),
            'status' => $request->string('status')->value(),
        ];

        return Inertia::render('Admin/Mail/Storage', [
            'overview' => $this->buildOverview(),
            'accounts' => $this->buildAccountList($filters),
            'near_quota' => $this->buildNearQuota(),
            'by_customer' => $this->buildByCustomer(),
            'available_domains' => EmailAccount::query()
                ->whereNull('deleted_at')
                ->groupBy('domain')
                ->pluck('domain')
                ->all(),
            'filters' => $filters,
            'is_windows_dev' => PHP_OS_FAMILY === 'Windows',
        ]);
    }

    private function buildOverview(): array
    {
        $totals = EmailAccount::query()
            ->whereNull('deleted_at')
            ->selectRaw('
                count(*) as total_accounts,
                count(distinct domain) as total_domains,
                count(distinct account_id) as total_customers,
                sum(usage_bytes) as total_usage_bytes,
                sum(quota_mb) as total_quota_mb,
                avg(usage_bytes) as avg_usage_bytes,
                max(usage_bytes) as max_usage_bytes
            ')
            ->first();

        $totalQuotaBytes = (int) (($totals->total_quota_mb ?? 0) * 1024 * 1024);
        $totalUsage = (int) ($totals->total_usage_bytes ?? 0);
        $usagePercent = $totalQuotaBytes > 0 ? round(($totalUsage / $totalQuotaBytes) * 100, 1) : 0;

        // Status dağılımı
        $byStatus = EmailAccount::query()
            ->whereNull('deleted_at')
            ->select('status', DB::raw('count(*) as count'))
            ->groupBy('status')
            ->get()
            ->mapWithKeys(fn ($r) => [$r->status => $r->count])
            ->toArray();

        // Domain dağılımı (top 10)
        $byDomain = EmailAccount::query()
            ->whereNull('deleted_at')
            ->selectRaw('domain, count(*) as count, sum(usage_bytes) as usage_bytes, sum(quota_mb) as quota_mb')
            ->groupBy('domain')
            ->orderByDesc('usage_bytes')
            ->limit(10)
            ->get()
            ->map(fn ($r) => [
                'domain' => $r->domain,
                'count' => (int) $r->count,
                'usage_bytes' => (int) $r->usage_bytes,
                'usage_mb' => round(($r->usage_bytes ?? 0) / 1024 / 1024, 1),
                'quota_mb' => (int) ($r->quota_mb ?? 0),
                'usage_percent' => $r->quota_mb > 0
                    ? round((($r->usage_bytes / 1024 / 1024) / $r->quota_mb) * 100, 1)
                    : 0,
            ]);

        return [
            'total_accounts' => (int) ($totals->total_accounts ?? 0),
            'total_domains' => (int) ($totals->total_domains ?? 0),
            'total_customers' => (int) ($totals->total_customers ?? 0),
            'total_usage_bytes' => $totalUsage,
            'total_usage_mb' => round($totalUsage / 1024 / 1024, 1),
            'total_usage_gb' => round($totalUsage / 1024 / 1024 / 1024, 2),
            'total_quota_mb' => (int) ($totals->total_quota_mb ?? 0),
            'usage_percent' => $usagePercent,
            'avg_usage_mb' => round(($totals->avg_usage_bytes ?? 0) / 1024 / 1024, 1),
            'max_usage_mb' => round(($totals->max_usage_bytes ?? 0) / 1024 / 1024, 1),
            'by_status' => $byStatus,
            'by_domain' => $byDomain,
        ];
    }

    private function buildAccountList(array $filters): \Illuminate\Contracts\Pagination\LengthAwarePaginator
    {
        $query = EmailAccount::query()
            ->whereNull('email_accounts.deleted_at')
            ->with(['account:id,username,email,owner_user_id', 'account.owner:id,name,email']);

        if ($search = $filters['search']) {
            $query->where(function ($q) use ($search) {
                $q->where('local', 'like', "%{$search}%")
                    ->orWhere('domain', 'like', "%{$search}%");
            });
        }
        if ($domain = $filters['domain']) {
            $query->where('domain', $domain);
        }
        if ($status = $filters['status']) {
            $query->where('status', $status);
        }

        match ($filters['sort']) {
            'usage_asc' => $query->orderBy('usage_bytes', 'asc'),
            'quota_desc' => $query->orderBy('quota_mb', 'desc'),
            'name' => $query->orderBy('domain')->orderBy('local'),
            'recent' => $query->orderByDesc('created_at'),
            default => $query->orderByDesc('usage_bytes'),
        };

        return $query->paginate(25)->withQueryString()->through(fn ($e) => [
            'id' => $e->id,
            'email' => $e->email,
            'local' => $e->local,
            'domain' => $e->domain,
            'usage_bytes' => (int) $e->usage_bytes,
            'usage_mb' => round(($e->usage_bytes ?? 0) / 1024 / 1024, 2),
            'quota_mb' => (int) $e->quota_mb,
            'usage_percent' => $e->quota_mb > 0
                ? round((($e->usage_bytes / 1024 / 1024) / $e->quota_mb) * 100, 1)
                : 0,
            'status' => $e->status,
            'account_username' => $e->account?->username,
            'owner_name' => $e->account?->owner?->name ?? $e->account?->owner?->email,
            'created_at' => $e->created_at?->format('d.m.Y'),
        ]);
    }

    private function buildNearQuota(): \Illuminate\Support\Collection
    {
        // >= 80% kullanım
        return EmailAccount::query()
            ->whereNull('deleted_at')
            ->where('quota_mb', '>', 0)
            ->whereRaw('(usage_bytes / 1024 / 1024 / quota_mb) >= 0.8')
            ->with('account:id,username,email')
            ->orderByRaw('(usage_bytes / 1024 / 1024 / quota_mb) DESC')
            ->limit(20)
            ->get()
            ->map(fn ($e) => [
                'id' => $e->id,
                'email' => $e->email,
                'usage_mb' => round(($e->usage_bytes ?? 0) / 1024 / 1024, 2),
                'quota_mb' => (int) $e->quota_mb,
                'usage_percent' => round((($e->usage_bytes / 1024 / 1024) / $e->quota_mb) * 100, 1),
                'account_username' => $e->account?->username,
            ]);
    }

    private function buildByCustomer(): \Illuminate\Support\Collection
    {
        // Customer (hosting hesabı) bazlı agregasyon — top 10
        return DB::table('email_accounts')
            ->whereNull('email_accounts.deleted_at')
            ->join('accounts', 'accounts.id', '=', 'email_accounts.account_id')
            ->selectRaw('
                accounts.id as account_id,
                accounts.username,
                accounts.email as account_email,
                count(email_accounts.id) as mailbox_count,
                sum(email_accounts.usage_bytes) as total_usage_bytes,
                sum(email_accounts.quota_mb) as total_quota_mb
            ')
            ->groupBy('accounts.id', 'accounts.username', 'accounts.email')
            ->orderByDesc('total_usage_bytes')
            ->limit(10)
            ->get()
            ->map(fn ($r) => [
                'account_id' => $r->account_id,
                'username' => $r->username,
                'email' => $r->account_email,
                'mailbox_count' => (int) $r->mailbox_count,
                'usage_mb' => round(($r->total_usage_bytes ?? 0) / 1024 / 1024, 2),
                'quota_mb' => (int) $r->total_quota_mb,
                'usage_percent' => $r->total_quota_mb > 0
                    ? round((($r->total_usage_bytes / 1024 / 1024) / $r->total_quota_mb) * 100, 1)
                    : 0,
            ]);
    }

    /**
     * Per-mailbox detail — admin drilldown sayfası.
     */
    public function show(int $id): Response
    {
        $email = EmailAccount::query()
            ->whereNull('email_accounts.deleted_at')
            ->with(['account:id,username,email,owner_user_id', 'account.owner:id,name,email'])
            ->findOrFail($id);

        $forwarders = Schema::hasTable('email_forwarders')
            ? EmailForwarder::where('source', $email->email)
                ->orWhere('source', $email->local . '@' . $email->domain)
                ->get(['id', 'source', 'destinations', 'keep_local_copy', 'created_at'])
            : collect();

        $autoresponders = Schema::hasTable('email_autoresponders')
            ? EmailAutoresponder::where('email_account_id', $email->id)
                ->get(['id', 'subject', 'body', 'starts_at', 'ends_at', 'active'])
            : collect();

        // Domain bazlı stats
        $domainStats = EmailAccount::query()
            ->whereNull('deleted_at')
            ->where('domain', $email->domain)
            ->selectRaw('count(*) as count, sum(usage_bytes) as usage, sum(quota_mb) as quota')
            ->first();

        return Inertia::render('Admin/Mail/MailboxDetail', [
            'mailbox' => [
                'id' => $email->id,
                'email' => $email->email,
                'local' => $email->local,
                'domain' => $email->domain,
                'usage_bytes' => (int) $email->usage_bytes,
                'usage_mb' => round(($email->usage_bytes ?? 0) / 1024 / 1024, 2),
                'usage_gb' => round(($email->usage_bytes ?? 0) / 1024 / 1024 / 1024, 3),
                'quota_mb' => (int) $email->quota_mb,
                'usage_percent' => $email->quota_mb > 0
                    ? round((($email->usage_bytes / 1024 / 1024) / $email->quota_mb) * 100, 1)
                    : 0,
                'status' => $email->status,
                'auto_create_dirs' => (bool) $email->auto_create_dirs,
                'account_id' => $email->account_id,
                'account_username' => $email->account?->username,
                'account_email' => $email->account?->email,
                'owner_name' => $email->account?->owner?->name ?? $email->account?->owner?->email,
                'created_at' => $email->created_at?->toIso8601String(),
                'created_at_human' => $email->created_at?->diffForHumans(),
                'updated_at' => $email->updated_at?->toIso8601String(),
            ],
            'forwarders' => $forwarders,
            'autoresponders' => $autoresponders,
            'domain_stats' => $domainStats ? [
                'count' => (int) $domainStats->count,
                'usage_mb' => round(($domainStats->usage ?? 0) / 1024 / 1024, 1),
                'quota_mb' => (int) $domainStats->quota,
            ] : null,
            'connect_info' => [
                'imap_host' => 'mail.' . preg_replace('/^[^.]+\./', '', parse_url(config('app.url'), PHP_URL_HOST) ?? 'example.com'),
                'imap_port_ssl' => 993,
                'imap_port_starttls' => 143,
                'smtp_port_ssl' => 465,
                'smtp_port_starttls' => 587,
                'pop3_port_ssl' => 995,
            ],
            'is_windows_dev' => PHP_OS_FAMILY === 'Windows',
        ]);
    }

    /**
     * Mailbox quota güncelleme (admin override).
     */
    public function updateQuota(Request $request, int $id): RedirectResponse
    {
        $data = $request->validate([
            'quota_mb' => 'required|integer|min:0|max:1048576',  // max 1TB
        ]);

        $email = EmailAccount::findOrFail($id);
        $email->update(['quota_mb' => $data['quota_mb']]);

        return back()->with('success', "Quota güncellendi: {$data['quota_mb']} MB");
    }

    /**
     * Mailbox status değiştir (active/suspended).
     */
    public function toggleStatus(int $id): RedirectResponse
    {
        $email = EmailAccount::findOrFail($id);
        $newStatus = $email->status === 'active' ? 'suspended' : 'active';
        $email->update(['status' => $newStatus]);

        $label = $newStatus === 'active' ? 'aktive edildi' : 'askıya alındı';

        return back()->with('success', "Mailbox {$email->email} {$label}");
    }

    /**
     * Password reset — yeni rastgele parola üretip set eder, admin'e gösterir.
     */
    public function resetPassword(int $id): RedirectResponse
    {
        $email = EmailAccount::findOrFail($id);

        $newPassword = $this->generateRandomPassword();
        $email->update(['password_hash' => Hash::make($newPassword)]);

        return back()
            ->with('success', "Parola sıfırlandı: {$newPassword}")
            ->with('new_password', $newPassword);
    }

    /**
     * Per-mailbox activity log — Postfix/Dovecot syslog parse edip timeline döner.
     */
    public function activity(int $id, MailboxActivityParser $parser): Response
    {
        $email = EmailAccount::query()
            ->whereNull('email_accounts.deleted_at')
            ->findOrFail($id);

        $activity = $parser->getActivity($email->email, limit: 100);

        return Inertia::render('Admin/Mail/MailboxActivity', [
            'mailbox' => [
                'id' => $email->id,
                'email' => $email->email,
                'local' => $email->local,
                'domain' => $email->domain,
                'status' => $email->status,
            ],
            'events' => $activity['events'],
            'stats' => $activity['stats'],
            'is_windows_dev' => PHP_OS_FAMILY === 'Windows',
        ]);
    }

    private function generateRandomPassword(int $length = 16): string
    {
        $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%';
        $password = '';
        for ($i = 0; $i < $length; $i++) {
            $password .= $chars[random_int(0, strlen($chars) - 1)];
        }

        return $password;
    }

    private function emptyOverview(): array
    {
        return [
            'total_accounts' => 0,
            'total_domains' => 0,
            'total_customers' => 0,
            'total_usage_bytes' => 0,
            'total_usage_mb' => 0,
            'total_usage_gb' => 0,
            'total_quota_mb' => 0,
            'usage_percent' => 0,
            'avg_usage_mb' => 0,
            'max_usage_mb' => 0,
            'by_status' => [],
            'by_domain' => [],
        ];
    }

    private function emptyFilters(Request $request): array
    {
        return [
            'search' => '',
            'sort' => 'usage_desc',
            'domain' => '',
            'status' => '',
        ];
    }
}
