<?php
if (! defined('ABSPATH')) {
    exit;
} abstract class PufferGo_Base_CPT
{
    public const DEFAULT_MODULES = ['product', 'solution', 'case-study'];

    protected array $config;

    private bool $skip_archive_save = false;

    private bool $skip_tax_save = false;

    abstract protected function get_module_key(): string;

    abstract protected function get_config(): array;

    abstract protected function get_meta_fields(): array;

    protected function register_integrations(): void
    {
    }

    protected function register_front_assets(): void
    {
    }

    protected function save_permalink_settings_extra(string $archive_slug): void
    {
    }

    final public function __construct()
    {
        if (! self::is_enabled($this->get_module_key())) {
            return;
        } add_action('init', [$this, '_load_config'], 0);
        add_action('init', [$this, 'register_cpt']);
        add_action('init', [$this, 'register_taxonomy']);
        add_action('init', [$this, 'register_tag_taxonomy']);
        add_action('init', [$this, 'register_meta_fields']);
        add_action('wp_enqueue_scripts', [$this, '_dispatch_front_assets']);
        add_action('admin_init', [$this, 'register_permalink_settings']);
        add_action('admin_head-nav-menus.php', [$this, 'force_show_tax_meta_box']);
        add_filter('puffergo_translatable_meta', [$this, '_register_translatable_meta']);
        $this->register_integrations();
    }

    final public function _load_config(): void
    {
        $this->config = $this->get_config();
    }

    final public static function is_enabled(string $module_key): bool
    {
        $enabled = get_option('puffergo_enabled_modules', self::DEFAULT_MODULES);

        return in_array($module_key, (array) $enabled, true);
    }

    final public function register_cpt(): void
    {
        $c = $this->config;
        register_post_type($c['cpt_slug'], ['labels' => $this->generate_labels($c['singular'], $c['plural']), 'public' => true, 'publicly_queryable' => true, 'show_ui' => true, 'show_in_menu' => true, 'menu_position' => $c['menu_position'] ?? 5, 'menu_icon' => $c['menu_icon'], 'query_var' => true, 'rewrite' => ['slug' => $this->resolve_archive_slug(), 'with_front' => false], 'capability_type' => 'post', 'has_archive' => $c['has_archive'] ?? true, 'hierarchical' => false, 'supports' => $c['supports'], 'show_in_rest' => true, ]);
    }

    final public function register_taxonomy(): void
    {
        $c = $this->config;

        if (empty($c['tax_slug'])) {
            return;
        } register_taxonomy($c['tax_slug'], [$c['cpt_slug']], ['hierarchical' => true, 'labels' => $this->generate_tax_labels($c['tax_singular'], $c['tax_plural']), 'show_ui' => true, 'show_in_menu' => true, 'show_admin_column' => true, 'query_var' => true, 'rewrite' => ['slug' => $this->resolve_tax_archive_slug(), 'with_front' => false, 'hierarchical' => true, ], 'show_in_rest' => true, 'show_in_nav_menus' => true, ]);
    }

    final public function register_tag_taxonomy(): void
    {
        $c = $this->config;

        if (empty($c['tag_slug'])) {
            return;
        } register_taxonomy($c['tag_slug'], [$c['cpt_slug']], ['hierarchical' => false, 'labels' => $this->generate_tax_labels($c['tag_singular'], $c['tag_plural']), 'show_ui' => true, 'show_in_menu' => true, 'show_admin_column' => true, 'query_var' => true, 'rewrite' => ['slug' => $c['tag_archive_slug'] ?? $c['tag_slug'], 'with_front' => false, ], 'show_in_rest' => true, 'show_in_nav_menus' => true, ]);
    }

    final public function register_meta_fields(): void
    {
        foreach ($this->get_meta_fields() as $meta_key => $args) {
            unset($args['translate']);
            register_post_meta($this->config['cpt_slug'], $meta_key, $args);
        }
    }

    final public function _register_translatable_meta(array $map): array
    {
        if (empty($this->config['cpt_slug'])) {
            return $map;
        } $specs = array();

        foreach ($this->get_meta_fields() as $meta_key => $args) {
            if (isset($args['translate'])) {
                $specs[ $meta_key ] = $args['translate'];
            }
        }

if (! empty($specs)) {
            $map[ $this->config['cpt_slug'] ] = $specs;
        }

return $map;
    }

    final public function register_permalink_settings(): void
    {
        $c = $this->config;

        if (empty($c['archive_slug_option'])) {
            return;
        } $section_id = 'puffergo-permalink-' . $c['module_key'];
        add_settings_section($section_id, sprintf(__('PufferGo %s Permalinks', 'puffergo'), $c['plural']), [$this, '_render_permalink_section_desc'], 'permalink');

        if (! empty($c['tax_archive_slug_option'])) {
            add_settings_field($c['tax_archive_slug_option'], $c['tax_archive_slug_label'] ?? __('Category base', 'puffergo'), [$this, '_render_tax_slug_field'], 'permalink', $section_id);
        } add_settings_field($c['archive_slug_option'], $c['archive_slug_label'] ?? __('Archive base', 'puffergo'), [$this, '_render_archive_slug_field'], 'permalink', $section_id);

        if (isset($_POST['puffergo_permalinks_nonce'])) {
            $this->process_permalink_save();
        }
    }

    final public function _render_permalink_section_desc(): void
    {
        printf(esc_html__('Customize the URL structure for PufferGo %s.', 'puffergo'), esc_html(strtolower($this->config['plural'])));
    }

    final public function _render_tax_slug_field(): void
    {
        $c = $this->config;
        $slug = $this->resolve_tax_archive_slug(); ?>
		<input
			type="text"
			name="<?php echo esc_attr($c['tax_archive_slug_option']); ?>"
			value="<?php echo esc_attr($slug); ?>"
			class="regular-text code"
		/>
		<p class="description">
			<?php
        printf(esc_html__('URL prefix for category archives, e.g. %s', 'puffergo'), '<code>/' . esc_html($slug) . '/example/</code>'); ?>
		</p>
		<?php
    }

    final public function _render_archive_slug_field(): void
    {
        $c = $this->config;
        $slug = $this->resolve_archive_slug(); ?>
		<input
			type="text"
			name="<?php echo esc_attr($c['archive_slug_option']); ?>"
			value="<?php echo esc_attr($slug); ?>"
			class="regular-text code"
		/>
		<p class="description">
			<?php
        printf(esc_html__('URL prefix for archives, e.g. %s', 'puffergo'), '<code>/' . esc_html($slug) . '/</code>'); ?>
		</p>
		<?php
        wp_nonce_field('puffergo_permalinks', 'puffergo_permalinks_nonce');
    }

    final public function force_show_tax_meta_box(): void
    {
        $c = $this->config;

        if (empty($c['tax_slug'])) {
            return;
        } $user_id = get_current_user_id();

        if (! $user_id) {
            return;
        } $hidden = get_user_meta($user_id, 'metaboxhidden_nav-menus', true);

        if (! is_array($hidden)) {
            return;
        } $box_id = 'add-' . $c['tax_slug'];
        $key = array_search($box_id, $hidden, true);

        if (false !== $key) {
            unset($hidden[ $key ]);
            update_user_meta($user_id, 'metaboxhidden_nav-menus', array_values($hidden));
        }
    }

    final public function sanitize_json_field($value): string
    {
        if (! is_string($value)) {
            return '';
        } $decoded = json_decode($value, true);

        if (json_last_error() !== JSON_ERROR_NONE) {
            return '';
        }

return wp_json_encode($decoded);
    }

    final public function auth_callback($allowed, $meta_key, $post_id): bool
    {
        return current_user_can('edit_post', $post_id);
    }

    final public function _dispatch_front_assets(): void
    {
        $this->register_front_assets();
    }

    final protected function abort_archive_slug_save(): void
    {
        $this->skip_archive_save = true;
    }

    final protected function abort_tax_slug_save(): void
    {
        $this->skip_tax_save = true;
    }

    final protected function generate_labels(string $singular, string $plural): array
    {
        return ['name' => $plural, 'singular_name' => $singular, 'menu_name' => $plural, 'all_items' => sprintf(__('All %s', 'puffergo'), $plural), 'add_new' => __('Add New', 'puffergo'), 'add_new_item' => sprintf(__('Add New %s', 'puffergo'), $singular), 'edit_item' => sprintf(__('Edit %s', 'puffergo'), $singular), 'new_item' => sprintf(__('New %s', 'puffergo'), $singular), 'view_item' => sprintf(__('View %s', 'puffergo'), $singular), 'search_items' => sprintf(__('Search %s', 'puffergo'), $plural), 'not_found' => sprintf(__('No %s found', 'puffergo'), strtolower($plural)), 'not_found_in_trash' => sprintf(__('No %s found in Trash', 'puffergo'), strtolower($plural)), 'archives' => sprintf(__('%s Archives', 'puffergo'), $singular), ];
    }

    final protected function generate_tax_labels(string $singular, string $plural): array
    {
        return ['name' => $plural, 'singular_name' => $singular, 'search_items' => sprintf(__('Search %s', 'puffergo'), $plural), 'all_items' => sprintf(__('All %s', 'puffergo'), $plural), 'parent_item' => sprintf(__('Parent %s', 'puffergo'), $singular), 'parent_item_colon' => sprintf(__('Parent %s:', 'puffergo'), $singular), 'edit_item' => sprintf(__('Edit %s', 'puffergo'), $singular), 'update_item' => sprintf(__('Update %s', 'puffergo'), $singular), 'add_new_item' => sprintf(__('Add New %s', 'puffergo'), $singular), 'new_item_name' => sprintf(__('New %s Name', 'puffergo'), $singular), 'menu_name' => $plural, ];
    }

    private function resolve_archive_slug(): string
    {
        $c = $this->config;

        if (! empty($c['archive_slug_option'])) {
            return get_option($c['archive_slug_option'], $c['archive_slug_default'] ?? '');
        }

return $c['archive_slug'] ?? '';
    }

    private function resolve_tax_archive_slug(): string
    {
        $c = $this->config;

        if (! empty($c['tax_archive_slug_option'])) {
            return get_option($c['tax_archive_slug_option'], $c['tax_archive_slug_default'] ?? '');
        }

return $c['tax_archive_slug'] ?? ($c['tax_slug'] ?? '');
    }

    private function process_permalink_save(): void
    {
        check_admin_referer('puffergo_permalinks', 'puffergo_permalinks_nonce');

        if (! current_user_can('manage_options')) {
            return;
        } $c = $this->config;
        $archive_option = $c['archive_slug_option'];
        $archive_default = $c['archive_slug_default'] ?? '';
        $new_archive = isset($_POST[ $archive_option ]) ? sanitize_title(wp_unslash($_POST[ $archive_option ])) : $archive_default;
        $new_archive = ! empty($new_archive) ? $new_archive : $archive_default;
        $this->save_permalink_settings_extra($new_archive);

        if (! $this->skip_archive_save) {
            update_option($archive_option, $new_archive);
        }

if (! empty($c['tax_archive_slug_option']) && ! $this->skip_tax_save) {
            $tax_option = $c['tax_archive_slug_option'];
            $tax_default = $c['tax_archive_slug_default'] ?? '';
            $new_tax = isset($_POST[ $tax_option ]) ? sanitize_title(wp_unslash($_POST[ $tax_option ])) : $tax_default;
            $new_tax = ! empty($new_tax) ? $new_tax : $tax_default;
            update_option($tax_option, $new_tax);
        }
    }
}
