<?php

namespace ModernFields\PostTypes\Hooks;

use ModernFields\WordPress\Interfaces\Hooks;

defined('ABSPATH') || exit;

/**
 * Reads post type definitions stored in the DB and registers them with WordPress.
 *
 * Runs at `init` with a low priority so the storage CPT is already registered
 * before we query it.
 *
 * @since 1.0.0
 */
class PostTypesRegistration implements Hooks
{
  public function registerHooks(): void
  {
    # Priority 20 so the storage CPT (priority default 10) is ready first
    add_action('init', [$this, 'registerPostTypes'], 20);
  }

  /**
   * Queries all published mf_post_type definitions and registers each one.
   */
  public function registerPostTypes(): void
  {
    $posts = get_posts([
      'post_type'      => MODERN_FIELDS_POST_TYPES_CPT_SLUG,
      'post_status'    => 'publish',
      'posts_per_page' => -1,
    ]);

    foreach ($posts as $post) {
      $config = $post->post_content ? json_decode($post->post_content, true) : [];
      $this->registerSingle($config);
    }
  }

  /**
   * Registers a single CPT from a config array.
   */
  protected function registerSingle(array $config): void
  {
    $key = $config['key'] ?? '';

    if (empty($key) || post_type_exists($key)) {
      return;
    }

    $singular = $config['singular'] ?? $key;
    $plural   = $config['plural'] ?? $key;

    $labels = [
      'name'               => $plural,
      'singular_name'      => $singular,
      'add_new'            => sprintf(__('Add new %s', 'modern-fields'), strtolower($singular)),
      'add_new_item'       => sprintf(__('Add new %s', 'modern-fields'), strtolower($singular)),
      'edit_item'          => sprintf(__('Edit %s', 'modern-fields'), strtolower($singular)),
      'new_item'           => sprintf(__('New %s', 'modern-fields'), strtolower($singular)),
      'view_item'          => sprintf(__('View %s', 'modern-fields'), strtolower($singular)),
      'search_items'       => sprintf(__('Search %s', 'modern-fields'), strtolower($plural)),
      'not_found'          => sprintf(__('No %s found', 'modern-fields'), strtolower($plural)),
      'not_found_in_trash' => sprintf(__('No %s found in trash', 'modern-fields'), strtolower($plural)),
      'all_items'          => sprintf(__('All %s', 'modern-fields'), strtolower($plural)),
      'menu_name'          => $plural,
    ];

    # custom-fields is mandatory: WordPress strips `meta` from the REST schema
    # of post types without it, so field values would silently never save in
    # the block editor. Forced here so definitions stored before this rule
    # existed are covered without a resave.
    $supports = $config['supports'] ?? ['title', 'editor', 'thumbnail'];
    if (!in_array('custom-fields', $supports, true)) {
      $supports[] = 'custom-fields';
    }

    $args = [
      'labels'              => $labels,
      'description'         => $config['description'] ?? '',
      'public'              => $config['public'] ?? true,
      'has_archive'         => $config['has_archive'] ?? false,
      'hierarchical'        => $config['hierarchical'] ?? false,
      'show_in_rest'        => $config['show_in_rest'] ?? true,
      'publicly_queryable'  => $config['publicly_queryable'] ?? true,
      'show_ui'             => $config['show_ui'] ?? true,
      'show_in_nav_menus'   => $config['show_in_nav_menus'] ?? true,
      'exclude_from_search' => $config['exclude_from_search'] ?? false,
      'supports'            => $supports,
    ];

    if (!empty($config['menu_position'])) {
      $args['menu_position'] = (int) $config['menu_position'];
    }

    if (!empty($config['menu_icon'])) {
      $args['menu_icon'] = sanitize_text_field($config['menu_icon']);
    }

    $rewrite_slug = $config['rewrite_slug'] ?? '';
    $args['rewrite'] = !empty($rewrite_slug)
      ? ['slug' => $rewrite_slug]
      : true;

    if (!empty($config['rest_base'])) {
      $args['rest_base'] = sanitize_key($config['rest_base']);
    }

    register_post_type($key, $args);
  }
}
