<?php

namespace App\Http\Controllers\SystemSettings;

use App\Http\Controllers\Controller;
use App\Models\AiHealingLog;
use App\Services\SystemConfig\SystemConfigService;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;

class AiSelfHealingController extends Controller
{
    public function index(SystemConfigService $systemConfig)
    {
        $this->authorize('view ai self-healing');
        $grouped  = $systemConfig->grouped();
        $settings = $grouped['ai_healing'] ?? [];
        $aiCfg    = $grouped['ai_config']  ?? [];

        $logs  = AiHealingLog::latest()->take(100)->get();
        $stats = $this->buildStats();

        $topExceptions = AiHealingLog::select('error_type', DB::raw('COUNT(*) as total'))
            ->groupBy('error_type')
            ->orderByDesc('total')
            ->take(5)
            ->get()
            ->map(fn ($r) => [
                'type'  => class_basename($r->error_type),
                'fqcn'  => $r->error_type,
                'count' => (int) $r->getAttribute('total'),
            ])
            ->all();

        $timeline = $this->build24hTimeline();
        $lastIncident = AiHealingLog::latest()->value('created_at');

        $providerInfo = [
            'enabled'  => (bool) ($aiCfg['ai_enabled'] ?? false),
            'provider' => strtoupper($aiCfg['ai_provider'] ?? 'gpt'),
            'has_key'  => $this->resolveProviderKeyPresent($aiCfg),
        ];

        return view('pages.system_settings.ai-self-healing', compact(
            'logs', 'settings', 'stats', 'topExceptions', 'timeline', 'lastIncident', 'providerInfo'
        ));
    }

    public function update(Request $request, SystemConfigService $systemConfig)
    {
        $this->authorize('manage ai self-healing');
        $input = [
            'ai_healing_enabled'            => $request->has('ai_healing_enabled'),
            'ai_healing_allow_cache'        => $request->has('ai_healing_allow_cache'),
            'ai_healing_allow_queue'        => $request->has('ai_healing_allow_queue'),
            'ai_healing_allow_maintenance'  => $request->has('ai_healing_allow_maintenance'),
            'ai_healing_allow_db'           => $request->has('ai_healing_allow_db'),
            'ai_healing_max_attempts_per_hour' => $request->input('ai_healing_max_attempts_per_hour', 5),
        ];

        $systemConfig->update($input, [], auth()->id(), $request);

        if ($request->wantsJson() || $request->ajax()) {
            return response()->json([
                'success'  => true,
                'message'  => 'AI Healing configuration saved successfully.',
                'settings' => $input,
            ]);
        }

        return redirect()->back()->with('success', 'AI Healing configuration saved successfully.');
    }

    public function show($id)
    {
        $this->authorize('view ai self-healing');
        $log = AiHealingLog::findOrFail($id);

        // Parse the action_taken marker for human-readable display + rollback info
        $action       = (string) $log->action_taken;
        $actionPretty = $action;
        $rollbackInfo = null;

        if (str_starts_with($action, 'CODE_EDIT|')) {
            $parts        = explode('|', $action, 3);
            $filePath     = $parts[1] ?? '';
            $backupPath   = $parts[2] ?? '';
            $backupExists = $backupPath && file_exists($backupPath);
            $actionPretty = 'Code edit applied in ' . basename($filePath)
                . ($backupExists ? ' (backup available)' : ' (backup missing)');
            $rollbackInfo = [
                'available'   => $backupExists,
                'file'        => basename($filePath),
                'backup_file' => basename($backupPath),
            ];
        } elseif (str_starts_with($action, 'ROLLED_BACK|')) {
            $parts        = explode('|', $action, 3);
            $filePath     = $parts[1] ?? '';
            $actionPretty = 'Rolled back: ' . basename($filePath) . ' restored from backup';
        }

        return response()->json([
            'success' => true,
            'data'    => [
                'id'             => $log->id,
                'error_type'     => $log->error_type,
                'error_message'  => $log->error_message,
                'stack_trace'    => $log->stack_trace,
                'ai_diagnosis'   => $log->ai_diagnosis,
                'action_taken'   => $actionPretty,
                'action_raw'     => $action,
                'rollback'       => $rollbackInfo,
                'status'         => $log->status,
                'original_code'  => $log->original_code,
                'fixed_code'     => $log->fixed_code,
                'created_at'     => optional($log->created_at)->format('d M Y, H:i:s'),
                'relative_time'  => optional($log->created_at)->diffForHumans(),
            ],
        ]);
    }

    public function clearLogs()
    {
        $this->authorize('manage ai self-healing');
        AiHealingLog::truncate();
        return response()->json([
            'success' => true,
            'message' => 'All AI Healing logs have been cleared successfully.',
        ]);
    }

