<?php
declare(strict_types=1);

namespace WP_AUX\Services\Admin\AuxComponents;

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

class AuxComponentsAuditFieldPropertiesService
{

  public static array $ignoreFieldProperties = [
    'arrayPropertiesMethods',
    'key',
    'title',
    'overrideName',
    'initConditionalLogic',
    'wrapper',
    'conditionalLogicSet',
    'fieldsCollection',
    'fieldsSet',
  ];

  public static array $automaticFieldValueProperties = [
    'key',
  ];

  public static function getPropertyDeclarationLine(string $filePath, string $propertyName, bool $debug = false): ?int
  {
    $classFile = new \SplFileObject($filePath);

    foreach ($classFile as $line => $content) {
      if (preg_match(
        '/
            (private|protected|public|var) # match visibility or var
            \s+
            (static[\s]+)?
            ([a-zA-Z_\?\|\\\]*) # optional type statement
            \s+
            \$' . $propertyName . '
        /x',
        $content)
      ) {
        return $line + 1;
      }
    }

    return null;
  }

  public static function getFieldPropertyOptions(\UnitEnum|string $enum): string
  {
    $cases = $enum::cases();

    if (count($cases) > 12) {
      $options = [count($cases) . ' options'];
    } else {
      $options = [];
      foreach ($cases as $case) {
        $options[] = '<div><span>' . $case->name . '</span> <span>' . $case->value . '</span></div>';
      }
    }

    return sprintf(
      '<div class="field-property-options">%s</div>',
      join($options)
    );
  }

  public static function renderFieldPropertiesTable(AuxComponentsAuditFieldEntity $auditField): void
  {
    ?>
    <div class="field-details-section">
      <h3>Properties</h3>
      <?php
      self::renderPropertiesLegend($auditField->auditProperties);
      ?>
      <table class="field-properties">
        <thead>
        <tr>
          <th>File/Ln.</th>
          <th>Property</th>
          <th>Value Type</th>
          <th>Value</th>
        </tr>
        </thead>
        <tbody>
        <?php
        foreach ($auditField->auditProperties as $auditProperty) {
          $propertyOptions = $valueOptions = '';

          if ('options' === $auditProperty->getValueType()) {
            $valueOptions = self::getFieldPropertyOptions($auditProperty->getValue());
          }

          if ('options' === $auditProperty->getParameterTypeString()) {
            $propertyOptions = self::getFieldPropertyOptions($auditProperty->getValue());
          }

          $formattedDisplayValue = $auditProperty->getDisplayValue();
          if (is_null($formattedDisplayValue)) {
            $formattedDisplayValue = '<em>null</em>';
          } elseif ('' === $formattedDisplayValue) {
            $formattedDisplayValue = '<em>empty</em>';
          }
          ?>
          <tr>
            <td class="field-property-source-cell">
              <?php
              if ($declarationFile = $auditProperty->getDeclarationFile()) {
                echo sprintf(
                  '<span class="field-property-declared-at field-property-declared-at-%s" data-tippy-content="%s">%s</span>',
                  $declarationFile->getPathLetter(),
                  $declarationFile->getRelativePath(),
                  $auditProperty->getDeclarationLine()
                );
              }
              ?>
            </td>
            <th class="field-property-name-cell">
              <div><?php echo $auditProperty->getName(); ?></div>
            </th>
            <td>
              <div
                class="field-property-type field-property-type-<?php echo $auditProperty->getParameterTypeString(); ?>">
                <?php echo $auditProperty->getParameterType(); ?>
              </div>
              <?php echo $propertyOptions; ?>
            </td>
            <td class="field-property-value-cell">
              <div
                class="field-property-value field-property-value-<?php echo $auditProperty->getValueType(); ?>">
                <?php echo $formattedDisplayValue; ?>
              </div>
              <?php echo $valueOptions; ?>
            </td>
          </tr>
          <?php
        }
        ?>
        </tbody>
      </table>
    </div>
    <?php
  }

  /**
   * @param AuxComponentsAuditFieldPropertyEntity[] $auditProperties
   */
  public static function renderPropertiesLegend($auditProperties): void
  {
    $declaredAts = [
      'F' => ['field file', null],
      'B' => ['base field-type file', null],
      'R' => ['root field file', null],
      'T' => ['a shared traits file', null],
    ];

    foreach ($auditProperties as $auditProperty) {
      if ($declarationFile = $auditProperty->getDeclarationFile()) {
        $declaredAts[$declarationFile->getPathLetter()][2] = true;
      }
    }
    ?>
    <div class="aux-audit-legend field-properties-legend">
      <strong>Legend</strong>
      <table>
        <?php
        foreach ($declaredAts as $declaredAtKey => $declaredAt) {
        ?>
        <tr>
          <td class="field-property-source-cell">
            <?php
            echo sprintf(
              '<span class="field-property-declared-at field-property-declared-at-%s">#</span>',
              $declaredAtKey
            );
            ?>
          </td>
          <td>
            <?php
            echo sprintf(
              'Value from %s',
              $declaredAt[0] . ' at line #'
            );
            ?>
          </td>
        </tr>
        <?php
        }
        ?>
      </table>
    </div>
    <?php
  }
}
