<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\DB;
use Symfony\Component\Process\Process;
use Carbon\Carbon;

class BackupController extends Controller
{
    public function __construct()
    {
        $this->middleware('permission:settings', ['only' => ['index', 'create', 'download', 'delete']]);
    }

    public function index()
    {
        $backupPath = storage_path('app/backups');

        if (!File::exists($backupPath)) {
            File::makeDirectory($backupPath, 0755, true);
        }

        $backupFiles = collect(File::files($backupPath))
            ->map(function ($file) {
                return [
                    'name' => $file->getFilename(),
                    'size' => $this->formatSize($file->getSize()),
                    'date' => Carbon::createFromTimestamp($file->getMTime())->format('Y-m-d H:i:s'),
                    'path' => $file->getPathname(),
                ];
            })
            ->sortByDesc('date')
            ->values()
            ->all();

        return view('admin.settings.backups', compact('backupFiles'));
    }

    public function create()
    {
        try {
            // Increase memory and time limits
            ini_set('memory_limit', '512M');
            set_time_limit(300); // 5 minutes

            // Create backup directory if it doesn't exist
            $backupPath = storage_path('app/backups');
            if (!File::exists($backupPath)) {
                File::makeDirectory($backupPath, 0755, true);
            }

            // Generate backup filename
            $filename = 'backup_' . date('Y-m-d_H-i-s') . '.sql';
            $outputPath = $backupPath . '/' . $filename;

            // Get list of tables
            $tables = DB::select('SHOW TABLES');
            $tableKey = 'Tables_in_' . config('database.connections.mysql.database');

            // Start writing to file
            $handle = fopen($outputPath, 'w+');

            // Write header
            fwrite($handle, "-- Database: " . config('database.connections.mysql.database') . "\n");
            fwrite($handle, "-- Generated on: " . date('Y-m-d H:i:s') . "\n\n");
            fwrite($handle, "SET FOREIGN_KEY_CHECKS=0;\n\n");

            // Process each table
            foreach ($tables as $table) {
                $tableName = $table->$tableKey;

                // Get create table statement
                $createTable = DB::select("SHOW CREATE TABLE `$tableName`")[0];
                $createTableSql = $createTable->{'Create Table'};

                // Write table structure
                fwrite($handle, "-- Table structure for table `$tableName`\n");
                fwrite($handle, "DROP TABLE IF EXISTS `$tableName`;\n");
                fwrite($handle, $createTableSql . ";\n\n");

                // Get and write data
                $rows = DB::table($tableName)->select('*')->get();

                if (count($rows) > 0) {
                    fwrite($handle, "-- Data for table `$tableName`\n");

                    // Process in chunks for large tables
                    $chunks = array_chunk($rows->toArray(), 100);
                    foreach ($chunks as $chunk) {
                        $insertSql = $this->generateInsertStatement($tableName, $chunk);
                        fwrite($handle, $insertSql);
                    }

                    fwrite($handle, "\n");
                }
            }

            // Write footer
            fwrite($handle, "SET FOREIGN_KEY_CHECKS=1;\n");

            // Close file
            fclose($handle);

            // Verify the file is created and has content
            if (File::exists($outputPath) && File::size($outputPath) > 100) {
                session()->flash('success', __('translations.backup_created_successfully'));
            } else {
                session()->flash('error', __('translations.backup_creation_failed') . ' - ' . __('translations.empty_file_created'));
            }
        } catch (\Exception $e) {
            \Log::error('Database backup error: ' . $e->getMessage() . ' - ' . $e->getTraceAsString());
            session()->flash('error', __('translations.backup_creation_failed') . ' - ' . $e->getMessage());
        }

        return redirect()->route('admin.settings.backups');
    }

    /**
     * Generate INSERT statement for a given table and data
     */
    private function generateInsertStatement($tableName, $data)
    {
        if (empty($data)) {
            return '';
        }

        $insertSql = "INSERT INTO `$tableName` VALUES ";
        $values = [];

        foreach ($data as $row) {
            $rowValues = [];
            $row = (array) $row;

            foreach ($row as $value) {
                if (is_null($value)) {
                    $rowValues[] = 'NULL';
                } else if (is_numeric($value)) {
                    $rowValues[] = $value;
                } else {
                    $rowValues[] = "'" . str_replace("'", "\'", $value) . "'";
                }
            }

            $values[] = '(' . implode(',', $rowValues) . ')';
        }

        $insertSql .= implode(',', $values) . ";\n";
        return $insertSql;
    }

    public function download($filename)
    {
        $backupPath = storage_path('app/backups/' . $filename);

        if (File::exists($backupPath)) {
            return response()->download($backupPath);
        }

        session()->flash('error', __('translations.backup_file_not_found'));
        return redirect()->route('admin.settings.backups');
    }

    public function delete($filename)
    {
        $backupPath = storage_path('app/backups/' . $filename);

        if (File::exists($backupPath)) {
            File::delete($backupPath);
            session()->flash('success', __('translations.backup_deleted_successfully'));
        } else {
            session()->flash('error', __('translations.backup_file_not_found'));
        }

        return redirect()->route('admin.settings.backups');
    }

    private function formatSize($bytes)
    {
        $units = ['B', 'KB', 'MB', 'GB', 'TB'];

        $bytes = max($bytes, 0);
        $pow = floor(($bytes ? log($bytes) : 0) / log(1024));
        $pow = min($pow, count($units) - 1);

        $bytes /= pow(1024, $pow);

        return round($bytes, 2) . ' ' . $units[$pow];
    }
}
