<?php
declare(strict_types=1);

namespace WP_AUX\Services\Admin\AuxComponents;

use WP_AUX\Entities\Admin\AuxComponents\AuxComponentsAuditComponentEntity;
use WP_AUX\Entities\Admin\AuxComponents\AuxComponentsAuditFieldEntity;
use WP_AUX\Services\HtmlService;

class AuxComponentsAuditFieldService
{
  protected static array $fieldIndicators = [
    'required' => 'Field is required',
    'conditional' => 'Field displays conditionally',
    'collection' => 'Field comes from a Fields Collection',
  ];

  public static function getFieldAuditPath(AuxComponentsAuditFieldEntity $auditField): array
  {
    $parentPathLinks = [];

    $auditPath = $auditField->getFieldAuditPath();
    foreach ($auditPath as $key => $item) {
      if (0 === $key) {
        $parentPathLinks[] = sprintf(
          '<span class="component-details-trigger">%s</span>',
          $item->title
        );
      } else {
        $parentPathLinks[] = sprintf(
          '<span class="field-details-trigger" data-field-row="%s">%s</span>',
          $item->instanceNumber,
          $item->field->getLabel()
        );
      }
    }

    return $parentPathLinks;
  }

  public static function renderFieldsList(AuxComponentsAuditComponentEntity $auditComponent): void
  {
    self::renderComponentFieldsIndicators($auditComponent);
    ?>
    <table class="fields-list">
      <thead>
      <tr>
        <th>Field</th>
        <th>Type</th>
        <th>Path</th>
        <th>Modified</th>
      </tr>
      </thead>
      <tbody>
      <?php
      foreach ($auditComponent->getAuditFields() as $auditField) {
        self::renderComponentFieldRow($auditField);
      }
      ?>
      </tbody>
    </table>
    <?php
    foreach ($auditComponent->getAuditFields() as $auditField) {
      self::renderFieldDetails($auditField);
    }
  }

  protected static function getFieldIndicators(AuxComponentsAuditFieldEntity $auditField): array
  {
    $fieldIndicatorsKeys = [];

    if ($auditField->field->getRequired()->value) {
      $fieldIndicatorsKeys[] = 'required';
    }

    if ($auditField->field->hasConditions()) {
      $fieldIndicatorsKeys[] = 'conditional';
    }

    if ($collectionFilePath = $auditField->getCollectionPath()) {
      $fieldIndicatorsKeys[] = 'collection';
    }

    return array_intersect(array_keys(self::$fieldIndicators), $fieldIndicatorsKeys);
  }

  protected static function getComponentFieldsIndicators(AuxComponentsAuditComponentEntity $auditComponent): array
  {
    $fieldIndicatorsKeys = [];

    foreach ($auditComponent->auditFields as $auditField) {
      $fieldIndicatorsKeys = array_merge($fieldIndicatorsKeys, self::getFieldIndicators($auditField));
    }

    return array_intersect(
      array_keys(self::$fieldIndicators),
      array_unique($fieldIndicatorsKeys)
    );
  }

  public static function renderFieldIndicators(AuxComponentsAuditFieldEntity $auditField): void
  {
    $fieldIndicators = [];

    foreach (self::getFieldIndicators($auditField) as $key) {
      $fieldIndicators[$key] = sprintf(
        '<span class="field-indicator field-%s-indicator" title="%s"></span>',
        $key,
        self::$fieldIndicators[$key]
      );
    }

    echo $fieldIndicators ? sprintf('<div class="field-indicators">%s</div>', join($fieldIndicators)) : '';
  }

  public static function renderComponentFieldsIndicators(AuxComponentsAuditComponentEntity $auditComponent): void
  {
    $fieldIndicators = [];

    $fieldIndicatorsKeys = self::getComponentFieldsIndicators($auditComponent);

    foreach ($fieldIndicatorsKeys as $key) {
      $fieldIndicators[$key] = sprintf(
        '<div><span class="field-indicator field-%s-indicator"></span> <span>%s</span></div>',
        $key,
        self::$fieldIndicators[$key]
      );
    }

    echo $fieldIndicators ? sprintf('<div class="aux-audit-legend"><strong>Legend</strong><div class="field-indicators field-indicators-legend">%s</div></div>', join($fieldIndicators)) : '';
  }

