<?php
/**
 * AbstractWidgetRepository class.
 *
 * Base class for widget repositories providing reusable logic.
 *
 * @package Ilabs\Firevert\Core\Repository
 */

declare( strict_types=1 );

namespace Ilabs\Firevert\Core\Repository;

use Ilabs\Firevert\Core\Services\Helper\Integration\LanguageHelper;
use WP_Post;
use Ilabs\Firevert\Core\Form\FormHandler;

/**
 * Class AbstractWidgetRepository
 */
abstract class AbstractWidgetRepository {

	/**
	 * Returns the main instance of a widget or creates a new one.
	 *
	 * @return WP_Post
	 * @throws \RuntimeException If failed to create or retrieve a valid post.
	 */
	public function get_or_create_main(): WP_Post {
		$post_type = $this->get_post_type();

		if ( ! post_type_exists( $post_type ) ) {
			throw new \RuntimeException(
				sprintf(
					'Post type %s is not registered at this point.',
					esc_html( $post_type )
				)
			);
		}

		$posts = get_posts(
			array(
				'post_type'      => $post_type,
				'post_status'    => 'publish',
				'posts_per_page' => 1,
				'orderby'        => 'ID',
				'order'          => 'ASC',
			)
		);

		$post = $posts[0] ?? null;

		if ( null === $post ) {
			$post_id = wp_insert_post(
				array(
					'post_type'   => $post_type,
					'post_status' => 'publish',
					'post_title'  => $this->get_default_post_title(),
				)
			);

			$post = get_post( $post_id );
		}

		if ( ! ( $post instanceof \WP_Post ) ) {
			throw new \RuntimeException(
				sprintf(
					'Failed to create or retrieve a valid %s post.',
					esc_html( $post_type )
				)
			);
		}

		return $post;
	}

	/**
	 * Extracts field values from post meta based on form handler definition.
	 *
	 * @param WP_Post     $post Post to extract meta from.
	 * @param FormHandler $handler Handler containing field definitions.
	 * @param string|null $lang Optional language key ('pl', 'en', 'fr' format).
	 *
	 * @return array<string, mixed> Key-value array of field values.
	 */
	protected function extract_fields( WP_Post $post, FormHandler $handler, ?string $lang = null ): array {
		$data         = array();
		$fields       = $handler->get_fields();
		$translatable = method_exists( $handler, 'get_translatable_fields' )
			? $handler->get_translatable_fields()
			: array();

		if ( null === $lang && LanguageHelper::is_translation_system_active() ) {
			$lang = LanguageHelper::get_active_region_code();
		} elseif ( null === $lang ) {
			$lang = get_locale();
		}

		foreach ( $fields as $key => $type ) {
			$is_translatable = in_array( $key, $translatable, true );
			$meta_key        = ( $is_translatable && $lang ) ? "{$key}__{$lang}" : $key;
			$value           = get_post_meta( $post->ID, $meta_key, true );

			if ( '' === $value && $is_translatable ) {
				$default_lang = LanguageHelper::get_default_region_code();
				if ( $default_lang && $default_lang !== $lang ) {
					$fallback_key = "{$key}__{$default_lang}";
					$value        = get_post_meta( $post->ID, $fallback_key, true );
				}
			}

			switch ( $type ) {
				case 'bool':
					$data[ $key ] = (bool) $value;
					break;
				case 'int':
					$data[ $key ] = (int) $value;
					break;
				case 'array':
					$maybe_unserialized = maybe_unserialize( $value );
					$data[ $key ]       = is_array( $maybe_unserialized ) ? $maybe_unserialized : array();
					break;
				default:
					$data[ $key ] = $value;
			}
		}

		return $data;
	}

	/**
	 * Returns the CPT name of the widget.
	 *
	 * @return string
	 */
	abstract protected function get_post_type(): string;

	/**
	 * Returns the default post title if no widget exists.
	 *
	 * @return string
	 */
	abstract protected function get_default_post_title(): string;
}
