<?php

declare(strict_types=1);

namespace Signocore\Multilanguage\UI\Metaboxes;

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

use Signocore\Multilanguage\Application\Constants;
use Signocore\Multilanguage\Features\LanguageManager;
use Signocore\Multilanguage\Infrastructure\Database\TranslationRepository;
use Signocore\Multilanguage\Infrastructure\Traits\Singleton;
use Signocore\Multilanguage\Support\FlagHelper;
use Signocore\Multilanguage\Support\PostTypeHelper;
use Signocore\Multilanguage\Support\TranslationHelper;
use Signocore\Multilanguage\Support\UrlHelper;

final class PostTranslation
{
	use Singleton;

	private const NONCE_ACTION = 'sml_post_translation_save';

	private const NONCE_FIELD = 'sml_post_translation_nonce';

	protected function init(): void
	{
		add_action('add_meta_boxes', [$this, 'registerMetabox']);
		add_action('save_post', [$this, 'handleSave'], 20);
		add_action('admin_enqueue_scripts', [$this, 'enqueueAssets']);
	}

	/**
	 * Load admin assets on post editor screens.
	 */
	public function enqueueAssets(string $hookSuffix): void
	{
		if (!in_array($hookSuffix, ['post.php', 'post-new.php'], true)) {
			return;
		}

		wp_enqueue_style(
			'signocore-ml-admin-css',
			plugins_url('assets/css/admin.css', SIGNOCORE_ML_FILE),
			[],
			Constants::$pluginVersion
		);

		wp_enqueue_script(
			'signocore-ml-admin-js',
			plugins_url('assets/js/admin.js', SIGNOCORE_ML_FILE),
			['jquery'],
			Constants::$pluginVersion,
			true
		);

		wp_localize_script('signocore-ml-admin-js', 'smlAdmin', [
			'ajaxUrl' => admin_url('admin-ajax.php'),
			'nonce' => wp_create_nonce(Constants::AJAX_NONCE),
			'postId' => get_the_ID(),
		]);
	}

	/**
	 * Register the translation metabox for all translatable post types.
	 */
	public function registerMetabox(): void
	{
		foreach (PostTypeHelper::getTranslatablePostTypes() as $postType) {
			add_filter("postbox_classes_{$postType}_sml-post-translation", [$this, 'addPostboxClass']);
			add_meta_box(
				'sml-post-translation',
				__('Translations', 'signocore-multilanguage'),
				[$this, 'renderMetabox'],
				$postType,
				'side',
				'high'
			);
		}
	}

	/**
	 * Add sml-settings class to the metabox postbox.
	 *
	 * @param array<string> $classes
	 * @return array<string>
	 */
	public function addPostboxClass(array $classes): array
	{
		$classes[] = 'sml-settings';

		return $classes;
	}

