<?php

class Assets extends CF_Controller
{
    private int $cacheTTL;
    public function __construct()
    {
        parent::__construct();
        $this->load->model('host_model');
        $this->load->model('report_model');
        $this->load->model('note_model');
        $this->load->model('assets_model');
        $this->load->model('advancedreports_model');
        $this->load->driver('cache', ['adapter' => 'file']);
        $this->load->library(['cfe_table']);

        $this->cacheTTL = $this->config->item('five_minutes_cache_ttl');
        $this->username = $this->session->userdata('username');
        setCurrentApplication('engineering');
    }

    public function node_assets()
    {
        $this->load->view('assets/assets-main-node', []);
    }

    public function host_assets($hostkey = '')
    {
        $this->load->helper('elements_creator');
        $requiredjs = [
            ['dist/widgets.bundle.js', 'dist/widgets.bundle.js', false, false],
            ['dist/jquery-scripts.bundle.js', 'dist/jquery-scripts.bundle.js', false, false],
            ['../themes/default/bootstrap/compiled/js/bootstrap.js'],
            ['host-page.js'],
        ];

        $this->carabiner->js($requiredjs);

        $requiredAngularjs = [
            ['dist/angular-base.bundle.js'],

            ['hostInfo/app.js'],
            ['hostInfo/controllers/hostInfoController.js'],
            ['hubManagement/services/hubManagementService.js'],
            ['common_directives/objectsFilter.js'],

            ['dist/ace-editor.bundle.js'],
        ];

        $this->carabiner->js($requiredAngularjs, $requiredAngularjs, $combine = true, $minify = false);

        $username = $this->username;

        $data = [];
        if (!empty($hostkey)) {
            try {
                $hostInfo = $this->host_model->getHostInfo($username, $hostkey, true);
            } catch (Exception $e) {
                $this->show_404();
                return;
            }
            // cache key contains hostkey and last report timestampt
            // this means that data will be automatically refreshed when last report time changed
            // otherwise cache will live for 5 minutes
            $cacheKey = "host_info_page_{$hostkey}_{$hostInfo['lastreport']}";

            if (!($assetsData = $this->cache->get($cacheKey))) {
                $assetsData = [];

                $policiesExecutionInfo = $this->host_model->getPolicyExecutionData($username, $hostkey);

                $hostname = !empty($hostInfo['hostname']) ? $hostInfo['hostname'] : null;
                $ipaddr = !empty($hostInfo['ip']) ? $hostInfo['ip'] : null;
                $lastUpdate = !empty($hostInfo['lastreport']) ? $hostInfo['lastreport'] : null;
                $firstReport = !empty($hostInfo['firstreport']) ? $hostInfo['firstreport'] : null;

                $this->load->model(['eventslog_model', 'hub_management/setup_hub_model']);

                $cfengineRoles = $this->host_model->getHostVariableDataByName($hostkey, 'CFEngine roles');
                $loadAverage = $this->host_model->getHostVariable(
                    $username,
                    $hostkey,
                    'cfe_autorun_inventory_loadaverage',
                    'value',
                );
                $diskFree = $this->host_model->getHostVariableDataByName($hostkey, 'Disk free (%)');
                $isSuperHub = $this->setup_hub_model->isSuperHub();

                $data = [
                    'title' => $this->lang->line('mission_portal_title'),
                    'showHeader' => !is_ajax() ? true : false,
                    'hostkey' => $hostkey,
                    'title' => $this->lang->line('mission_portal_title') . ' - host ' . $ipaddr,
                    'hostname' => $hostname,
                    'ipaddr' => $ipaddr,
                    'last' => $lastUpdate,
                    'firstReport' => $firstReport,
                    'load' => $loadAverage,
                    'free' => $diskFree,
                    'collectionInitiatedBy' => $hostInfo['iscallcollected'] == true ? 'Client' : 'Hub',
                    'lastAgentExecutionTime' => $hostInfo['lastAgentExecutionTime'],
                    'agentExecutionInterval' => $hostInfo['agentexecutioninterval'],
                    'policiesExecutionInfo' => $policiesExecutionInfo,
                    // find if `CFEngine roles` contains `Reporting hub` or `policy_server` (value reported by hubs before 3.24.0)
                    'isHub' =>
                        sizeof(
                            array_filter(
                                ['Reporting hub', 'policy_server'],
                                fn($value) => str_contains($cfengineRoles, $value),
                            ),
                        ) > 0,
                    'isSuperHub' => $isSuperHub,
                ];

                if (isActionAllowed('host-groups-shared.get')) {
                    try {
                        $data['groups'] = $this->host_model->getSharedGroupsByHostkey($hostkey);
                    } catch (Exception $e) {
                        error_log(
                            'Unexpected error calling getSharedGroupsByHostkey(' . $hostkey . '). Exception: ' . $e,
                        );
                        return;
                    }
                } else {
                    $data['groups_access_denied'] = true;
                }

                $software_installed = $this->report_model->getSoftwareInstalled(
                    $this->username,
                    $hostkey,
                    null,
                    null,
                    null,
                    [],
                    [],
                    $rows = 1,
                    $page_number = 1,
                    $hosts_only = false,
                );
                $pathches_available = $this->report_model->getPatches(
                    $this->username,
                    $hostkey,
                    null,
                    null,
                    null,
                    'AVAILABLE',
                    [],
                    [],
                    $rows = 1,
                    $page_number = 1,
                    $hosts_only = false,
                );
                $pathches_installed = $this->report_model->getPatches(
                    $this->username,
                    $hostkey,
                    null,
                    null,
                    null,
                    'INSTALLED',
                    [],
                    [],
                    $rows = 1,
                    $page_number = 1,
                    $hosts_only = false,
                );

                $data['software_installed'] = $software_installed['rowCount'];
                $data['patches_installed'] = $pathches_installed['rowCount'];
                $data['patches_available'] = $pathches_available['rowCount'];

                $data['software_installed_query'] = $software_installed['query'];
                $data['patches_installed_query'] = $pathches_installed['query'];
                $data['patches_available_query'] = $pathches_available['query'];

                $data['software_installed_state'] = base64_encode(
                    json_encode($this->assets_model->getSoftwareInstalledParams($hostkey)),
                );
                $data['patches_available_state'] = base64_encode(
                    json_encode($this->assets_model->getAvailableSoftwareParams($hostkey)),
                );

                $assetsData = array_merge($assetsData, $data, $hostInfo);
                $this->cache->save($cacheKey, $assetsData, $this->cacheTTL);
            }

            if (is_ajax()) {
                $this->load->view('assets/assets-main-host', $assetsData);
            } else {
                $this->template->load('templates/singleColumnTemplate', 'assets/assets-main-host', $assetsData);
            }
        } else {
            if (is_ajax()) {
                $this->load->view('assets/error', []);
            } else {
                $this->template->load('template', 'assets/error', []);
            }
        }
    }

