<?php

global $g_comp_database, $g_comp_database_system;

// Set migrationId
$migrationIdentifier = 'migrate_validation_and_attribute_visibility';

// Check whether migration was executed before
if ($this->is_migration_done($migrationIdentifier)) {
    $g_migration_log[] = '<span class="bold">Validation and attribute visibility migration has already been processed</span>';
} else {
    $g_migration_log[] = '<span class="bold">Migrate validation and attribute visibility configuration...</span>';

    $dao = new \isys_cmdb_dao($g_comp_database);
    $daoSystem = new \isys_cmdb_dao($g_comp_database_system);

    if (!function_exists('getDefaultConfiguration')) {
        function getDefaultConfiguration(string $className, string $constant, string $propertyKey): array
        {
            return [
                'propertyReference'  => "{$constant}::{$propertyKey}",
                'className'          => $className,
                'propertyKey'        => $propertyKey,
                'dao'                => null,
                'visible'            => true,
                'visibleOverview'    => true,
                'mandatory'          => false,
                'uniqueObject'       => false,
                'uniqueObjectType'   => false,
                'uniqueGlobal'       => false,
                'validation'         => null,
                'validationOption'   => null
            ];
        }
    }

    $tenantDatabaseName = $dao->convert_sql_text($g_comp_database->get_db_name());
    $tenantId = (int)$daoSystem
        ->retrieve("SELECT isys_mandator__id AS id FROM isys_mandator WHERE isys_mandator__db_name = {$tenantDatabaseName} LIMIT 1;")
        ->get_row_value('id');

    $readValidationQuery = "SELECT * FROM isys_validation_config;";

    $migratedData = [];
    $result = $dao->retrieve($readValidationQuery);

    while ($row = $result->get_row()) {
        $properties = json_decode($row['isys_validation_config__json'], true);

        foreach ($properties as $property => $option) {
            $daoClassName = $row['isys_validation_config__category_class'];

            if (!class_exists($daoClassName)) {
                $g_migration_log[] = '<span class="indent text-red">Class does not exists "' . $daoClassName . '". Skipping configuration."</span>';
                continue;
            }

            $categoryDao = new $daoClassName($g_comp_database);
            $constant = $categoryDao->get_category_const();

            if ($daoClassName === 'isys_cmdb_dao_category_g_custom_fields' && $row['isys_validation_config__isysgui_catg_custom__id'] > 0) {
                /** @var isys_cmdb_dao_category_g_custom_fields $categoryDao */
                $categoryDao->set_catg_custom_id($row['isys_validation_config__isysgui_catg_custom__id']);
                $constant = $categoryDao->get_catg_custom_const();
            }

            $configuration = getDefaultConfiguration($daoClassName, $constant, $property);
            $configuration['dao'] = $categoryDao;

            $configuration['gId'] = $row['isys_validation_config__isysgui_catg__id'];
            $configuration['cId'] = $row['isys_validation_config__isysgui_catg_custom__id'];
            $configuration['sId'] = $row['isys_validation_config__isysgui_cats__id'];
            $configuration['mandatory'] = $option['check']['mandatory'] ?? false;
            $configuration['uniqueObject'] = $option['check']['unique_obj'] ?? false;
            $configuration['uniqueObjectType'] = $option['check']['unique_objtype'] ?? false;
            $configuration['uniqueGlobal'] = $option['check']['unique_global'] ?? false;
            $configuration['validation'] = $option['check']['validation'][0] ?? null;
            $configuration['validationOption'] = $option['check']['validation'][1] ?? null;

            if ($configuration['validation'] && is_array($configuration['validationOption']) && !empty($configuration['validationOption'])) {
                $configuration['validationOption'] = json_encode($configuration['validationOption']);
            } else {
                $configuration['validationOption'] = null;
            }

            $migratedData["{$daoClassName}::{$property}"] = $configuration;
        }
    }

    $readAttributeVisibilityQuery = "SELECT *
        FROM isys_settings
        WHERE isys_settings__key LIKE 'cmdb.attribute-visibility.%'
        AND isys_settings__isys_mandator__id = {$tenantId};";

    $result = $daoSystem->retrieve($readAttributeVisibilityQuery);
    $constantMap = [];

    while ($row = $result->get_row()) {
        $properties = json_decode($row['isys_settings__value'], true);

        foreach ($properties as $options) {
            // Skip the attribute, if it is not hidden.
            if (!$options['isHidden'] && !$options['hideInOverview']) {
                continue;
            }

            $categoryConstant = $dao->convert_sql_text($options['categoryConstant']);
            $retrieveClassNameQuery = "SELECT isysgui_catg__class_name AS className, isysgui_catg__id AS id
                FROM isysgui_catg
                WHERE isysgui_catg__const = {$categoryConstant}

                UNION

                SELECT isysgui_cats__class_name AS className, isysgui_cats__id AS id
                FROM isysgui_cats
                WHERE isysgui_cats__const = {$categoryConstant}

                UNION

                SELECT isysgui_catg_custom__class_name AS className, isysgui_catg_custom__id AS id
                FROM isysgui_catg_custom
                WHERE isysgui_catg_custom__const = {$categoryConstant};";

            if (!isset($constantMap[$options['categoryConstant']])) {
                $data = $dao->retrieve($retrieveClassNameQuery)->get_row();

                if (empty($data)) {
                    $g_migration_log[] = '<span class="indent text-red">No data found for constant "' . $categoryConstant . '". Skipping entry."</span>';
                    continue;
                }

                $constantMap[$options['categoryConstant']] = $data;
            }

            $className = $constantMap[$options['categoryConstant']]['className'];
            $id = $constantMap[$options['categoryConstant']]['id'];

            if ($className === '') {
                $g_migration_log[] = '<span class="indent text-red">The class for "' . $categoryConstant . '" is empty. Please check the entry with ID: "'. $id .' in isysgui_catg, isysgui_cats or isysgui_catg_custom."</span>';
                continue;
            }

            if (!class_exists($className)) {
                $g_migration_log[] = '<span class="indent text-red">The class "' . $className . '" does not exist. Please check the entry with ID: "'. $id .' in isysgui_catg, isysgui_cats or isysgui_catg_custom.</span>';
                continue;
            }

            $property = $options['propertyKey'];

            $configuration = $migratedData["{$className}::{$property}"] ?? getDefaultConfiguration($className, $options['categoryConstant'], $property);

            if (!isset($configuration['dao'])) {
                $configuration['dao'] = new $className($g_comp_database);

                if ($className === 'isys_cmdb_dao_category_g_custom_fields' && $constantMap[$options['categoryConstant']]['id'] > 0) {
                    /** @var isys_cmdb_dao_category_g_custom_fields $configuration['dao'] */
                    $configuration['dao']->set_catg_custom_id($constantMap[$options['categoryConstant']]['id']);

                    $configuration['cId'] = $constantMap[$options['categoryConstant']]['id'];
                } elseif (strpos($className, 'isys_cmdb_dao_category_g') === 0) {
                    $configuration['gId'] = $constantMap[$options['categoryConstant']]['id'];
                } else {
                    $configuration['sId'] = $constantMap[$options['categoryConstant']]['id'];
                }
            }

            $configuration['visible'] = !$options['isHidden'];
            $configuration['visibleOverview'] = !$options['hideInOverview'];

            $migratedData["{$className}::{$property}"] = $configuration;
        }
    }

    foreach ($migratedData as $entry) {
        try {
            // Set the UI ID.
            if (empty($entry['uiId'])) {
                $propertyDefinition = $entry['dao']->get_property_by_key($entry['propertyKey']);

                if ($entry['dao'] instanceof isys_cmdb_dao_category_g_custom_fields && $entry['propertyKey'] !== 'description') {
                    $entry['uiId'] = 'C__CATG__CUSTOM__' . $propertyDefinition[C__PROPERTY__UI][C__PROPERTY__UI__ID];
                } else {
                    $entry['uiId'] = $propertyDefinition[C__PROPERTY__UI][C__PROPERTY__UI__ID];
                }
            }

            // Process validation
            if (!empty($entry['validation'])) {
                $entry['validation'] = $dao->convert_sql_text($entry['validation']);
            } else {
                $entry['validation'] = 'NULL';
            }

            // Process validation options.
            if (!empty($entry['validationOption'])) {
                $entry['validationOption'] = $dao->convert_sql_text($entry['validationOption']);
            } else {
                $entry['validationOption'] = 'NULL';
            }

            $createEntryQuery = "INSERT IGNORE INTO isys_property_config SET
                isys_property_config__property_reference = {$dao->convert_sql_text($entry['propertyReference'])},
                isys_property_config__isysgui_catg__id = {$dao->convert_sql_id($entry['gId'])},
                isys_property_config__isysgui_catg_custom__id = {$dao->convert_sql_id($entry['cId'])},
                isys_property_config__isysgui_cats__id = {$dao->convert_sql_id($entry['sId'])},
                isys_property_config__ui_id = {$dao->convert_sql_text($entry['uiId'])},
                isys_property_config__visible = {$dao->convert_sql_boolean($entry['visible'])},
                isys_property_config__visible_overview = {$dao->convert_sql_boolean($entry['visibleOverview'])},
                isys_property_config__mandatory = {$dao->convert_sql_boolean($entry['mandatory'])},
                isys_property_config__unique_object = {$dao->convert_sql_boolean($entry['uniqueObject'])},
                isys_property_config__unique_object_type = {$dao->convert_sql_boolean($entry['uniqueObjectType'])},
                isys_property_config__unique_global = {$dao->convert_sql_boolean($entry['uniqueGlobal'])},
                isys_property_config__validation = {$entry['validation']},
                isys_property_config__validation_option = {$entry['validationOption']};";

            $dao->update($createEntryQuery) && $dao->apply_update();

            $g_migration_log[] = '<span class="indent">Migrated validation and attribute-visibility for field "' . $entry['propertyReference'] . '".</span>';
            $migratedTables++;
        } catch (Exception $e) {
            $g_migration_log[] = '<span class="indent text-red">Error: ' . $e->getMessage() . '</span>';
            $errors++;
        }
    }

    $g_migration_log[] = '<span class="bold">Migration finished!</span>';

    $this->migration_done($migrationIdentifier);
}
