<?php

use idoit\Component\Helper\Unserialize;

/**
 * i-doit Report View which shows all CMDB-Status changes of all objects
 *
 * @package     i-doit
 * @subpackage  Reports
 * @author      Van Quyen Hoang <qhoang@i-doit.com>
 * @copyright   synetics GmbH
 * @license     http://www.i-doit.com/license
 */
class isys_report_view_cmdb_changes extends isys_report_view
{
    /**
     * @return string
     */
    public static function name()
    {
        return 'LC__REPORT__VIEW__CMDB_CHANGES__TITLE';
    }

    /**
     * @return string
     */
    public static function description()
    {
        return 'LC__REPORT__VIEW__CMDB_CHANGES__DESCRIPTION';
    }

    /**
     * @return string
     */
    public function template()
    {
        return isys_module_report::getPath() . 'templates/view_cmdb_changes.tpl';
    }

    /**
     * @return string
     */
    public static function viewtype()
    {
        return 'LC__REPORT__VIEW_TYPE__CMDB_CHANGES';
    }

    /**
     *
     */
    public function start()
    {
        $rules = [
            'C__CMDB_CHANGES__PERIOD_FROM' => [
                'p_strClass' => 'input-small'
            ],
            'C__CMDB_CHANGES__PERIOD_TO'   => [
                'p_strClass' => 'input-small'
            ],
            'C__CMDB_CHANGES__PERSONS'     => [
                'multiselection' => true,
                'catFilter'      => 'C__CATS__PERSON;C__CATS__PERSON_MASTER'
            ],
            'C__CMDB_CHANGES__OBJECTS'     => [
                'multiselection' => true
            ],
        ];

        $ajaxUrl = isys_helper_link::create_url([
            C__GET__AJAX             => 1,
            C__GET__MODULE_ID        => C__MODULE__REPORT,
            C__GET__TREE_NODE        => C__MODULE__REPORT . C__REPORT_PAGE__VIEWS,
            C__GET__REPORT_PAGE      => C__REPORT_PAGE__VIEWS,
            C__GET__REPORT_REPORT_ID => 'isys_report_view_cmdb_changes'
        ]);

        $this->template->activate_editmode()
            ->assign('page_limit', isys_glob_get_pagelimit())
            ->assign('ajax_url', $ajaxUrl)
            ->smarty_tom_add_rules('tom.content.bottom.content', $rules);
    }

