<?php

namespace App\Controllers\Panel\App\Settings\BackupRestore;

use App\Controllers\Panel\BC;
use App\Libraries\HZip;

class Backup extends BC
{

    public function index()
    {
        set_time_limit(60 * 30);
        helper('Panel/utils');
        $db = \Config\Database::connect();
        $tables = $db->listTables();
        $withAssets = $this->request->getGet("assets") == 'true';
        $limitedMemory = $this->request->getGet("limited-memory") == 'true';
        $withDB = $this->request->getGet("db") == 'true';
        $path = WRITEPATH . "db/backups";
        $archiveName = url_title(options('appname')) . "-" . time();
        if ($withAssets && !$withDB) $archiveName = "Assets-$archiveName";
        elseif ($withDB && !$withAssets) $archiveName = "DB-$archiveName";
        $pathTemp = "$path/$archiveName";
        $dbPath = "$pathTemp/db";
        if (!file_exists($pathTemp)) {
            try {
                $old = umask(0);
                @mkdir($pathTemp, 0755, true);
                umask($old);
                chownr($pathTemp, 'www');
            } catch (\Throwable $th) {
            }
        }
        if ($withDB) {

            if (!file_exists("$pathTemp/db")) {
                try {
                    $old = umask(0);
                    @mkdir("$pathTemp/db", 0755, true);
                    umask($old);
                    chownr("$pathTemp/db", 'www');
                } catch (\Throwable $th) {
                }
            }
        }
        if ($withAssets) {
            if (!file_exists("$pathTemp/public")) {
                try {
                    $old = umask(0);
                    @mkdir("$pathTemp/public", 0755, true);
                    umask($old);
                    chownr("$pathTemp/public", 'www');
                } catch (\Throwable $th) {
                }
            }
        }

        if ($withDB) {
            foreach ($tables as $table) {
                $builder = $db->table($table);
                if (in_array($table, $this->ignoreTable)) continue;
                $rows = $builder->countAll();
                $myData = [];
                $limit = 1000;
                if ($rows > 5000 && $limitedMemory) {
                    while ($rows > 0) {
                        $builder->limit($limit, count($myData));
                        $md = $builder->get()->getResultArray();
                        if (count($md) > 0) $myData = array_merge($myData, $md);
                        else break;
                        $rows -= $limit;
                    }
                } else {
                    $myData = $builder->get()->getResultArray();
                }
                if ($table == 'm_siswa') {
                    $temp = [];
                    foreach ($myData as $key => $value) {
                        if ($value['password_hash']) $value['password_hash'] = bin2hex($value['password_hash']);
                        $temp[] = $value;
                    }
                    $myData = $temp;
                }
                file_put_contents("$dbPath/$table.json", json_encode($myData));
            }
        }
        if ($withAssets) recurse_copy(FCPATH . 'assets', "$pathTemp/public/assets");
        file_put_contents("$pathTemp/config.json", json_encode(['app_version_code' => APP_VERSION_CODE, 'app_version_name' => APP_VERSION_NAME]));
        $hz = new HZip;
        $hz->zipDir($pathTemp, "$pathTemp.zip");
        rrmdir($pathTemp);
        foreach (scandir($path) as  $value) {
            if (in_array($value, ['.', '..'])) continue;
            if (filemtime("$path/$value") < strtotime('-10 days') && !is_dir("$path/$value")) {
                unlink("$path/$value");
            }
        }
        return $this->response->download("$pathTemp.zip", null)->setFileName("backup-$archiveName.candy");
    }
}
