<?php

namespace idoit\Module\Forms\Model;

use idoit\Component\Property\Property;
use idoit\Model\Dao\Base;
use idoit\Module\Cmdb\Component\SyncMerger\Config;
use idoit\Module\Cmdb\Component\SyncMerger\Merger;
use idoit\Module\Forms\Blocked;
use isys_cmdb_dao;
use isys_cmdb_dao_category;
use isys_component_database;

class AttributeDefaultValueDao extends Base
{
  /**
   * @var string
   */
  private string $objectTypeConstant = '';

  /**
   * @var string
   */
  private string $categoryConstant = '';

  /**
   * @var array
   */
  private array $templateData = [];

  /**
   * @param isys_component_database $database
   * @param int|null $objectTypeConstant
   *
   * @return AttributeDefaultValueDao
   */
  public static function factory($database, ?int $objectTypeConstant = null)
  {
    $instance = parent::factory($database);

    if ($objectTypeConstant !== null) {
      $instance->loadTemplate($objectTypeConstant);
    }

    return $instance;
  }

  /**
   * @param int $objectType
   *
   * @return bool
   */
  protected function loadTemplate(int $objectType): bool
  {
    $query = 'SELECT isys_obj__id as id FROM isys_obj
      INNER JOIN isys_obj_type ON isys_obj_type__default_template = isys_obj__id
      WHERE isys_obj_type__id = ' . $this->convert_sql_id($objectType);
    $templateInfo = $this->retrieve($query)->get_row();

    if (!$templateInfo) {
      return false;
    }

    $cmdbDao = isys_cmdb_dao::instance($this->get_database_component());
    $result = $cmdbDao->get_all_catg_2_objtype_id($objectType);

    while ($data = $result->get_row()) {
      $categoryClass = $data['isysgui_catg__class_name'];
      $categoryConst = $data['isysgui_catg__const'];

      if (in_array($categoryConst, Blocked::CATEGORIES) || !class_exists($categoryClass)) {
        continue;
      }
      /**
       * @var isys_cmdb_dao_category $categoryDao
       */
      $categoryDao = $categoryClass::instance($this->get_database_component());
      $this->templateData[$categoryConst] = [
          'isMultivalued' => false,
          'data' => []
      ];

      if ($categoryDao->is_multivalued()) {
        $this->templateData[$categoryConst]['isMultivalued'] = true;
        $this->handleMultiValueTemplateEntries($categoryConst, $categoryDao, $templateInfo);
        continue;
      }
      $this->setTemplateEntry($categoryConst, $categoryDao, $templateInfo);
    }

    return true;
  }

  /**
   * @param string                 $categoryConst
   * @param isys_cmdb_dao_category $categoryDao
   * @param array                  $templateInfo
   */
  private function handleMultiValueTemplateEntries(string $categoryConst, isys_cmdb_dao_category $categoryDao, array $templateInfo)
  {
    $result = $categoryDao->get_data(null, $templateInfo['id']);
    if ($result->count() === 0) {
      // At least create one entry to retrieve the default value from the category dao
      $this->setTemplateEntry($categoryConst, $categoryDao, $templateInfo);
      return;
    }

    $table = $categoryDao->get_table();
    while ($data = $result->get_row())
    {
      $entryId = $data[$table . '__id'];
      $fakeEntry = [
          Config::CONFIG_DATA_ID    => $entryId ?? null,
          Config::CONFIG_PROPERTIES => ['id' => $entryId ?? null]
      ];

      $categoryData = Merger::instance(Config::instance($categoryDao, $templateInfo['id'], $fakeEntry))->getDataForSync();
      $this->templateData[$categoryConst]['data'][] = $categoryData;
    }
  }

  /**
   * @param string                 $categoryConst
   * @param isys_cmdb_dao_category $categoryDao
   * @param array                  $templateInfo
   */
  private function setTemplateEntry(string $categoryConst, isys_cmdb_dao_category $categoryDao, array $templateInfo) {
      $table = $categoryDao->get_table();
      $entryId = $categoryDao->get_data(null, $templateInfo['id'])
        ->get_row_value($table . '__id');

      $fakeEntry = [
        Config::CONFIG_DATA_ID    => $entryId ?? null,
        Config::CONFIG_PROPERTIES => ['id' => $entryId ?? null]
      ];

      $categoryData = Merger::instance(Config::instance($categoryDao, $templateInfo['id'], $fakeEntry))->getDataForSync();
      $this->templateData[$categoryConst]['data'][] = $categoryData;
  }

  /**
   * @param string $categoryConstant
   * @param string $property
   *
   * @return mixed|null
   */
  public function getDefaultPropertyValue(string $categoryConstant, string $property)
  {
    if (!isset($this->templateData[$categoryConstant])) {
      return null;
    }

    $data = $this->templateData[$categoryConstant]['data'];
    $isMultiValued = $this->templateData[$categoryConstant]['isMultivalued'];
    if (!$isMultiValued) {
      $data = current($data);
      return $data[Config::CONFIG_PROPERTIES][$property][C__DATA__VALUE] ?? null;
    }

    if (count($data) > 1) {
        return null;
    }

    $data = current($data);
    if ($data[Config::CONFIG_DATA_ID] === null) {
      return $data[Config::CONFIG_PROPERTIES][$property][C__DATA__VALUE] ?? null;
    }

    return null;
  }

  /**
   * @param string $categoryConstant
   *
   * @return array
   */
  public function getDefaultCategoryEntry(string $categoryConstant): array
  {
    if (!isset($this->templateData[$categoryConstant])) {
        return [];
    }

    return current($this->templateData[$categoryConstant]['data']);
  }

  /**
   * @return array
   */
  public function getTemplateEntries(): array
  {
    return $this->templateData;
  }
}