    /**
     * @throws \idoit\Exception\JsonException
     */
    public function ajax_request()
    {
        $response = [
            'success' => true,
            'data'    => null,
            'message' => '',
        ];

        try {
            /** @var isys_cmdb_dao $dao */
            $dao = isys_application::instance()->container->get('cmdb_dao');

            // Fetching some translations that will be used a few times.
            $lcTitle = $this->language->get('LC__UNIVERSAL__TITLE_LINK');
            $lcObjectTypeTitle = $this->language->get('LC__CMDB__OBJTYPE');
            $lcObjectSysId = $this->language->get('LC__CMDB__CATG__GLOBAL_SYSID');
            $lcUsername = $this->language->get('LC__CMDB__LOGBOOK__SOURCE__USER');
            $lcLogbookDate = $this->language->get('LC_UNIVERSAL__DATE');
            $lclogbookChanges = $this->language->get('LC__UNIVERSAL__CHANGES');
            // Prepare some other values.
            $emptyValue = isys_tenantsettings::get('gui.empty_value', '-');
            $locale = isys_application::instance()->container->get('locales');

            $conditions = implode(' ', $this->getQueryCondition($dao, $_POST));

            $query = "SELECT isys_obj__id AS 'objectId',
                isys_obj__title AS 'objectTitle',
                isys_obj__sysid AS 'objectSysId',
                isys_logbook__obj_type_static AS 'objectTypeTitle',
                isys_logbook__user_name_static AS 'username',
                isys_logbook__date AS 'logbookDate',
                isys_logbook__changes AS 'logbookChanges'
                FROM isys_catg_logb_list
                INNER JOIN isys_logbook ON isys_logbook__id = isys_catg_logb_list__isys_logbook__id
                INNER JOIN isys_obj ON isys_obj__id = isys_catg_logb_list__isys_obj__id
                WHERE isys_logbook__event_static = 'C__LOGBOOK_EVENT__CATEGORY_CHANGED'
                AND (isys_logbook__changes LIKE '%cmdb\_status%' OR isys_logbook__changes LIKE '%C\_\_OBJ\_\_CMDB\_STATUS%')
                {$conditions};";

            $result = $dao->retrieve($query);

            if (count($result) === 0) {
                throw new Exception($this->language->get('LC__CMDB__FILTER__NOTHING_FOUND_STD'));
            }

            while ($row = $result->get_row()) {
                $objectUrl = isys_helper_link::create_url([C__CMDB__GET__OBJECT => $row['objectId']]);
                $changes = Unserialize::toArray($row['logbookChanges']);

                // Build change string
                $changeKey = isset($changes['C__OBJ__CMDB_STATUS'])
                    ? 'C__OBJ__CMDB_STATUS'
                    : 'isys_cmdb_dao_category_g_global::cmdb_status';

                $from = $changes[$changeKey]['from'] ?? $emptyValue;
                $to = $changes[$changeKey]['to'] ?? $emptyValue;

                $response['data'][] = [
                    $lcTitle           => "<a href=\"{$objectUrl}\">{$row['objectTitle']}</a>",
                    $lcObjectTypeTitle => $this->language->get($row['objectTypeTitle']),
                    $lcObjectSysId     => $row['objectSysId'],
                    $lcUsername        => $row['username'],
                    $lcLogbookDate     => $locale->fmt_datetime($row['logbookDate']),
                    $lclogbookChanges  => "{$from} => {$to}",
                ];
            }
        } catch (Throwable $e) {
            $response = [
                'success' => false,
                'data'    => null,
                'message' => $e->getMessage(),
            ];
        }

        header('Content-Type: application/json');
        echo isys_format_json::encode($response);

        die;
    }

    private function getQueryCondition(isys_cmdb_dao $dao, array $input): array
    {
        $conditions = [];

        $periodFrom = $_POST['C__CMDB_CHANGES__PERIOD_FROM__HIDDEN'] ?? '';
        $periodTo = $_POST['C__CMDB_CHANGES__PERIOD_TO__HIDDEN'] ?? '';
        $contacts = $_POST['C__CMDB_CHANGES__PERSONS__HIDDEN'] ?? '';
        $objects = $_POST['C__CMDB_CHANGES__OBJECTS__HIDDEN'] ?? '';

        // From date
        if (trim($periodFrom) !== '') {
            $date = DateTime::createFromFormat('Y-m-d', $periodFrom);

            if ($date) {
                $conditions[] = ' AND isys_logbook__date >= ' . $dao->convert_sql_text($date->format('Y-m-d 00:00:00'));
            }
        }

        // To date
        if (trim($periodTo) !== '') {
            $date = DateTime::createFromFormat('Y-m-d', $periodTo);

            if ($date) {
                $conditions[] = ' AND isys_logbook__date < ' . $dao->convert_sql_text($date->modify('+1 day')->format('Y-m-d 00:00:00'));
            }
        }

        // Contact objects
        if (isys_format_json::is_json_array($contacts)) {
            $contacts = isys_format_json::decode($contacts);

            if (count($contacts) > 1) {
                $conditions[] = ' AND isys_logbook__isys_obj__id IN (' . implode(',', $contacts) . ')';
            } else {
                $conditions[] = ' AND isys_logbook__isys_obj__id = ' . $dao->convert_sql_id($contacts[0]);
            }
        }

        // Affected objects.
        if (isys_format_json::is_json_array($objects)) {
            $objects = isys_format_json::decode($objects);

            if (count($objects) > 1) {
                $conditions[] = ' AND isys_obj__id IN (' . implode(',', $objects) . ')';
            } else {
                $conditions[] = ' AND isys_obj__id = ' . $dao->convert_sql_id($objects[0]);
            }
        }

        return $conditions;
    }
}
