<?php

declare(strict_types=1);

namespace App\Http\Controllers\Admin;

use App\Domain\Cron\Services\CronExpressionValidator;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Inertia\Inertia;
use Inertia\Response;

/**
 * Admin Cron Audit — WHM "Cron Jobs" sayfasının cross-account muadili (Phase 2).
 *
 * Sorumluluk:
 *  - Tüm hesapların tüm cron_jobs satırlarını listele
 *  - Her cron için syntax validation (CronExpressionValidator)
 *  - Command için suspicious pattern detection (xmrig, curl|bash, reverse shell)
 *  - Per-account / per-status filter, search
 *  - Bulk disable (örn. tüm "broken" cron'ları toplu kapat)
 *  - last_run_at + exit_code görünür — kaç gündür çalışmıyor?
 */
class CronAuditController extends Controller
{
    public function __construct(private readonly CronExpressionValidator $validator) {}

    public function index(Request $request): Response
    {
        if (! Schema::hasTable('cron_jobs')) {
            return Inertia::render('Admin/Cron/Audit', [
                'crons' => [],
                'summary' => ['total' => 0, 'active' => 0, 'broken' => 0, 'suspicious' => 0, 'never_run' => 0, 'stale' => 0],
                'filters' => $request->only(['search', 'status', 'account_id']),
                'no_table' => true,
            ]);
        }

        $query = DB::table('cron_jobs as c')
            ->join('accounts as a', 'a.id', '=', 'c.account_id')
            ->select(
                'c.id', 'c.account_id', 'c.label', 'c.expression', 'c.command',
                'c.is_active', 'c.last_run_at', 'c.last_exit_code', 'c.created_at',
                'a.username', 'a.primary_domain', 'a.status as account_status',
            )
            ->whereNull('c.deleted_at');

        // Filter — account
        if ($accountId = (int) $request->input('account_id')) {
            $query->where('c.account_id', $accountId);
        }

        // Filter — search
        if ($search = trim((string) $request->input('search', ''))) {
            $query->where(function ($q) use ($search) {
                $q->where('a.username', 'like', "%{$search}%")
                  ->orWhere('c.command', 'like', "%{$search}%")
                  ->orWhere('c.expression', 'like', "%{$search}%")
                  ->orWhere('c.label', 'like', "%{$search}%");
            });
        }

        $rows = $query->orderByDesc('c.id')->limit(2000)->get();

        // Her satıra validation + suspicious check
        $crons = $rows->map(function ($row): array {
            $exprResult = $this->validator->validate($row->expression);
            $cmdIssues = $this->validator->checkCommand($row->command ?? '');

            $now = now();
            $lastRun = $row->last_run_at ? \Carbon\Carbon::parse($row->last_run_at) : null;
            $stale = $row->is_active && $lastRun && $lastRun->lt($now->copy()->subDays(7));
            $neverRun = $row->is_active && $lastRun === null;

            return [
                'id' => $row->id,
                'account_id' => $row->account_id,
                'username' => $row->username,
                'primary_domain' => $row->primary_domain,
                'account_status' => $row->account_status,
                'label' => $row->label,
                'expression' => $row->expression,
                'command' => $row->command,
                'command_preview' => mb_strlen($row->command ?? '') > 80
                    ? mb_substr($row->command ?? '', 0, 80) . '…'
                    : ($row->command ?? ''),
                'is_active' => (bool) $row->is_active,
                'last_run_at' => $row->last_run_at,
                'last_exit_code' => $row->last_exit_code !== null ? (int) $row->last_exit_code : null,
                'created_at' => $row->created_at,

                // Validation
                'expression_valid' => $exprResult['valid'],
                'expression_issues' => $exprResult['issues'],
                'expression_warnings' => $exprResult['warnings'],
                'expression_human_tr' => $exprResult['human_tr'],
                'command_issues' => $cmdIssues,

                // Health flags
                'broken' => ! $exprResult['valid'],
                'suspicious' => ! empty($cmdIssues),
                'stale' => $stale,
                'never_run' => $neverRun,
                'last_run_failed' => $row->last_exit_code !== null && (int) $row->last_exit_code !== 0,
            ];
        });

        // Status filter — DB üstünde olamaz, validation client-side
        $statusFilter = (string) $request->input('status', '');
        if ($statusFilter !== '' && $statusFilter !== 'all') {
            $crons = $crons->filter(function (array $c) use ($statusFilter) {
                return match ($statusFilter) {
                    'active' => $c['is_active'],
                    'inactive' => ! $c['is_active'],
                    'broken' => $c['broken'],
                    'suspicious' => $c['suspicious'],
                    'stale' => $c['stale'],
                    'never_run' => $c['never_run'],
                    'failed' => $c['last_run_failed'],
                    default => true,
                };
            })->values();
        }

        $summary = [
            'total' => $rows->count(),
            'active' => $crons->where('is_active', true)->count(),
            'broken' => $crons->where('broken', true)->count(),
            'suspicious' => $crons->where('suspicious', true)->count(),
            'never_run' => $crons->where('never_run', true)->count(),
            'stale' => $crons->where('stale', true)->count(),
            'failed' => $crons->where('last_run_failed', true)->count(),
        ];

        // Accounts dropdown — filter için
        $accounts = DB::table('accounts')
            ->select('id', 'username', 'primary_domain')
            ->orderBy('username')
            ->get();

        return Inertia::render('Admin/Cron/Audit', [
            'crons' => $crons->values(),
            'summary' => $summary,
            'accounts' => $accounts,
            'filters' => [
                'search' => $request->input('search', ''),
                'status' => $statusFilter ?: 'all',
                'account_id' => $request->input('account_id'),
            ],
        ]);
    }

