<?php
    defined('BASEPATH') or exit('No direct script access allowed');
    
    use \VisualAppeal\AutoUpdate;
    use Curl\Curl;
    
    class Updateversi extends CI_Controller
    {
        public $title;
        public $versi;
        private $user;
        private $pass;
        private $api_key;
        private $curl;
        private $pro;
        
        function __construct()
        {
            parent::__construct();
            error_reporting(0);
            // cek_tabel();
            cek_session_login();
            
            $this->load->model('model_update');
            $this->load->library('add_menu');
            $this->lang->load('update_controller_lang', 'indonesia');
            
            $this->curl        = new Curl();
            $this->url_checker = URL_CHECKER;
            $this->api_key     = info()['api_key'];
            $this->title       = info()['title'];
            $this->versi       = info()['version'];
            $this->pro         = info()['user_pass'];
            
            $this->user = info()['user_name'];
        }
        
        /**
            * index
            *
            * @return string
        */
        public function index()
        {
            cek_menu_akses();
            $data['title'] = 'Cek Update | ' . $this->title;
            $data['tema'] =  info()['tema'];
            $data['nama'] =  $this->session->nama;
            $this->template->load('main/themes', 'update', $data);
        }
        
        /**
            * cek_notif
            *
            * @return void
        */
        public function cek_notifikasi()
        {
            // cek_nput_post('GET');
            $cek_notif = $this->input->post('tipe');
            
            $fileOffline = FCPATH . "version.json";
            
            if (!is_file($fileOffline)) {
                echo "";
                die();
            }
            if (ENVIRONMENT == 'development') {
                $url_checker = URL_CHECKER_SANDBOX;
                $file_checker = '/update_checker_sandbox_kasir.json';
                } else {
                $url_checker = $this->url_checker;
                $file_checker = '/update_checker_kasir.json';
            }
            $html = "";
            $url_update = base_url('updateversi');
            $url_checker = $url_checker . $file_checker;
            
            $fileOffline = site_url('', 'http') . "version.json";
            $this->curl->setOpt(CURLOPT_SSL_VERIFYPEER, false);
            $this->curl->get($url_checker);
            if ($this->curl->error) {
                $response  =  (object)$this->curl->errorMessage;
                
                $html .= '';
                } else {
                $response = (object)$this->curl->response;
                $last_version = end($response->aplikasi);
                
                $this->curl->get($fileOffline);
                
                if ($this->curl->error) {
                    // $response_offline  =  (object)$this->curl->errorMessage;
                    $html .= '';
                    } else {
                    $response_offline = (object)$this->curl->response;
                    if ($last_version->version == $response_offline->aplikasi[0]->version) {
                        $html .= '<a class="nav-link dropdown-toggle" href="#" id="alertsDropdown" role="button" data-toggle="dropdown"
                        aria-haspopup="true" aria-expanded="false">
                        <i class="fa fa-bell fa-fw"></i>
                        <span class="badge badge-danger badge-counter" id="remove-notif">0</span>
                        </a>';
                        } elseif ($last_version->version > $response_offline->aplikasi[0]->version) {
                        $html .= '<a class="nav-link dropdown-toggle" href="#" id="alertsDropdown" role="button" data-toggle="dropdown"
                        aria-haspopup="true" aria-expanded="false">
                        <i class="fa fa-bell fa-fw"></i>
                        <span class="badge badge-danger badge-counter">1</span>
                        </a>
                        <div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
                        aria-labelledby="alertsDropdown">
                        <h6 class="dropdown-header">Versi ' . $last_version->version . ' tersedia</h6>
                        <div id="slimm">
                        <a class="dropdown-item d-flex align-items-center remove-notif" href="' . $url_update . '" id="remove-notif">
                        <div class="dropdown-list-image mr-3">
                        <img class="rounded-circle" src="' . $last_version->url_image . '" style="max-width: 60px" alt="">
                        <div class="status-indicator bg-success"></div>
                        </div>
                        <div>
                        <div class="small text-gray-500">Versi ' . $last_version->version . '</div>
                        <span class="font-weight-bold">' . $last_version->caption . '</span>
                        <div class="small text-gray-500">' . dtime($last_version->updateDate) . '</div>
                        </div>
                        </a>';
                        
                        array_pop($response->aplikasi);
                        rsort($response->aplikasi);
                        foreach ($response->aplikasi as $key => $val) {
                            $html .= '
                            <a class="dropdown-item d-flex align-items-center remove-notif" href="#" id="remove-notif">
                            <div class="dropdown-list-image mr-3">
                            <img class="rounded-circle" src="' . $val->url_image . '" style="max-width: 60px" alt="">
                            <div class="status-indicator bg-default"></div>
                            </div>
                            <div>
                            <div class="small text-gray-500">Versi ' . $val->version . '</div>
                            <span class="font-weight-bold">' . $val->caption . '</span>
                            <div class="small text-gray-500">' . dtime($val->updateDate) . '</div>
                            </div>
                            </a>';
                        }
                        $html .= '</div>
                        <a class="dropdown-item text-center small text-gray-500" href="https://pospercetakan.my.id/detail-update" target="_blank">Detail update</a>';
                        } else {
                        $html .= '';
                    }
                }
                $html .= '<script>
                $("#slimm").slimscroll({
                height: "260px"
                });
                </script>';
                echo $html;
            }
        }
        
        
        /**
            * update_app
            *
            * @return array
        */
        
        public function update_app()
{
    $this->output->set_content_type('application/json');

    $t0 = microtime(true);
    $trace = [];

    $ms = function() use ($t0){
        return (int) round((microtime(true) - $t0) * 1000);
    };

    // TRACE plain text (tanpa [[...]] formatting)
    $log = function($msg) use (&$trace, $ms){
        $trace[] = '['.date('H:i:s').'] TRACE '.$msg.' ('.$ms().' ms)';
    };

    // Normalisasi output dari model jadi array baris
    $normalizeLines = function($data){
        // jika format {status:'log', data:'...'}
        if (is_array($data) && isset($data['status']) && $data['status'] === 'log') {
            $data = (string)($data['data'] ?? '');
        }

        // object -> json string
        if (is_object($data)) {
            $data = json_encode($data);
        }

        // string ber-newline -> pecah per baris
        if (is_string($data)) {
            $data = str_replace(["\r\n", "\r"], "\n", $data);
            return explode("\n", $data);
        }

        // numeric -> string
        if (is_numeric($data)) {
            return [(string)$data];
        }

        // array numerik -> return apa adanya (pastikan isi string)
        if (is_array($data)) {
            $out = [];
            foreach ($data as $v) {
                if (is_object($v) || is_array($v)) $v = json_encode($v);
                $out[] = (string)$v;
            }
            return $out;
        }

        return [];
    };

    // Sanitasi config update (agar versions tidak error kalau time/temp null)
    $sanitizeUpdateCfg = function($resp) use ($log){
        if (!is_object($resp)) return $resp;

        if (!isset($resp->temp) || !$resp->temp) { $resp->temp = 'temp/update_tmp/'; }
        if (!isset($resp->path) || $resp->path === null) { $resp->path = ''; }
        if (!isset($resp->time) || $resp->time === null || $resp->time === '') { $resp->time = 60; }

        $resp->time = (int)$resp->time;

        if (!isset($resp->logs) || !$resp->logs) $resp->logs = 'temp/update.log';
        if (!isset($resp->updatefile) || !$resp->updatefile) $resp->updatefile = 'update_kasir.json';

        return $resp;
    };

    $command = strtolower(trim((string)$this->input->post('command')));
    if ($command === '') {
        echo json_encode(['command kosong']);
        return;
    }

    // TRACE header (sesuai screenshot kamu)
    $log("command diterima: $command");
    $log('ENVIRONMENT: '.ENVIRONMENT);

    $result = null;

        try {
        // Fokus tombol utama
        if ($command === 'ping') {
            $log('masuk branch: ping -> model_update->ping()');
            $result = $this->model_update->ping();

        } elseif ($command === 'versions' || $command === 'versis') {
            $log('masuk branch: versions/versis -> global_command("versions")');
            $response = $this->model_update->global_command('versions');

            if (!is_object($response) || !isset($response->status)) {
                $log('global_command return non-object / tanpa status');
            } else {
                $log('global_command return status: '.$response->status);
            }

            $response = $sanitizeUpdateCfg($response);
            $log('lanjut: model_update->version(response)');
            $result = $this->model_update->version($response);

        } elseif ($command === 'update') {
            $log('masuk branch: update -> update_demo_admin + model_update->update_aplikasi()');
            update_demo_admin($this->session->nama);
            $result = $this->model_update->update_aplikasi($command);

        } elseif ($command === 'patch') {
            $log('masuk branch: patch -> global_command("patch") + model_update->patch()');
            update_demo_admin($this->session->nama);
            $response = $this->model_update->global_command('patch');
            $result = $this->model_update->patch($response);

        } elseif ($command === 'installpatch') {
            $log('masuk branch: installpatch -> global_command("installpatch") + model_update->install_patch()');
            update_demo_admin($this->session->nama);
            $response = $this->model_update->global_command('installpatch');
            $result = $this->model_update->install_patch($response);

        // command lain tetap jalan
        } elseif ($command === 'log') {
            $log('masuk branch: log -> update_demo_admin + model_update->log()');
            update_demo_admin($this->session->nama);
            $result = $this->model_update->log($command);

        } elseif ($command === 'cleartmp') {
            $log('masuk branch: cleartmp -> model_update->cleartmp()');
            $result = $this->model_update->cleartmp();

        } elseif ($command === 'clearlog') {
            $log('masuk branch: clearlog -> model_update->clearlog()');
            $result = $this->model_update->clearlog($command);

        } else {
            $result = "command $command tidak dikenali";
        }

    } catch (\Throwable $e) {
        $log('EXCEPTION: '.$e->getMessage());
        $result = 'ERROR: '.$e->getMessage();
    }


    $bodyLines = $normalizeLines($result);

    // Output akhir: TRACE + blank + body + blank + Selesai (...)
    $final = array_merge(
        $trace,
        [''],
        $bodyLines,
        [''],
        ['Selesai ('.$ms().' ms)']
    );

    echo json_encode($final);
}


public function stream_update_app()
{
    // SSE hanya GET (EventSource)
    $command = strtolower(trim((string)$this->input->get('command')));

    // Header SSE
    @set_time_limit(0);
    @ini_set('output_buffering', 'off');
    @ini_set('zlib.output_compression', 0);

    while (ob_get_level() > 0) { @ob_end_flush(); }
    @ob_implicit_flush(true);

    header('Content-Type: text/event-stream; charset=utf-8');
    header('Cache-Control: no-cache, no-store, must-revalidate');
    header('Pragma: no-cache');
    header('X-Accel-Buffering: no'); // kalau pakai nginx (aman walau apache)
    header('Connection: keep-alive');

    $t0 = microtime(true);

    $send = function(string $msg, string $event = 'line') use ($t0) {
        // prefix waktu biar enak kebaca
        $ms = (int)round((microtime(true) - $t0) * 1000);
        $msg = '[[;#9ca3af;black]['.date('H:i:s').']] [[b;#60a5fa;black]LIVE]] ' . $msg . ' [[;#9ca3af;black]('.$ms.' ms)]';

        echo "event: {$event}\n";
        // boleh multiline: kirim per baris "data:"
        $lines = preg_split("/\r\n|\n|\r/", (string)$msg);
        foreach ($lines as $line) {
            echo "data: " . $line . "\n";
        }
        echo "\n";
        @ob_flush();
        @flush();
    };

    $done = function(array $payload = []) {
        echo "event: done\n";
        echo "data: " . json_encode($payload) . "\n\n";
        @ob_flush();
        @flush();
    };

    if ($command === '') {
        $send('[[b;red;black]command kosong]]');
        $done(['ok'=>false]);
        return;
    }

    // supaya terminal nggak “diam” kalau proses lama
    $send('Mulai proses command: [[b;#eab308;black]'.$command.']]');

    try {
        // emitter untuk dikirim ke model (biar model bisa stream per langkah)
        $emit = function($m) use ($send) {
            $send($m);
        };

        // === mapping command (mirip update_app), tapi streaming ===
        if ($command === 'ping') {
            $send('Menjalankan ping (3x) ...');
            $arr = $this->model_update->ping(); // hasil array
            foreach ((array)$arr as $line) $send((string)$line);

        } elseif ($command === 'log') {
            $send('Ambil log update ...');
            $arr = $this->model_update->log($command);
            if (is_array($arr) && isset($arr['status']) && $arr['status'] === 'log') {
                $send((string)($arr['data'] ?? ''));
            } else {
                foreach ((array)$arr as $line) $send((string)$line);
            }

        } elseif ($command === 'clearlog') {
            $send('Membersihkan log ...');
            $arr = $this->model_update->clearlog($command);
            foreach ((array)$arr as $line) $send((string)$line);

        } elseif ($command === 'cleartmp') {
            $send('Membersihkan folder temp ...');
            $arr = $this->model_update->cleartmp();
            foreach ((array)$arr as $line) $send((string)$line);

        } elseif ($command === 'versions' || $command === 'versis') {
            $send('Ambil konfigurasi update dari server ...');
            $response = $this->model_update->global_command('versions');
            $send('Konfigurasi diterima. Cek versi terbaru ...');

            // versi streaming (model akan ngirim progress)
            $arr = $this->model_update->version($response, $emit);
            foreach ((array)$arr as $line) $send((string)$line);

        } elseif ($command === 'patch') {
            $send('Ambil info patch ...');
            $response = $this->model_update->global_command('patch');
            $arr = $this->model_update->patch($response); // patch ini belum streaming detail per langkah (opsional)
            foreach ((array)$arr as $line) $send((string)$line);

        } elseif ($command === 'installpatch') {
            $send('Mulai install patch ...');
            $response = $this->model_update->global_command('installpatch');
            $arr = $this->model_update->install_patch($response, $emit);
            foreach ((array)$arr as $line) $send((string)$line);

        } elseif ($command === 'update') {
            $send('Mulai update aplikasi ... (ini bisa beberapa menit)');
            $arr = $this->model_update->update_aplikasi($command, $emit);
            foreach ((array)$arr as $line) $send((string)$line);

        } else {
            // fallback: command lain
            $send('Mengirim command ke server update ...');
            $response = $this->model_update->global_command($command);

            if (is_object($response) && isset($response->status) && $response->status === 'versi') {
                $arr = $this->model_update->version($response, $emit);
                foreach ((array)$arr as $line) $send((string)$line);
            } else {
                // minimal tampilkan message/status
                $send('status: ' . (is_object($response) ? ($response->status ?? '(kosong)') : '(bukan object)'));
                if (is_object($response) && isset($response->message)) {
                    if (is_array($response->message)) {
                        foreach ($response->message as $m) $send((string)$m);
                    } else {
                        $send((string)$response->message);
                    }
                } else {
                    $send('[[b;red;black]command tidak dikenali / respon invalid]]');
                }
            }
        }

        $send('Selesai.');
        $done(['ok'=>true]);

    } catch (\Throwable $e) {
        $send('[[b;red;black]ERROR]] ' . $e->getMessage());
        $done(['ok'=>false, 'err'=>$e->getMessage()]);
    }
}

public function stop_update()
{
    file_put_contents(FCPATH . 'temp/update.stop', 'STOP');
    echo json_encode(['status' => 'stopped']);
}



public function check_update_notif()
{
    $this->load->model('Model_update');

    $info = info();
    $current = $info['version'] ?? '0.0.0';

    $latest = $this->Model_update->get_latest_version_only();

    $has_update = false;

    if ($latest && version_compare($latest, $current, '>')) {
        $has_update = true;
    }

    echo json_encode([
        'current'    => $current,
        'latest'     => $latest,
        'has_update' => $has_update
    ]);
}



    }                                                           