<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Services\AuditService;
use App\Services\SystemBackupService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Validation\Rule;
use Illuminate\View\View;
use RuntimeException;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Throwable;

class SystemBackupController extends Controller
{
    public function index(SystemBackupService $backups): View
    {
        return view('admin.backups.index', [
            'backups' => $backups->backups(),
            'summary' => $backups->summary(),
        ]);
    }

    public function store(Request $request, SystemBackupService $backups): RedirectResponse
    {
        $data = $request->validate([
            'type' => ['required', Rule::in(['database', 'full'])],
        ]);

        @set_time_limit(0);
        ignore_user_abort(true);

        $lock = Cache::lock('system-backup-create', 1800);
        if (! $lock->get()) {
            return back()->with('error', 'Another system backup is already being created. Please wait for it to finish.');
        }

        try {
            $backup = $backups->create($data['type']);

            AuditService::record('system.backup.created', null, [], [
                'filename' => $backup['filename'],
                'type' => $backup['type'],
                'size' => $backup['size'],
            ]);

            return back()->with('success', 'System backup created successfully.');
        } catch (Throwable $exception) {
            report($exception);

            return back()->with('error', 'Backup creation failed: '.$exception->getMessage());
        } finally {
            $lock->release();
        }
    }

    public function download(string $filename, SystemBackupService $backups): BinaryFileResponse|RedirectResponse
    {
        try {
            $path = $backups->resolve($filename);

            AuditService::record('system.backup.downloaded', null, [], [
                'filename' => basename($path),
                'size' => (int) (filesize($path) ?: 0),
            ]);

            return response()->download($path, basename($path), [
                'Content-Type' => 'application/octet-stream',
                'Cache-Control' => 'private, no-store, max-age=0',
            ]);
        } catch (RuntimeException $exception) {
            return back()->with('error', $exception->getMessage());
        }
    }

    public function destroy(string $filename, SystemBackupService $backups): RedirectResponse
    {
        try {
            $deleted = $backups->delete($filename);

            AuditService::record('system.backup.deleted', null, [
                'filename' => $deleted['filename'],
                'size' => $deleted['size'],
            ], []);

            return back()->with('success', 'Backup deleted successfully.');
        } catch (RuntimeException $exception) {
            return back()->with('error', $exception->getMessage());
        }
    }

    public function prune(Request $request, SystemBackupService $backups): RedirectResponse
    {
        $data = $request->validate([
            'days' => ['required', 'integer', 'between:1,3650'],
        ]);

        $result = $backups->prune((int) $data['days']);

        AuditService::record('system.backups.pruned', null, [], $result);

        return back()->with(
            'success',
            $result['deleted'] > 0
                ? $result['deleted'].' old backup(s) deleted successfully.'
                : 'No backups were old enough to delete.'
        );
    }
}
