<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;

class MaintenanceController extends Controller
{
    public function index()
    {
        return view('admin.maintenance.index');
    }

    public function backupDatabase()
    {
        try {
            $dbName     = config('database.connections.mysql.database');
            $dbUser     = config('database.connections.mysql.username');
            $dbPass     = config('database.connections.mysql.password');
            $dbHost     = config('database.connections.mysql.host');
            $dbPort     = config('database.connections.mysql.port', 3306);

            $fileName   = $dbName . '_backup_' . now()->format('Ymd_His') . '.sql';
            $storagePath = storage_path('app/backups');

            if (!file_exists($storagePath)) {
                mkdir($storagePath, 0755, true);
            }

            $filePath = $storagePath . DIRECTORY_SEPARATOR . $fileName;

            // Build mysqldump command
            $dumpCmd = sprintf(
                'mysqldump --host=%s --port=%s --user=%s --password=%s %s > %s 2>&1',
                escapeshellarg($dbHost),
                escapeshellarg($dbPort),
                escapeshellarg($dbUser),
                escapeshellarg($dbPass),
                escapeshellarg($dbName),
                escapeshellarg($filePath)
            );

            exec($dumpCmd, $output, $returnCode);

            if ($returnCode !== 0 || !file_exists($filePath) || filesize($filePath) === 0) {
                // Fallback: generate SQL via PHP
                $this->generateSqlDump($filePath, $dbName);
            }

            return redirect()->route('admin.maintenance.index')
                ->with('backup_success', $fileName)
                ->with('backup_path', $filePath);

        } catch (\Exception $e) {
            return redirect()->route('admin.maintenance.index')
                ->with('error', 'Backup gagal: ' . $e->getMessage());
        }
    }

    public function downloadBackup(Request $request)
    {
        $request->validate(['file' => 'required|string']);

        $filePath = storage_path('app/backups/' . basename($request->file));

        if (!file_exists($filePath)) {
            return redirect()->route('admin.maintenance.index')
                ->with('error', 'File backup tidak ditemukan.');
        }

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

    public function optimize()
    {
        $results = [];

        try {
            Artisan::call('config:cache');
            $results[] = ['label' => 'Config Cache', 'status' => 'success', 'message' => 'Berhasil di-cache'];
        } catch (\Exception $e) {
            $results[] = ['label' => 'Config Cache', 'status' => 'error', 'message' => $e->getMessage()];
        }

        try {
            Artisan::call('route:cache');
            $results[] = ['label' => 'Route Cache', 'status' => 'success', 'message' => 'Berhasil di-cache'];
        } catch (\Exception $e) {
            $results[] = ['label' => 'Route Cache', 'status' => 'error', 'message' => $e->getMessage()];
        }

        try {
            Artisan::call('view:cache');
            $results[] = ['label' => 'View Cache', 'status' => 'success', 'message' => 'Berhasil di-cache'];
        } catch (\Exception $e) {
            $results[] = ['label' => 'View Cache', 'status' => 'error', 'message' => $e->getMessage()];
        }

        try {
            Artisan::call('optimize');
            $results[] = ['label' => 'Optimize', 'status' => 'success', 'message' => 'Aplikasi berhasil dioptimasi'];
        } catch (\Exception $e) {
            $results[] = ['label' => 'Optimize', 'status' => 'error', 'message' => $e->getMessage()];
        }

        return redirect()->route('admin.maintenance.index')
            ->with('optimize_results', $results);
    }

    public function clearCache()
    {
        $results = [];

        try {
            Artisan::call('cache:clear');
            $results[] = ['label' => 'Application Cache', 'status' => 'success', 'message' => 'Cache berhasil dibersihkan'];
        } catch (\Exception $e) {
            $results[] = ['label' => 'Application Cache', 'status' => 'error', 'message' => $e->getMessage()];
        }

        try {
            Artisan::call('config:clear');
            $results[] = ['label' => 'Config Cache', 'status' => 'success', 'message' => 'Config cache dibersihkan'];
        } catch (\Exception $e) {
            $results[] = ['label' => 'Config Cache', 'status' => 'error', 'message' => $e->getMessage()];
        }

        try {
            Artisan::call('route:clear');
            $results[] = ['label' => 'Route Cache', 'status' => 'success', 'message' => 'Route cache dibersihkan'];
        } catch (\Exception $e) {
            $results[] = ['label' => 'Route Cache', 'status' => 'error', 'message' => $e->getMessage()];
        }

        try {
            Artisan::call('view:clear');
            $results[] = ['label' => 'View Cache', 'status' => 'success', 'message' => 'View cache dibersihkan'];
        } catch (\Exception $e) {
            $results[] = ['label' => 'View Cache', 'status' => 'error', 'message' => $e->getMessage()];
        }

        return redirect()->route('admin.maintenance.index')
            ->with('optimize_results', $results);
    }

    /**
     * PHP-based SQL dump fallback (no mysqldump required)
     */
    private function generateSqlDump(string $filePath, string $dbName): void
    {
        $handle = fopen($filePath, 'w');
        fwrite($handle, "-- DigiShop Database Backup\n");
        fwrite($handle, "-- Generated: " . now()->toDateTimeString() . "\n");
        fwrite($handle, "-- Database: {$dbName}\n\n");
        fwrite($handle, "SET FOREIGN_KEY_CHECKS=0;\n\n");

        $tables = DB::select('SHOW TABLES');
        $tableKey = 'Tables_in_' . $dbName;

        foreach ($tables as $tableRow) {
            $table = $tableRow->$tableKey;

            // Table structure
            $createRow = DB::select("SHOW CREATE TABLE `{$table}`");
            $createSql = $createRow[0]->{'Create Table'};
            fwrite($handle, "DROP TABLE IF EXISTS `{$table}`;\n");
            fwrite($handle, $createSql . ";\n\n");

            // Table data
            $rows = DB::table($table)->get();
            if ($rows->count() > 0) {
                $columns = array_keys((array) $rows->first());
                $cols    = implode('`, `', $columns);

                foreach ($rows as $row) {
                    $values = array_map(function ($val) {
                        if (is_null($val)) return 'NULL';
                        return "'" . addslashes($val) . "'";
                    }, (array) $row);

                    $valStr = implode(', ', $values);
                    fwrite($handle, "INSERT INTO `{$table}` (`{$cols}`) VALUES ({$valStr});\n");
                }
                fwrite($handle, "\n");
            }
        }

        fwrite($handle, "SET FOREIGN_KEY_CHECKS=1;\n");
        fclose($handle);
    }
}
