<?php
declare(strict_types=1);

namespace WP_AUX\Entities\AuxFramework\Partials;

use WP_AUX\Enum\AlertTypeEnum;
use WP_AUX\Enum\IconsEnum;
use WP_AUX\Services\AuxFramework\ElementClassesService;

/**
 * Represents an alert that can be displayed in the user interface.
 * An alert consists of a type, title, content, optional icon,
 * and optional call-to-action (CTA) data.
 *
 * @see https://aggieux.tamu.edu/?path=/docs/components-alert-about-alerts--docs
 * @since 1.0.0
 */
class AlertEntity
{
  protected ?AlertTypeEnum $type;
  protected ?string $title;
  protected ?string $content;
  protected ?IconsEnum $icon;
  protected bool $isBanner = false;
  protected array $cta = [];

  public function __construct(string|AlertTypeEnum|null $type, ?string $title, ?string $content) {
    $this->setType($type);

    $this->title = $title;
    $this->content = $content;
  }

  /**
   * Set the type of the alert with a string or an AlertTypeEnum
   *
   * Invalid types not found in AlertTypeEnum will be ignored.
   *
   * @since 1.0.0
   */
  public function setType(string|AlertTypeEnum|null $type): static
  {
    if (is_string($type)) {
      $type = AlertTypeEnum::tryFrom($type);
    }

    if (!$type) {
      return $this;
    }

    $this->type = $type;

    $this->setIcon($this->type->icon());

    return $this;
  }

  /**
   * Set the icon of the alert with a string or IconsEnum
   *
   * Invalid icons not found in IconsEnum will be ignored.
   *
   * @since 1.0.0
   */
  public function setIcon(string|IconsEnum|null $icon): static
  {
    if (is_string($icon)) {
      $icon = IconsEnum::tryFrom($icon);
    }

    $this->icon = $icon;

    return $this;
  }

  /**
   * Set the Call to Action (CTA) of the alert
   *
   * If a string is provided, it will be used as the URL and the title will default to 'See More'.
   *
   * @since 1.0.0
   */
  public function setCta(string|array|null $cta): static
  {
    if (is_string($cta)) {
      $this->cta = [
        'url' => $cta,
        'title' => 'See More',
      ];
    } else {
      $this->cta = $cta ?? [];
    }

    return $this;
  }

  /**
   * Set the flag to display the alert as a banner or not
   *
   * @since 1.0.0
   */
  public function setIsBanner(bool $isBanner): static
  {
    $this->isBanner = $isBanner;
    return $this;
  }

  /**
   * HTML string value with all settings and properties at the moment the string value is requested
   *
   * @since 1.0.0
   */
  public function __toString(): string
  {
    $alertClasses = ElementClassesService::buildClasses('alert');
    $alertClasses->addModifier($this->type->string());

    $modifier = [];
    if ($this->isBanner) {
      $modifier[] = 'banner';
    }
    if (!empty($this->cta)) {
      $modifier[] = 'cta';
    }

    if ($modifier) {
      $alertClasses->addCompoundModifier($modifier);
    }

    $iconElement = $this->icon ? IconEntity::create($this->icon, false) : '';
    $title = $this->title;
    $content = $this->content;

    $ctaContent = '';
    if ($this->cta) {
      if ($this->isBanner) {
        $ctaContent = sprintf('<a href="%s" class="link--cta">%s</a>', $this->cta['url'], $this->cta['title']);
      } else {
        $ctaIcon = IconEntity::create(IconsEnum::ARROW_RIGHT_LONG, false);
        $ctaContent = sprintf('<a href="%s" class="btn btn--cta-secondary">%s%s</a>', $this->cta['url'], $this->cta['title'], $ctaIcon);
      }
    }

    $content = <<<HTML
        <div class="$alertClasses">
          <div class="alert__content">
            <div class="alert__heading">
              $iconElement
              <h2>$title</h2>
            </div>
            <p class="alert__description">$content</p>
          </div>
          $ctaContent
        </div>
    HTML;

    return $content;
  }

  /**
   * Static method to create an instance of the AlertEntity class
   *
   *  <code>
   *  AlertEntity::create('info', 'Alert Title', 'Alert content goes here.');
   *  </code>
   *
   * @since 1.0.0
   */
  public static function create(string|AlertTypeEnum|null $type, ?string $title, ?string $content): static
  {
    $alert = new static($type, $title, $content);

    return $alert;
  }

  /**
   * Static method to create an instance of the AlertEntity with the banner format
   *
   *  <code>
   *  AlertEntity::createBanner('info', 'Alert Title', 'Alert content goes here.');
   *  </code>
   *
   * @since 1.0.0
   */
  public static function createBanner(string|AlertTypeEnum|null $type, ?string $title, ?string $content): static
  {
    $alert = new static($type, $title, $content);
    $alert->setIsBanner(true);

    return $alert;
  }
}