  public static function renderComponentFieldRow(AuxComponentsAuditFieldEntity $auditField, $depth = 0) {
    $field = $auditField->field;
    ?>
    <tr>
      <th data-depth="<?php echo $depth; ?>">
        <a href="javascript: void(0);"
              data-field-row="<?php echo $auditField->instanceNumber; ?>"
              class="component-field-label field-details-trigger">
          <div class="field-label">
            <?php echo $field->getLabel(); ?>
          </div>
          <?php
          self::renderFieldIndicators($auditField);
          ?>
        </a>
      </th>
      <td><?php echo $field->getType()->value; ?></td>
      <td><?php AuxComponentsAuditPageService::renderFilePath(
        $auditField->file->getRelativePath(), $auditField->file->getPathKey()
        ); ?></td>
      <td><?php echo $auditField->file->getDateString('n/j/y h:i a'); ?></td>
    </tr>
    <?php

    if (!empty($auditField->subAuditFields)) {
      foreach ($auditField->subAuditFields as $subAuditField) {
        self::renderComponentFieldRow($subAuditField, $depth+1);
      }
    }
  }

  public static function renderFieldDetails(AuxComponentsAuditFieldEntity $auditField)
  {
    $field = $auditField->field;
    ?>
    <div class="field-details" id="field-details-<?php echo $auditField->instanceNumber; ?>">
      <div class="field-parent-path">
        <?php echo join(' ', self::getFieldAuditPath($auditField)); ?>
      </div>
      <?php
      AuxComponentsAuditPageService::renderDetailsBlock(
        $field->getLabel(),
        $field->getInstructions(),
        $auditField->file,
        $auditField->parentClassFile
      );

      if ($collectionFilePath = $auditField->getCollectionPath()) {
        ?>
        <div class="field-details-section field-collection">
          <h3>Fields Collection</h3>
          <div>
            This field is included through a "Fields Collection" defined in
            <?php AuxComponentsAuditPageService::renderFilePath($collectionFilePath, 'collection'); ?>.
          </div>
        </div>
        <?php
      }

      if ($conditionsString = self::conditionalLogicString($auditField->conditionalLogic)) {
        ?>
        <div class="field-details-section field-conditions">
          <h3>Conditions</h3>
          <div>
            <?php echo $conditionsString; ?>
          </div>
        </div>
        <?php
      }
      ?>
      <div class="field-details-section field-use">
        <h3>Use</h3>
        Access the value of this field with:
        <div class="field-use-options">
          <?php echo self::getFieldSingleUse($auditField->field->getKey()); ?>
          <?php echo self::getFieldArrayUse($auditField->field->getKey()); ?>
        </div>
      </div>
      <?php
      AuxComponentsAuditFieldPropertiesService::renderFieldPropertiesTable($auditField);
      ?>
    </div>
    <?php
    if (!empty($auditField->subAuditFields)) {
      foreach ($auditField->subAuditFields as $subAuditField) {
        self::renderFieldDetails($subAuditField);
      }
    }
  }

  public static function getFieldSingleUse(string $key): string
  {
    return sprintf("<pre data-use-type='Alone'>\$thisFieldValue = get_field('%s');</pre>", $key);
  }

  public static function getFieldArrayUse(string $key): string
  {
    return sprintf(
      "<pre data-use-type='In Array'>\$fields = get_fields();\n\$thisFieldValue = \$fields['%s'];</pre>",
      $key
    );
  }

  public static function conditionalLogicString($conditionalLogic)
  {
    $ors = [];

    foreach ($conditionalLogic as $group) {
      $ands = [];
      foreach ($group as $condition) {
        $field = new $condition[0];

        $value = $condition[2];
        if ($value instanceof \UnitEnum) {
          $value = $value->value;
        }

        $ands[] = '"' . $field->getLabel() . '" field value is ' . $condition[1]->label() . ' "' . $value . '"';
      }

      if (!empty($ands)) {
        $ors[] = join(' AND ', $ands);
      }
    }

    if (empty($ors)) {
      return '';
    }

    return 'This field is shown if ' . join(', OR if ', $ors) . '.';
  }
}