    /**
     * Tek bir cron'u disable et — soft "broken" cron'lar için.
     */
    public function disable(Request $request, int $id): RedirectResponse
    {
        if (! Schema::hasTable('cron_jobs')) {
            return back()->with('error', 'cron_jobs tablosu yok — migrate çalıştırın.');
        }

        $row = DB::table('cron_jobs')->find($id);
        if (! $row) {
            return back()->with('error', 'Cron bulunamadı.');
        }

        DB::table('cron_jobs')->where('id', $id)->update([
            'is_active' => false,
            'updated_at' => now(),
        ]);

        $this->auditCron($request, 'cron.disabled', $row, $request->input('reason'));

        return back()->with('success', "Cron #{$id} ({$row->expression}) devre dışı bırakıldı.");
    }

    /**
     * Cron'u tekrar aktive et.
     */
    public function enable(Request $request, int $id): RedirectResponse
    {
        if (! Schema::hasTable('cron_jobs')) {
            return back()->with('error', 'cron_jobs tablosu yok — migrate çalıştırın.');
        }

        $row = DB::table('cron_jobs')->find($id);
        if (! $row) {
            return back()->with('error', 'Cron bulunamadı.');
        }

        DB::table('cron_jobs')->where('id', $id)->update([
            'is_active' => true,
            'updated_at' => now(),
        ]);

        $this->auditCron($request, 'cron.enabled', $row, null);

        return back()->with('success', "Cron #{$id} aktive edildi.");
    }

    /**
     * Tüm broken (geçersiz syntax) cron'ları toplu disable et.
     */
    public function bulkDisableBroken(Request $request): RedirectResponse
    {
        $confirm = $request->input('confirm_string', '');
        if ($confirm !== 'TUMUNU KAPAT') {
            return back()->with('error', 'Onay metni hatalı. "TUMUNU KAPAT" yazmanız gerek.');
        }

        if (! Schema::hasTable('cron_jobs')) {
            return back()->with('error', 'cron_jobs tablosu yok.');
        }

        $allActive = DB::table('cron_jobs')
            ->where('is_active', true)
            ->whereNull('deleted_at')
            ->get(['id', 'expression']);

        $brokenIds = [];
        foreach ($allActive as $cron) {
            $result = $this->validator->validate($cron->expression);
            if (! $result['valid']) {
                $brokenIds[] = $cron->id;
            }
        }

        if (empty($brokenIds)) {
            return back()->with('info', 'Disable edilecek broken cron bulunamadı.');
        }

        DB::table('cron_jobs')
            ->whereIn('id', $brokenIds)
            ->update(['is_active' => false, 'updated_at' => now()]);

        try {
            if (Schema::hasTable('audit_log')) {
                DB::table('audit_log')->insert([
                    'user_id' => $request->user()?->id,
                    'action' => 'cron.bulk_disable_broken',
                    'target_type' => 'cron_jobs',
                    'target_id' => null,
                    'ip_address' => $request->ip(),
                    'outcome' => 'success',
                    'metadata' => json_encode([
                        'disabled_count' => count($brokenIds),
                        'cron_ids' => $brokenIds,
                    ]),
                    'created_at' => now(),
                ]);
            }
        } catch (\Throwable) {}

        return back()->with('success', count($brokenIds) . ' broken cron toplu olarak disable edildi.');
    }

    private function auditCron(Request $request, string $action, object $row, ?string $reason): void
    {
        try {
            if (! Schema::hasTable('audit_log')) {
                return;
            }
            DB::table('audit_log')->insert([
                'user_id' => $request->user()?->id,
                'action' => $action,
                'target_type' => 'cron_job',
                'target_id' => $row->id ?? null,
                'ip_address' => $request->ip(),
                'outcome' => 'success',
                'metadata' => json_encode([
                    'account_id' => $row->account_id ?? null,
                    'expression' => $row->expression ?? null,
                    'command' => $row->command ?? null,
                    'reason' => $reason,
                ], JSON_UNESCAPED_UNICODE),
                'created_at' => now(),
            ]);
        } catch (\Throwable) {}
    }
}
