<?php

declare(strict_types=1);

namespace Signocore\Multilanguage\Features;

if (!defined('ABSPATH')) {
	exit;
}

use Signocore\Multilanguage\Application\Constants;
use Signocore\Multilanguage\Infrastructure\Database\TranslationRepository;
use Signocore\Multilanguage\Infrastructure\Traits\Singleton;

final class ContentDuplicator
{
	use Singleton;

	protected function init(): void
	{
		add_action('wp_ajax_sml_duplicate_as_translation', [$this, 'handleDuplicate']);
	}

	/**
	 * AJAX handler to duplicate a post as a translation.
	 */
	public function handleDuplicate(): void
	{
		check_ajax_referer(Constants::AJAX_NONCE, 'nonce');

		if (!current_user_can('manage_options')) {
			wp_send_json_error(['message' => __('Permission denied.', 'signocore-multilanguage')]);
		}

		$sourcePostId = (int) ($_POST['post_id'] ?? 0);
		$langCode = sanitize_text_field($_POST['language'] ?? '');

		if ($sourcePostId === 0 || $langCode === '') {
			wp_send_json_error(['message' => __('Invalid parameters.', 'signocore-multilanguage')]);
		}

		$newPostId = $this->duplicate($sourcePostId, $langCode);

		if ($newPostId === false) {
			wp_send_json_error(['message' => __('Failed to duplicate post.', 'signocore-multilanguage')]);
		}

		wp_send_json_success([
			'post_id' => $newPostId,
			'edit_url' => get_edit_post_link($newPostId, 'raw'),
		]);
	}

	/**
	 * Duplicate a post as a translation.
	 *
	 * @return int|false New post ID or false on failure.
	 */
	public function duplicate(int $sourcePostId, string $langCode): int|false
	{
		$sourcePost = get_post($sourcePostId);
		if ($sourcePost === null) {
			return false;
		}

		$postData = apply_filters('signocore_ml_pre_duplicate_post', [
			'post_title' => $sourcePost->post_title,
			'post_content' => $sourcePost->post_content,
			'post_excerpt' => $sourcePost->post_excerpt,
			'post_status' => 'draft',
			'post_type' => $sourcePost->post_type,
			'post_author' => $sourcePost->post_author,
			'post_parent' => $sourcePost->post_parent,
			'menu_order' => $sourcePost->menu_order,
			'comment_status' => $sourcePost->comment_status,
			'ping_status' => $sourcePost->ping_status,
		], $sourcePostId, $langCode);

		$newPostId = wp_insert_post($postData, true);

		if (is_wp_error($newPostId)) {
			return false;
		}

		// Duplicate post meta
		$this->duplicatePostMeta($sourcePostId, $newPostId, $langCode);

		// Duplicate featured image
		$thumbnailId = (int) get_post_thumbnail_id($sourcePostId);
		if ($thumbnailId > 0) {
			set_post_thumbnail($newPostId, $thumbnailId);
		}

		// Duplicate taxonomies
		$this->duplicateTaxonomies($sourcePostId, $newPostId);

		// Link as translation
		$postTranslation = PostTranslation::load();
		$linked = $postTranslation->linkTranslation($sourcePostId, $newPostId, $langCode);

		if (!$linked) {
			wp_delete_post($newPostId, true);
			return false;
		}

		return $newPostId;
	}

	/**
	 * Duplicate post meta from source to target.
	 */
	private function duplicatePostMeta(int $sourcePostId, int $newPostId, string $langCode): void
	{
		$meta = get_post_meta($sourcePostId);
		if (!is_array($meta)) {
			return;
		}

		/** @var string[] $allowedKeys */
		$allowedKeys = apply_filters('signocore_ml_post_meta_to_duplicate', array_keys($meta), $sourcePostId, $langCode);

		foreach ($allowedKeys as $key) {
			if (str_starts_with($key, '_edit_') || $key === '_wp_old_slug' || str_starts_with($key, Constants::META_PREFIX)) {
				continue;
			}

			if (!isset($meta[$key])) {
				continue;
			}

			foreach ($meta[$key] as $value) {
				add_post_meta($newPostId, $key, maybe_unserialize($value));
			}
		}
	}

	/**
	 * Duplicate taxonomy terms from source to target post.
	 */
	private function duplicateTaxonomies(int $sourcePostId, int $newPostId): void
	{
		$postType = get_post_type($sourcePostId);
		if ($postType === false) {
			return;
		}

		$taxonomies = get_object_taxonomies($postType);

		foreach ($taxonomies as $taxonomy) {
			$terms = wp_get_object_terms($sourcePostId, $taxonomy, ['fields' => 'ids']);
			if (!is_wp_error($terms) && !empty($terms)) {
				wp_set_object_terms($newPostId, $terms, $taxonomy);
			}
		}
	}
}
