<?php
declare(strict_types=1);

namespace WP_AUX\Services\AuxCF;

use AuxCF\Entities\Field\GroupFieldEntity;
use AuxCF\Entities\Settings\Enum\OperatorEnum;
use WP_AUX\Entities\AuxCF\Fields\CuratedCollection\CuratedCollectionVariationFieldEntity;
use WP_AUX\Entities\AuxCF\Fields\Section\SectionRowAnchorFieldEntity;
use WP_AUX\Entities\AuxFramework\Partials\SectionEntity;
use WP_AUX\Entities\AuxFramework\Partials\SectionIntroEntity;
use WP_AUX\Entities\AuxFramework\Partials\SlabEntity;

class BlocksService
{
  /**
   * Get an array of block variations data from both the parent and child theme
   * @since 1.0.0
   */
  public static function getBlockVariations(string $blockName, array $additionalData = []): array
  {
    $variations = [];

    $try = [
      get_template_directory(),
      get_stylesheet_directory(),
    ];

    $dataFields = [
      'Name' => 'Name',
      'Description' => 'Description',
      'Post Types' => 'Post Types',
    ];

    if (!empty($additionalData)) {
      $dataFields = array_replace_recursive($dataFields, $additionalData);
    }

    foreach ($try as $tryDir) {
      $blockDir = $tryDir . '/blocks/' . $blockName;
      $variationsFiles = @glob($blockDir . '/variations/*.php');

      foreach ($variationsFiles as $variationFile) {
        $fileKey = pathinfo($variationFile, PATHINFO_FILENAME);

        $variations[$fileKey] = get_file_data($variationFile, $dataFields);
      }
    }

    return $variations;
  }

  /**
   * Get the variations options as a key => label array for block editor choices
   * @since 1.0.0
   */
  public static function getBlockVariationsChoices(string $blockName): array
  {
    $choices = [];

    $variations = self::getBlockVariations($blockName);

    foreach ($variations as $variationKey => $variation) {
      $choices[$variationKey] = '<strong>' . ($variation['Name'] ?? $variationKey) . '</strong>';

      if (!empty($variation['Description'])) {
        $choices[$variationKey] .= ': ' . $variation['Description'];
      }
    }

    return $choices;
  }

  /**
   * Get default variation value for a block
   *
   * Specify a variation as the default by adding "Default: true" to the file
   * header comments of that variation file.
   *
   * @since 1.0.0
   */
  public static function getBlockVariationsDefault(string $blockName): ?string
  {
    $default = null;

    if ($variations = self::getBlockVariations($blockName, ['Default' => 'Default'])) {
      $defaultIndex = array_search(true, array_column($variations, 'Default'));

      if ($defaultIndex !== false) {
        $default = array_keys($variations)[$defaultIndex];
      }
    }

    return $default;
  }

  /**
   * Get the conditional logic for blocks that have variations
   * @since 1.0.0
   */
  public static function addVariationsSectionsConditionalLogic(string $blockName, int $threshold, GroupFieldEntity $group): array
  {
    $conditionalLogic = [];

    $variations = BlocksService::getBlockVariations(
      $blockName,
      [
        'Curated Sections' => 'Curated Sections',
      ]
    );

    foreach ($variations as $variationKey => $variation) {
      if (empty($variation['Curated Sections'])) {
        continue;
      }

      if ($variation['Curated Sections'] >= $threshold) {
        $group->addCondition(
          CuratedCollectionVariationFieldEntity::class,
          OperatorEnum::EQUALS,
          $variationKey
        );
      }
    }

    return $conditionalLogic;
  }

  /**
   * Get section intro entity partial for current block
   * @since 1.0.0
   */
  public static function getSectionIntro(bool $setStyleOnIntro = false): SectionIntroEntity
  {
    $sectionIntro = SectionIntroEntity::create()
      ->setDescription(aux_get_field('section_description'));

    $sectionIntro->addHeader(
      aux_get_field('section_heading'),
      null,
      aux_get_field('section_superheader'),
      aux_get_field('section_subheader')
    );

    $sectionCtas = aux_get_field('section_ctas');
    if ($sectionCtas) {
      foreach ($sectionCtas as $sectionCta) {
        $sectionIntro->addCta($sectionCta['section_cta_link']);
      }
    }

    if ($setStyleOnIntro) {
      $sectionIntro->setStyle(aux_get_field('section_style'));
    }

    return $sectionIntro;
  }

  /**
   * Get current cleaned row anchor/id value from AUX block editor
   * @since 1.0.1
   */
  public static function getRowAnchor(): string
  {
    $anchor = '';

    if ($rowAnchor = aux_get_field(SectionRowAnchorFieldEntity::$name)) {
      $anchor = preg_replace("/[^a-zA-Z0-9-_]+/", "", $rowAnchor);
    }

    return $anchor;
  }

  /**
   * Get the AUX section entity partial for a block
   *
   * If the block has a section intro, it will be made and added to the section.
   * In rare cases the section style is applied to the section intro instead of the section.
   *
   * @since 1.0.0
   */
  public static function getSection(string $componentClass, bool $hasIntro = true, bool $styleOnIntro = false): SectionEntity
  {
    $section = SectionEntity::create(
      $componentClass,
      aux_get_field('section_background'),
      $styleOnIntro ? null : aux_get_field('section_style'),
    );

    $section->setId(self::getRowAnchor());

    if ($hasIntro) {
      $sectionIntro = self::getSectionIntro($styleOnIntro);
      $section->setSectionIntro($sectionIntro);
    }

    /**
     * For blocks that use the WP_AUX::renderAuxBlock() 'renderCallback' property in block.json,
     * we can add context to the section partial from the Gutenberg block data
     */
    if ($blockHandler = \WP_AUX::instance()->getCurrentBlockHandler()) {
      $blockData = $blockHandler->getBlockData();

      $section->addSectionDataValue('section', $blockHandler->getSlug());

      // Additional classes from the Advanced tab for this block
      if (!empty($blockData['className'])) {
        $section->addSectionClass($blockData['className']);
      }
    }

    return $section;
  }

  /**
   * Get the AUX slab entity partial for a block
   * @since 1.0.1
   */
  public static function getSlab(string $componentClass): SlabEntity
  {
    $slab = SlabEntity::create(
      $componentClass,
      aux_get_field('section_solid_background'),
      aux_get_field('section_style'),
    );

    $slab->setId(self::getRowAnchor());
    $slab->setHeading(aux_get_field('slab_intro_heading'));
    $slab->setSuperheader(aux_get_field('slab_intro_superheader'));
    $slab->setSubheader(aux_get_field('slab_intro_subheader'));
    $slab->setDescription(aux_get_field('slab_intro_description'));

    if ($slabIcon = aux_get_field('slab_intro_icon')) {
      $slab->setIcon($slabIcon);
    }

    if ($slabCta = aux_get_field('slab_intro_cta_link')) {
      $slab->setCta($slabCta);
    }

    /**
     * For blocks that use the WP_AUX::renderAuxBlock() 'renderCallback' property in block.json,
     * we can add context to the slab partial from the Gutenberg block data
     */
    if ($blockHandler = \WP_AUX::instance()->getCurrentBlockHandler()) {
      $blockData = $blockHandler->getBlockData();

      $slab->addSectionDataValue('section', $blockHandler->getSlug());

      // Additional classes from the Advanced tab for this block
      if (!empty($blockData['className'])) {
        $slab->addSectionClass($blockData['className']);
      }
    }

    return $slab;
  }
}
