<?php

namespace App\Controllers\Panel\App\Settings\Updates;

use App\Controllers\Panel\BC;
use CodeIgniter\API\ResponseTrait;
use ZipArchive;

class Main extends BC
{

    use ResponseTrait;
    private $fileUpdateState = WRITEPATH . "cache/updates.json";
    public function __construct()
    {
        parent::__construct();
        if (!file_exists($this->fileUpdateState)) {
            file_put_contents($this->fileUpdateState, json_encode(['VERSION_NAME' => null, 'VERSION_CODE' => null, 'available' => false, 'note' => null, 'checkCount' => 0, 'lastCheck' => date("Y-m-d H:i:s")]));
        }
    }

    public function index()
    {
        $data['page_title'] = "Pengaturan - Pembaruan";
        return view('Panel/App/Settings/Updates/index', $data);
    }
    public function state()
    {
        if (!$this->request->isAJAX() && ENVIRONMENT != 'development') {
            exit('No direct script access allowed');
        }
        $updateConfig = json_decode(file_get_contents($this->fileUpdateState), true);
        $data['available'] = !$updateConfig['VERSION_CODE'] ? false : $updateConfig['VERSION_CODE'] > APP_VERSION_CODE;
        $data['VERSION_NAME'] = $updateConfig['VERSION_NAME'];
        $data['VERSION_CODE'] = $updateConfig['VERSION_CODE'];
        $data['available'] = $updateConfig['available'];
        $data['lastCheck'] = $updateConfig['lastCheck'];
        return $this->respond($updateConfig);
    }
    public function check()
    {
        if (!$this->request->isAJAX() && ENVIRONMENT != 'development') {
            exit('No direct script access allowed');
        }
        $updateConfig = json_decode(file_get_contents($this->fileUpdateState), true);
        if (strtotime($updateConfig['lastCheck']) > strtotime('-5 minutes') && $updateConfig['checkCount'] > 5) return $this->fail(['message' => "Terlalu banyak permintaan, silahkan tunggu beberapa menit lagi"]);
        $update = checkUpdate(options('licensekey'), ['cv' => APP_VERSION_CODE]);
        if ($update['state'] == 0) return $this->fail(['message' => $update['msg']]);
        $updateConfig['checkCount']++;
        if (strtotime("+5 minutes $updateConfig[lastCheck]") < time()) $updateConfig['checkCount'] = 0;
        $updateConfig['lastCheck'] = date("Y-m-d H:i:s");
        if ($update['state'] == 1) {
            $updateConfig['VERSION_NAME'] = $update['VERSION_NAME'];
            $updateConfig['VERSION_CODE'] = $update['VERSION_CODE'];
            $updateConfig['available'] = true;
            $updateConfig['note'] = $update['NOTE'];
        } else {
            $updateConfig['VERSION_NAME'] = null;
            $updateConfig['VERSION_CODE'] = null;
            $updateConfig['available'] = false;
            $updateConfig['note'] = "";
        }
        file_put_contents($this->fileUpdateState, json_encode($updateConfig));
        return $this->respond(['message' => "Berhasil memeriksa update", 'state' => $update['state']]);
    }
    public function do()
    {
        if (!$this->request->isAJAX() && ENVIRONMENT != 'development') {
            exit('No direct script access allowed');
        }
        $updateConfig = json_decode(file_get_contents($this->fileUpdateState), true);
        if (!$updateConfig['available']) return $this->fail(['message' => "Tidak ada update yang tersedia"]);
        $update = checkUpdate(options('licensekey'), ['cv' => APP_VERSION_CODE]);
        if ($update['state'] != 1) return $this->fail(['message' => $update['msg']]);
        $updateDir = WRITEPATH . "file/updates";
        try {
            if (!file_exists($updateDir)) {
                @mkdir($updateDir, 0777, true);
            }


            $output_filename = "$updateDir/update.zip";

            $host = $update['FILE'];
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $host);
            curl_setopt($ch, CURLOPT_VERBOSE, 1);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
            curl_setopt($ch, CURLOPT_HEADER, 0);
            $result = curl_exec($ch);
            curl_close($ch);
            // the following lines write the contents to a file in the same directory (provided permissions etc)
            $fp = fopen($output_filename, 'w');
            fwrite($fp, $result);
            fclose($fp);
        } catch (\Throwable $th) {
            if (ENVIRONMENT != 'production') return $this->fail(['message' => $th->getMessage()]);
            return $this->fail(['message' => "Gagal mengunduh update"]);
        }
        global $patchPath;
        global $backupPath;
        $patchPath = WRITEPATH . "patch/main";
        $backupPath = WRITEPATH . "patch/backup";
        @mkdir(WRITEPATH . "patch");
        @mkdir($patchPath);
        @mkdir($backupPath);
        helper('Panel/utils');
        try {
            $za = new ZipArchive();
            $filePath = "$updateDir/update.zip";
            $za->open($filePath);
            $za->extractTo($patchPath);
        } catch (\Throwable $e) {
            return $this->fail(['message' => $e->getMessage()]);
        }
        if (file_exists("$patchPath/init.php")) {
            include "$patchPath/init.php";
            try {
                if (function_exists('patchInit')) patchInit();
            } catch (\Throwable $th) {
                rrename($backupPath, ROOTPATH);
                return $this->fail(['message' => $th->getMessage()]);
            }
        }
        if (file_exists(WRITEPATH . "patch")) {
            rrmdir(WRITEPATH . "patch");
        }
        if (file_exists("$updateDir/update.zip")) {
            unlink("$updateDir/update.zip");
        }
        setLog("Memasang update " . APP_VERSION_NAME);
        $updateConfig['VERSION_NAME'] = null;
        $updateConfig['VERSION_CODE'] = null;
        $updateConfig['available'] = false;
        $updateConfig['note'] = "";
        $updateConfig['lastCheck'] = date("Y-m-d H:i:s");
        file_put_contents($this->fileUpdateState, json_encode($updateConfig));
        return $this->respond(['message' => "Update berhasil dipasang"]);
    }
}
