<?php

namespace ModernFields\FieldGroups\Services;

defined('ABSPATH') || exit;

/**
 * Field Service
 * 
 * Provides methods to retrieve and display field values in WordPress templates.
 * 
 * @since 1.0.0
 */
class FieldService
{
  /**
   * Display a field value (echoes formatted output)
   * 
   * @since 1.0.0
   * @param string $field_name The name of the field to display
   * @param mixed $context The context of the field (id, taxonomy, option)
   * @return void
   */
  public function theField(string $field_name, mixed $context = null): void
  {
    $value = $this->getField($field_name, $context);

    # Handle different data types
    if (is_bool($value)) {
      echo $value ? '1' : '';
    } elseif (is_int($value) || is_float($value)) {
      echo esc_html((string) $value);
    } elseif (is_string($value)) {
      echo wp_kses_post($value);
    } else {
      # Arrays and objects (repeater, relation…) cannot be rendered as a plain string.
      # Use getField() to retrieve the raw value and handle the display yourself.
      if (defined('WP_DEBUG') && WP_DEBUG) {
        trigger_error(
          sprintf(
            'modern_fields: theField("%s") was called on a non-scalar value (%s). Use getField() instead.',
            esc_html($field_name),
            gettype($value)
          ),
          E_USER_NOTICE
        );
      }
    }
  }

  /**
   * Get a raw field value
   *
   * @since 1.0.0
   * @param string $field_name The name of the field to retrieve
   * @param mixed $context The context of the field (id, taxonomy, option, array with term_id and taxonomy, or WP_Term object)
   * @return string|null The field value or empty string if not found
   */
  public function getField(string $field_name, mixed $context = null): mixed
  {
    # Early return if field name is empty
    if (!$field_name) {
      return "";
    }

    $value = $this->resolveFieldValue($field_name, $context);

    /**
     * Filters a field value before it is returned by getField().
     *
     * Allows third parties to transform the stored value before it reaches
     * the template (e.g. resolve an image attachment ID into its URL).
     *
     * @since 1.1.1
     * @param mixed  $value      The resolved field value.
     * @param string $field_name The name of the field.
     * @param mixed  $context    The context the field was retrieved from.
     */
    $value = apply_filters('modern-fields/get_field/value', $value, $field_name, $context);

    /**
     * Filters a specific field value before it is returned by getField().
     *
     * Dynamic counterpart of the generic filter, scoped to a single field name
     * so handlers don't need to check $field_name themselves.
     *
     * @since 1.1.1
     * @param mixed $value   The resolved field value.
     * @param mixed $context The context the field was retrieved from.
     */
    return apply_filters("modern-fields/get_field/name={$field_name}", $value, $context);
  }

  /**
   * Resolve the raw stored value for a field from its context.
   *
   * @since 1.1.1
   * @param string $field_name The name of the field to retrieve
   * @param mixed $context The context of the field (id, taxonomy, option, array with term_id and taxonomy, or WP_Term object)
   * @return mixed The raw field value or empty string if not found
   */
  protected function resolveFieldValue(string $field_name, mixed $context = null): mixed
  {
    # Option
    if ($context === "option" || $context === "options") {
      return get_option($field_name);
    }

    # Taxonomy/Term
    if (is_string($context) && (str_starts_with($context, "taxonomy_") || str_starts_with($context, "category_") || str_starts_with($context, "tag_"))) {
      $parts = explode('_', $context, 2);
      $term_id = isset($parts[1]) ? (int) $parts[1] : 0;

      if ($term_id > 0) {
        return get_term_meta($term_id, $field_name, true);
      }

      return "";
    }

    # User
    if (is_string($context) && str_starts_with($context, "user_")) {
      $parts = explode('_', $context, 2);
      $user_id = isset($parts[1]) ? (int) $parts[1] : 0;

      if ($user_id > 0) {
        return get_user_meta($user_id, $field_name, true);
      }

      return "";
    }

    # Current Post
    if (!$context || $context === "post") {
      $post_id = get_the_ID();
      return get_post_meta($post_id, $field_name, true);
    }

    # Specific Post
    $post_id = (int) $context;
    return get_post_meta($post_id, $field_name, true);
  }
}
