<?php

namespace App\Http\Controllers;

use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Response;
use ZipArchive;
use JsonMachine\Items;
class JsonTransferController extends Controller
{
    protected $exportPath = 'database/seeders/data/';
    public function index(){
        //POSTGRESS
        $tables = DB::select("SELECT tablename FROM pg_tables WHERE schemaname = 'public'");
        $tableNames = array_map(fn($t) => $t->tablename, $tables);
        //MYSQL
        //$tables = DB::select('SHOW TABLES');
        //$tableNames = array_map('current', $tables);
        $tableInfo = [];

        foreach ($tableNames as $table) {
            $filePath = base_path($this->exportPath . $table . '.json');
            $fileSize = file_exists($filePath) ? filesize($filePath) : null;

            $tableInfo[] = [
                'name' => $table,
                'size' => $fileSize,
            ];
        }
        return view('backup', compact('tableInfo'));
    }
    public function generate(){
        $exportPath = base_path($this->exportPath);
        if (!is_dir($exportPath)) {
            mkdir($exportPath, 0777, true);
        }

        $tables     = DB::select("SELECT tablename FROM pg_tables WHERE schemaname = 'public'");
        $tableNames = array_map(fn($t) => $t->tablename, $tables);

        foreach ($tableNames as $table) {
            try {
                $filePath = $exportPath . $table . '.json';
                $handle = fopen($filePath, 'w');

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

                $first = true;

                foreach (DB::table($table)->cursor() as $row) {
                    $jsonRow = json_encode($row, JSON_UNESCAPED_UNICODE);

                    if (!$first) {
                        fwrite($handle, ",\n");
                    } else {
                        $first = false;
                    }

                    fwrite($handle, $jsonRow);
                }

                fwrite($handle, "\n]");
                fclose($handle);
            } catch (\Exception $e) {
                \Log::warning("Gagal ekspor tabel $table: " . $e->getMessage());
                continue;
            }
        }

        return redirect()->back()->with('success', 'Semua tabel berhasil diekspor tanpa kehabisan memori.');
    }
    public function downloadTable($table){
        $file = base_path($this->exportPath . $table . '.json');

        if (!file_exists($file)) {
            return abort(404, 'File tidak ditemukan.');
        }

        return response()->download($file);
    }
    public function downloadAll(){
        $zipFile = base_path('database/seeders/data/all_json.zip');
        $zip = new ZipArchive;

        File::delete($zipFile);

        if ($zip->open($zipFile, ZipArchive::CREATE) === TRUE) {
            foreach (File::files(base_path($this->exportPath)) as $file) {
                $zip->addFile($file->getRealPath(), basename($file));
            }
            $zip->close();
        }

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

    public function importTable($table) {
        set_time_limit(0); 
        ini_set('memory_limit', '-1'); 
        ini_set('max_execution_time', 0);

        $path = base_path($this->exportPath . $table . '.json');
        if (!file_exists($path)) {
            return back()->with('error', "File tidak ditemukan.");
        }

        DB::disableQueryLog();
        try {
            DB::beginTransaction();
            DB::statement("TRUNCATE TABLE $table RESTART IDENTITY CASCADE");
            $items = Items::fromFile($path);
            
            $chunk = [];
            $batchSize = 1000;
            $counter = 0;

            foreach ($items as $row) {
                $data = (array) $row;
                unset($data['id']);
                $chunk[] = $data;
                $counter++;

                if (count($chunk) >= $batchSize) {
                    DB::table($table)->insert($chunk);
                    $chunk = [];
                    if ($counter % 5000 == 0) {
                        gc_collect_cycles(); 
                    }
                }
            }

            if (!empty($chunk)) {
                DB::table($table)->insert($chunk);
            }
            $resetSequenceSql = "SELECT setval(pg_get_serial_sequence('$table', 'id'), COALESCE(MAX(id), 1)) FROM $table";
            DB::statement($resetSequenceSql);
            DB::commit();            
            DB::enableQueryLog();

            return back()->with('success', 'Import berhasil!');

        } catch (\Exception $e) {
            DB::rollBack();
            \Log::error("Import Error $table: " . $e->getMessage());            
            return back()->with('error', "Error 500 Details: " . $e->getMessage());
        }
    }
    public function pull(Request $request){
        if (session('previlage') !== 'developer') {
            abort(403, 'Akses ditolak. Anda tidak memiliki izin untuk menjalankan git pull.');
        }
        $gitPath = base_path();
        $output = shell_exec("cd {$gitPath} && git pull 2>&1");
        if (auth()->check()) {
            Log::info('Git pull executed by user: ' . auth()->user()->email.' at '.now());
        }

        return back()->with('git_output', $output);
    }

}