	/**
	 * Render the translation metabox.
	 *
	 * @param \WP_Post $post
	 */
	public function renderMetabox(\WP_Post $post): void
	{
		$languages = array_filter(
			LanguageManager::load()->getActiveLanguages(),
			fn (object $lang): bool => UrlHelper::isLanguageReachable($lang->code)
		);
		$elementType = TranslationHelper::resolveElementType($post->ID);
		$currentLang = TranslationHelper::getElementLanguage($post->ID, $elementType);
		$translations = TranslationRepository::getTranslationsForPost($post->ID);
		$ajaxNonce = wp_create_nonce(Constants::AJAX_NONCE);

		// Detect source post for "Copy Content" feature
		$sourcePostId = null;
		$sourceLangName = '';
		$currentRecord = TranslationRepository::findByElement($post->ID, $elementType);

		if ($currentRecord !== null && $currentRecord->source_language_code !== null) {
			$sourceLangCode = $currentRecord->source_language_code;
			$sourceId = $translations[$sourceLangCode] ?? null;

			if ($sourceId !== null) {
				$sourcePost = get_post($sourceId);
				if ($sourcePost !== null && $sourcePost->post_status !== 'trash') {
					$sourcePostId = $sourceId;
					$sourceLangName = $languages[$sourceLangCode]->name ?? $sourceLangCode;
				}
			}
		}

		wp_nonce_field(self::NONCE_ACTION, self::NONCE_FIELD);

		?>
		<div class="sml-metabox" data-post-id="<?php echo esc_attr((string) $post->ID); ?>" data-post-type="<?php echo esc_attr($post->post_type); ?>">
			<div class="sml-metabox__section">
				<label class="sml-metabox__label" for="sml_post_language"><?php echo esc_html__('Language', 'signocore-multilanguage'); ?></label>
				<select name="sml_post_language" id="sml_post_language" class="sml-metabox__select">
					<?php foreach ($languages as $code => $lang) :
						$isLinked = isset($translations[$code]) && $code !== $currentLang;
					?>
						<option value="<?php echo esc_attr($code); ?>" <?php selected($currentLang, $code); ?> <?php disabled($isLinked); ?>>
							<?php echo esc_html($lang->name . ' (' . $code . ')'); ?>
						</option>
					<?php endforeach; ?>
				</select>
			</div>

			<?php if ($sourcePostId !== null) : ?>
				<div class="sml-metabox__copy" data-source-id="<?php echo esc_attr((string) $sourcePostId); ?>">
					<button type="button" class="button button-small sml-metabox__copy-btn">
						<?php
						printf(
							/* translators: %s: source language name */
							esc_html__('Copy content from %s', 'signocore-multilanguage'),
							esc_html($sourceLangName)
						);
						?>
					</button>
					<p class="sml-metabox__copy-note">
						<?php echo esc_html__('Replaces title, content, excerpt, and metadata.', 'signocore-multilanguage'); ?>
					</p>
				</div>
			<?php endif; ?>

			<div class="sml-metabox__section">
				<label class="sml-metabox__label"><?php echo esc_html__('Translations', 'signocore-multilanguage'); ?></label>
				<table class="sml-metabox__table">
					<tbody>
						<?php foreach ($languages as $code => $lang) : ?>
							<?php if ($code === $currentLang) {
								continue;
							} ?>
							<?php
							$translationId = $translations[$code] ?? null;
							$status = 'none';
							$statusLabel = __('Not translated', 'signocore-multilanguage');

							if ($translationId !== null) {
								$translatedPost = get_post($translationId);

								if ($translatedPost === null || $translatedPost->post_status === 'trash') {
									$translationId = null;
								} elseif ($translatedPost->post_status === 'publish') {
									$status = 'published';
									$statusLabel = __('Published', 'signocore-multilanguage');
								} else {
									$status = 'draft';
									$statusLabel = __('Draft', 'signocore-multilanguage');
								}
							}
							?>
							<tr class="sml-metabox__row">
								<td class="sml-metabox__flag">
									<?php echo FlagHelper::getFlagImg($code, 16, 12, $lang->name); ?>
								</td>
								<td class="sml-metabox__info">
									<strong><?php echo esc_html($lang->name); ?></strong>
									<span class="sml-metabox__status sml-metabox__status--<?php echo esc_attr($status); ?>">
										<?php echo esc_html($statusLabel); ?>
									</span>
								</td>
								<td class="sml-metabox__actions">
									<?php if ($translationId !== null) : ?>
										<a href="<?php echo esc_url(get_edit_post_link($translationId) ?? ''); ?>" class="button button-small">
											<?php echo esc_html__('Edit', 'signocore-multilanguage'); ?>
										</a>
										<a href="<?php echo esc_url(admin_url(sprintf(
											'admin-ajax.php?action=sml_unlink_translation&post_id=%d&lang=%s&_ajax_nonce=%s',
											$translationId,
											$code,
											$ajaxNonce
										))); ?>" class="button button-small button-link-delete" onclick="return confirm('<?php echo esc_js(__('Remove translation link?', 'signocore-multilanguage')); ?>');">
											<?php echo esc_html__('Unlink', 'signocore-multilanguage'); ?>
										</a>
									<?php else : ?>
										<a href="<?php echo esc_url(admin_url(sprintf(
											'admin-ajax.php?action=sml_create_translation&source_id=%d&lang=%s&_ajax_nonce=%s',
											$post->ID,
											$code,
											$ajaxNonce
										))); ?>" class="button button-small button-primary">
											<?php echo esc_html__('Create', 'signocore-multilanguage'); ?>
										</a>
										<button type="button" class="button button-small sml-metabox__link-btn" data-lang="<?php echo esc_attr($code); ?>">
											<?php echo esc_html__('Link', 'signocore-multilanguage'); ?>
										</button>
									<?php endif; ?>
								</td>
							</tr>
							<?php if ($translationId === null) : ?>
								<tr class="sml-metabox__link-row" data-lang="<?php echo esc_attr($code); ?>" style="display: none;">
									<td colspan="3">
										<input type="text"
											   class="sml-metabox__search-input"
											   aria-label="<?php echo esc_attr__('Search posts to link...', 'signocore-multilanguage'); ?>"
											   placeholder="<?php echo esc_attr__('Search posts to link...', 'signocore-multilanguage'); ?>"
											   data-lang="<?php echo esc_attr($code); ?>">
										<div class="sml-metabox__search-results"></div>
									</td>
								</tr>
							<?php endif; ?>
						<?php endforeach; ?>
					</tbody>
				</table>
			</div>
		</div>
		<?php
	}

	/**
	 * Handle language change on post save.
	 */
	public function handleSave(int $postId): void
	{
		if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
			return;
		}

		if (wp_is_post_revision($postId) || wp_is_post_autosave($postId)) {
			return;
		}

		if (!isset($_POST[self::NONCE_FIELD]) || !wp_verify_nonce($_POST[self::NONCE_FIELD], self::NONCE_ACTION)) {
			return;
		}

		if (!current_user_can('edit_post', $postId)) {
			return;
		}

		$langCode = sanitize_text_field($_POST['sml_post_language'] ?? '');
		if ($langCode === '') {
			return;
		}

		$langManager = LanguageManager::load();
		if (!$langManager->isActiveLanguage($langCode)) {
			return;
		}

		$elementType = TranslationHelper::resolveElementType($postId);
		$existing = TranslationRepository::findByElement($postId, $elementType);

		if ($existing !== null) {
			if ($existing->language_code !== $langCode) {
				TranslationRepository::update((int) $existing->id, [
					'language_code' => $langCode,
				]);
			}
		} else {
			\Signocore\Multilanguage\Features\PostTranslation::load()->assignLanguage($postId, $langCode);
		}
	}
}
