<?php

namespace ModernFields\FieldGroups\Locations\Hooks;

use ModernFields\FieldGroups\Locations\Location;
use ModernFields\FieldGroups\Locations\UseCases\SaveFieldsUseCase;
use ModernFields\FieldGroups\Locations\UseCases\GroupAssetsLoaderUseCase;
use ModernFields\FieldGroups\Repositories\TermRepository;
use ModernFields\FieldGroups\Repositories\FieldGroupRepository;
use ModernFields\WordPress\Security\SecurityHelper;
use ModernFields\WordPress\Interfaces\Hooks;

defined('ABSPATH') || exit;

/**
 * TermLocation Class
 *
 * Handles the integration of Modern Fields fields into the WordPress term edit page.
 * This class is responsible for:
 * - Registering required hooks for displaying fields on term edit pages
 * - Enqueuing necessary scripts and styles for the field interface
 * - Preparing and injecting inline styles for field blocks
 * - Registering term meta fields dynamically for REST API access
 * 
 * @since 1.0.0
 */
class TermLocation extends Location implements Hooks
{
  /**
   * Register the WordPress hooks required for the term location.
   * 
   * @since 1.0.0
   * @return void
   */
  public function registerHooks(): void
  {
    add_action('admin_enqueue_scripts', [$this, 'enqueueAssets']);
    add_action('init', [$this, 'registerTermFormHooks']);
    add_action('edited_term', [$this, 'saveFields'], 10);
    add_action('created_term', [$this, 'saveFields'], 10);
  }

  /**
   * Register hooks for all taxonomies to display fields on term edit/add forms.
   * 
   * @since 1.0.0
   * @return void
   */
  public function registerTermFormHooks(): void
  {
    $taxonomies = get_taxonomies(['public' => true], 'names');

    foreach ($taxonomies as $taxonomy) {
      add_action("{$taxonomy}_edit_form_fields", [$this, 'renderFieldsGroups'], 10);
      add_action("{$taxonomy}_add_form_fields", [$this, 'renderFieldsGroups'], 10);
    }
  }

  /**
   * Checks if the current admin screen is a term edit page.
   * 
   * @since 1.0.0
   * @return bool True if the current screen is a term edit page, false otherwise.
   */
  protected function isTermEditPage(): bool
  {
    # Check if the current admin page is a term edit page
    $allowed_pages = ['term.php', 'edit-tags.php'];
    if (!SecurityHelper::isCurrentAdminPage($allowed_pages)) {
      return false;
    }

    return true;
  }

  /**
   * Enqueue assets for the term edit React application.
   * 
   * Loads the necessary JavaScript and CSS assets for rendering field groups
   * on the term edit/add page. Only enqueues assets if the current screen is
   * a term edit page and field groups exist.
   * 
   * @since 1.0.0
   * @return void
   */
  public function enqueueAssets(): void
  {
    if (!$this->isTermEditPage()) {
      return;
    }

    $taxonomy = isset($_GET['taxonomy']) ? sanitize_text_field(wp_unslash($_GET['taxonomy'])) : '';

    $field_groups = FieldGroupRepository::getTermFieldGroups($taxonomy);

    if (empty($field_groups)) {
      return;
    }

    # Build context with term data if available (edit form), or empty for add form
    $context = [];
    if (isset($_GET['tag_ID']) && absint($_GET['tag_ID']) > 0) {
      $term_id = absint($_GET['tag_ID']);
      $term = TermRepository::getTermById($term_id);
      if (!$term) {
        return;
      }
      $context['term'] = $term->toArray();
    }

    $groupAssetsLoaderUseCase = new GroupAssetsLoaderUseCase('term-fields', $field_groups, $context);
    $groupAssetsLoaderUseCase->execute();
  }

  /**
   * Render the term fields for the given term.
   * 
   * Outputs the root container divs for each field group that will be
   * populated by the React application. Each container includes a data
   * attribute with the field group ID for React to mount the component.
   *
   * @since 1.0.0
   * @return void
   */
  public function renderFieldsGroups(): void
  {
    $taxonomy = isset($_GET['taxonomy']) ? sanitize_text_field(wp_unslash($_GET['taxonomy'])) : '';

    $field_groups = FieldGroupRepository::getTermFieldGroups($taxonomy);

    if (empty($field_groups)) {
      return;
    }

    # Edit form
    if (isset($_GET['tag_ID']) && absint($_GET['tag_ID']) > 0) {
      foreach ($field_groups as $field_group) {
        echo '<tr class="form-field mf-term-fields-row">';
        echo '<th scope="row"><label>' . esc_html__('Additional data', 'modern-fields') . '</label></th>';
        echo '<td>';
        echo '<div class="mf-term-fields-root" data-page="edit" data-group-id="' . esc_attr($field_group->getId()) . '"></div>';
        echo '</td>';
        echo '</tr>';
      }
    } else {
      foreach ($field_groups as $field_group) {
        echo '<div class="mf-term-fields-root" data-page="add" data-group-id="' . esc_attr($field_group->getId()) . '"></div>';
      }
    }
  }

  /**
   * Save the term fields for the given term.
   * 
   * Handles saving field values when the term is updated or created. Validates
   * the nonce and user capabilities before processing the save operation.
   *
   * @since 1.0.0
   * @param int $term_id The ID of the term to save the fields for.
   * @return void
   */
  public function saveFields($term_id): void
  {
    # Verify nonce: for edit use 'update-tag_' . $term_id, for creation use 'add-tag'
    $nonce_valid = SecurityHelper::checkNonce('_wpnonce', 'update-tag_' . $term_id) || SecurityHelper::checkNonce('_wpnonce_add-tag', 'add-tag');

    if (!$nonce_valid) {
      return;
    }

    if (!current_user_can('edit_term', $term_id)) {
      return;
    }

    $term = TermRepository::getTermById($term_id);

    if (!$term) {
      return;
    }

    $taxonomy = $term->getTaxonomy();
    $field_groups = FieldGroupRepository::getTermFieldGroups($taxonomy);

    $saveFieldsUseCase = new SaveFieldsUseCase($term, $field_groups);
    $saveFieldsUseCase->execute();
  }
}