    public function retry($id)
    {
        $this->authorize('manage ai self-healing');
        $log = AiHealingLog::findOrFail($id);

        if (!\in_array($log->status, ['failed', 'diagnosing', 'pending'], true)) {
            return response()->json([
                'success' => false,
                'message' => 'Only failed, pending, or stuck-diagnosing logs can be retried.',
            ], 422);
        }

        $log->update([
            'status'       => 'pending',
            'action_taken' => 'Retry queued by ' . (auth()->user()->name ?? 'system'),
        ]);

        try {
            // Synchronous dispatch — matches the original interceptor behaviour
            // so the user sees the new outcome immediately on refresh.
            \App\Jobs\AiHealerJob::dispatchSync($log->id);
        } catch (\Throwable $e) {
            $log->update([
                'status'       => 'failed',
                'ai_diagnosis' => 'Retry crashed: ' . $e->getMessage(),
                'action_taken' => 'Retry pipeline error',
            ]);
            return response()->json([
                'success' => false,
                'message' => 'Retry failed: ' . $e->getMessage(),
            ], 500);
        }

        return response()->json([
            'success' => true,
            'message' => 'Healing re-attempted. Status: ' . $log->fresh()->status,
            'status'  => $log->fresh()->status,
        ]);
    }

    public function rollback($id)
    {
        $this->authorize('manage ai self-healing');
        $log = AiHealingLog::findOrFail($id);

        $action = (string) $log->action_taken;
        if (!str_starts_with($action, 'CODE_EDIT|')) {
            return response()->json([
                'success' => false,
                'message' => 'This incident has no code-edit backup to roll back.',
            ], 422);
        }

        $parts      = explode('|', $action, 3);
        $filePath   = $parts[1] ?? null;
        $backupPath = $parts[2] ?? null;

        if (!$filePath || !$backupPath || !file_exists($backupPath)) {
            return response()->json([
                'success' => false,
                'message' => 'Backup file not found. It may have been deleted manually.',
            ], 404);
        }

        if (!is_writable($filePath)) {
            return response()->json([
                'success' => false,
                'message' => 'Target file is not writable.',
            ], 422);
        }

        $backupContent = file_get_contents($backupPath);
        file_put_contents($filePath, $backupContent);
        \Illuminate\Support\Facades\Artisan::call('optimize:clear');

        $log->update([
            'action_taken' => 'ROLLED_BACK|' . $filePath . '|from ' . basename($backupPath),
            'ai_diagnosis' => '[rolled back by ' . (auth()->user()->name ?? 'system') . '] ' . $log->ai_diagnosis,
        ]);

        return response()->json([
            'success' => true,
            'message' => 'Rollback completed. ' . basename($filePath) . ' restored from backup.',
        ]);
    }

    public function stats()
    {
        $this->authorize('view ai self-healing');
        return response()->json($this->buildStats() + [
            'timeline'      => $this->build24hTimeline(),
            'last_incident' => optional(AiHealingLog::latest()->value('created_at'))->diffForHumans() ?? 'No incidents',
        ]);
    }

    private function buildStats(): array
    {
        $total    = AiHealingLog::count();
        $resolved = AiHealingLog::where('status', 'resolved')->count();
        $failed   = AiHealingLog::where('status', 'failed')->count();
        $pending  = AiHealingLog::whereIn('status', ['pending', 'diagnosing'])->count();

        return [
            'total'    => $total,
            'resolved' => $resolved,
            'failed'   => $failed,
            'pending'  => $pending,
            'rate'     => $total > 0 ? round(($resolved / $total) * 100) : 0,
            'last_24h' => AiHealingLog::where('created_at', '>=', now()->subDay())->count(),
        ];
    }

    private function build24hTimeline(): array
    {
        $from = now()->subHours(23)->startOfHour();

        $buckets = [];
        for ($i = 23; $i >= 0; $i--) {
            $hour = now()->subHours($i)->startOfHour();
            $buckets[$hour->format('Y-m-d H')] = [
                'label' => $hour->format('H:00'),
                'count' => 0,
            ];
        }

        AiHealingLog::where('created_at', '>=', $from)
            ->select('created_at')
            ->orderBy('created_at')
            ->get()
            ->each(function ($row) use (&$buckets) {
                $key = Carbon::parse($row->created_at)->startOfHour()->format('Y-m-d H');
                if (isset($buckets[$key])) {
                    $buckets[$key]['count']++;
                }
            });

        return array_values($buckets);
    }

    private function resolveProviderKeyPresent(array $aiCfg): bool
    {
        $provider = $aiCfg['ai_provider'] ?? 'gpt';
        $keyMap = [
            'gpt'        => 'ai_gpt_key',
            'gemini'     => 'ai_gemini_key',
            'claude'     => 'ai_claude_key',
            'deepseek'   => 'ai_deepseek_key',
            'grok'       => 'ai_grok_key',
            'mistral'    => 'ai_mistral_key',
            'openrouter' => 'ai_openrouter_key',
        ];

        $field = $keyMap[$provider] ?? null;
        return $field !== null && !empty($aiCfg[$field] ?? '');
    }
}
