<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
use ZipArchive;
use Exception;

class BackupController extends Controller
{
    private $backupPath;

    public function __construct()
    {
        $this->backupPath = storage_path('backups');
        
        // Create backups directory jika belum ada
        if (!File::isDirectory($this->backupPath)) {
            File::makeDirectory($this->backupPath, 0755, true);
        }
    }

    public function index(Request $request)
    {
        $backups = [];
        
        if (File::isDirectory($this->backupPath)) {
            $files = File::files($this->backupPath);
            
            foreach ($files as $file) {
                $backups[] = [
                    'name' => $file->getFilename(),
                    'size' => $file->getSize(),
                    'date' => $file->getMTime(),
                    'path' => $file->getRealPath(),
                ];
            }
        }

        // Sort by date descending
        usort($backups, function($a, $b) {
            return $b['date'] <=> $a['date'];
        });

        return view('admin.backup.index', compact('backups'));
    }

    public function create(Request $request)
    {
        try {
            $timestamp = now()->format('Y-m-d-H-i-s');
            $backupFile = $this->backupPath . "/backup_{$timestamp}.sql";

            // Get database credentials (use config() instead of env() for config:cache compatibility)
            $database = config('database.connections.mysql.database');
            $username = config('database.connections.mysql.username');
            $password = config('database.connections.mysql.password');
            $host = config('database.connections.mysql.host');

            // Create SQL dump (Windows MySQL)
            $command = sprintf(
                'mysqldump --user=%s --password=%s --host=%s %s > "%s"',
                escapeshellarg($username),
                escapeshellarg($password),
                escapeshellarg($host),
                escapeshellarg($database),
                $backupFile
            );

            $output = null;
            $exitCode = null;
            exec($command, $output, $exitCode);

            if ($exitCode === 0 && File::exists($backupFile)) {
                // Create zip file
                $zipFile = $this->backupPath . "/backup_{$timestamp}.zip";
                $zip = new ZipArchive();
                
                if ($zip->open($zipFile, ZipArchive::CREATE) === true) {
                    $zip->addFile($backupFile, 'database.sql');
                    $zip->close();

                    // Delete original SQL file
                    File::delete($backupFile);

                    return redirect()->back()->with('success', "Backup berhasil dibuat: backup_{$timestamp}.zip");
                }
            }

            return redirect()->back()->with('error', 'Gagal membuat backup');
        } catch (Exception $e) {
            return redirect()->back()->with('error', 'Error: ' . $e->getMessage());
        }
    }

    public function download($backup)
    {
        // Sanitize: prevent path traversal
        $backup = basename($backup);
        $backupPath = $this->backupPath . '/' . $backup;

        if (!File::exists($backupPath)) {
            return redirect()->back()->with('error', 'File backup tidak ditemukan');
        }

        return response()->download($backupPath);
    }

    public function delete($backup)
    {
        try {
            // Sanitize: prevent path traversal
            $backup = basename($backup);
            $backupPath = $this->backupPath . '/' . $backup;

            if (!File::exists($backupPath)) {
                return redirect()->back()->with('error', 'File backup tidak ditemukan');
            }

            File::delete($backupPath);

            return redirect()->back()->with('success', 'Backup berhasil dihapus');
        } catch (Exception $e) {
            return redirect()->back()->with('error', 'Error: ' . $e->getMessage());
        }
    }

    public function restore(Request $request, $backup)
    {
        try {
            // Sanitize: prevent path traversal
            $backup = basename($backup);
            $backupPath = $this->backupPath . '/' . $backup;

            if (!File::exists($backupPath)) {
                return redirect()->back()->with('error', 'File backup tidak ditemukan');
            }

            // Extract zip jika zip file
            if (pathinfo($backupPath, PATHINFO_EXTENSION) === 'zip') {
                $extractPath = $this->backupPath . '/temp_' . time();
                $zip = new ZipArchive();
                
                if ($zip->open($backupPath) === true) {
                    $zip->extractTo($extractPath);
                    $zip->close();
                    
                    $sqlFile = $extractPath . '/database.sql';
                    if (!File::exists($sqlFile)) {
                        File::deleteDirectory($extractPath);
                        return redirect()->back()->with('error', 'File SQL tidak ditemukan dalam backup');
                    }
                } else {
                    return redirect()->back()->with('error', 'Gagal membuka file zip');
                }
            } else {
                $sqlFile = $backupPath;
            }

            // Restore database (use config() instead of env() for config:cache compatibility)
            $database = config('database.connections.mysql.database');
            $username = config('database.connections.mysql.username');
            $password = config('database.connections.mysql.password');
            $host = config('database.connections.mysql.host');

            $command = sprintf(
                'mysql --user=%s --password=%s --host=%s %s < "%s"',
                escapeshellarg($username),
                escapeshellarg($password),
                escapeshellarg($host),
                escapeshellarg($database),
                $sqlFile
            );

            $output = null;
            $exitCode = null;
            exec($command, $output, $exitCode);

            // Cleanup temp files
            if (isset($extractPath) && File::isDirectory($extractPath)) {
                File::deleteDirectory($extractPath);
            }

            if ($exitCode === 0) {
                return redirect()->back()->with('success', 'Database berhasil di-restore');
            } else {
                return redirect()->back()->with('error', 'Gagal restore database');
            }
        } catch (Exception $e) {
            return redirect()->back()->with('error', 'Error: ' . $e->getMessage());
        }
    }
}