    public function host_assets_by_name($hostName = '')
    {
        $username = $this->username;

        if (!empty($hostName)) {
            $decodedHostName = urldecode($hostName);
            $escapedHostName = $this->db->escape_str($decodedHostName);

            $SQLString = sprintf("SELECT hostkey FROM hosts WHERE hostName='%s'", $escapedHostName);

            $data = $this->advancedreports_model->runQuery($username, $SQLString);

            if (count($data['rows']) === 1) {
                redirect('hosts/' . $data['rows'][0][0]); //$data['rows'][0][0] contain hostkey
            }

            // show user page where he can see what happened.
            // scenarious can be:
            // 1. not able to find host with the given name
            // 2. more than 1 host with the same name.

            $assetsData = [];
            $assetsData['hostName'] = $decodedHostName;

            if (empty($data['rows'])) {
                $this->template->load('templates/singleColumnTemplate', 'assets/assets-host-not-found', $assetsData);
            } elseif (count($data['rows']) > 1) {
                $SQLString = sprintf(
                    'SELECT Hosts.HostKey AS "Host key", Hosts.HostName AS "Host name", Hosts.IPAddress AS "IP address"  FROM Hosts WHERE hostname = \'%s\'',
                    $escapedHostName,
                );

                $data = $this->advancedreports_model->runQuery($username, $SQLString);
                $assetsData['hostData'] = $data['rows'];

                $this->template->load(
                    'templates/singleColumnTemplate',
                    'assets/assets-many-host-with-same-name',
                    $assetsData,
                );
            }
        } else {
            $this->template->load('templates/singleColumnTemplate', 'assets/assets-host-name-empty', $assetsData);
        }
    }
}
