<?php

declare(strict_types=1);

namespace Signocore\Multilanguage\Admin;

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

use Signocore\Multilanguage\Application\Constants;
use Signocore\Multilanguage\Features\LanguageManager;
use Signocore\Multilanguage\Features\StringScanner;
use Signocore\Multilanguage\Infrastructure\Database\StringRepository;
use Signocore\Multilanguage\Infrastructure\Traits\Singleton;

final class StringTranslationPage
{
	use Singleton;

	private const PER_PAGE = 30;

	private const NONCE_BULK_SAVE = 'sml_strings_bulk_save';

	protected function init(): void
	{
		add_action('admin_init', [$this, 'handleBulkSave']);
		add_action('wp_ajax_sml_save_string_translation', [$this, 'handleAjaxSave']);
		add_action('wp_ajax_sml_save_string_translations_bulk', [$this, 'handleAjaxBulkSave']);
		add_action('wp_ajax_sml_get_strings', [$this, 'handleAjaxGetStrings']);
	}

	/**
	 * Render the string translation admin page.
	 */
	public function render(): void
	{
		if (!current_user_can('manage_options')) {
			return;
		}

		// Handle manual rescan request
		if (isset($_GET['sml_rescan']) && wp_verify_nonce($_GET['_wpnonce'] ?? '', 'sml_rescan')) {
			StringScanner::load()->forceRescan();
			wp_safe_redirect(remove_query_arg(['sml_rescan', '_wpnonce']));
			exit;
		}

		// Auto-scan if no recent scan exists
		$scanner = StringScanner::load();
		if ($scanner->shouldScan()) {
			$scanner->runFullScan();
		}

		$langManager = LanguageManager::load();
		$activeLanguages = $langManager->getActiveLanguages();

		// Non-default languages only
		$languages = [];
		foreach ($activeLanguages as $lang) {
			if ((int) $lang->is_default !== 1) {
				$languages[] = $lang;
			}
		}

		// Initial load: first non-default language
		$firstLangCode = !empty($languages) ? $languages[0]->code : '';
		$perPage = self::PER_PAGE;

		if ($firstLangCode !== '') {
			$totalStrings = StringRepository::countStringsWithStatus(null, null, $firstLangCode);
			$strings = StringRepository::getAllForLanguageWithStatus($firstLangCode, null, null, $perPage, 0);
			$statusCounts = $this->buildStatusCounts($firstLangCode, null, '');
		} else {
			$totalStrings = 0;
			$strings = [];
			$statusCounts = [
				'all' => 0,
				'translated' => 0,
				'needs_update' => 0,
				'needs_translation' => 0,
			];
		}

		$contexts = StringRepository::getContexts();

		include __DIR__ . '/Views/string-translation.php';
	}

	/**
	 * Handle AJAX request to fetch strings with filters.
	 */
	public function handleAjaxGetStrings(): void
	{
		if (!check_ajax_referer(Constants::AJAX_NONCE, '_ajax_nonce', false)) {
			wp_send_json_error(__('Security check failed.', 'signocore-multilanguage'), 403);
		}

		if (!current_user_can('manage_options')) {
			wp_send_json_error(__('You do not have permission to perform this action.', 'signocore-multilanguage'), 403);
		}

		$langCode = sanitize_text_field($_POST['lang'] ?? '');
		$context = sanitize_text_field($_POST['context'] ?? '');
		$status = sanitize_text_field($_POST['status'] ?? 'all');
		$search = sanitize_text_field($_POST['search'] ?? '');
		$page = max(1, (int) ($_POST['page'] ?? 1));
		$perPage = max(1, min(100, (int) ($_POST['per_page'] ?? self::PER_PAGE)));
		$offset = ($page - 1) * $perPage;

		$contextArg = $context !== '' ? $context : null;
		$statusArg = $status !== 'all' ? $status : null;

		if ($search !== '') {
			$strings = StringRepository::searchStringsWithTranslation($search, $langCode, $contextArg, $statusArg, $perPage, $offset);
			$total = StringRepository::countSearchStrings($search, $contextArg, $statusArg, $langCode);
		} else {
			$strings = StringRepository::getAllForLanguageWithStatus($langCode, $contextArg, $statusArg, $perPage, $offset);
			$total = StringRepository::countStringsWithStatus($contextArg, $statusArg, $langCode);
		}

		wp_send_json_success([
			'strings' => array_map(static fn (object $s): array => [
				'id' => (int) $s->id,
				'context' => $s->context,
				'name' => $s->name,
				'value' => $s->value,
				'type' => $s->type ?? 'line',
				'translation_value' => $s->translation_value ?? '',
				'translation_status' => $s->translation_status ?? 'needs_translation',
			], $strings),
			'total' => $total,
			'page' => $page,
			'per_page' => $perPage,
			'status_counts' => $this->buildStatusCounts($langCode, $contextArg, $search),
		]);
	}

	/**
	 * Handle bulk save via POST (backward compatibility).
	 */
	public function handleBulkSave(): void
	{
		if (!isset($_POST['sml_bulk_save_strings'])) {
			return;
		}

		if (!current_user_can('manage_options')) {
			return;
		}

		if (!isset($_POST['_wpnonce']) || !wp_verify_nonce($_POST['_wpnonce'], self::NONCE_BULK_SAVE)) {
			wp_die(esc_html__('Security check failed.', 'signocore-multilanguage'));
		}

		$translations = $_POST['sml_translations'] ?? [];

		if (!is_array($translations)) {
			return;
		}

		$userId = get_current_user_id();

		foreach ($translations as $stringId => $langs) {
			if (!is_array($langs)) {
				continue;
			}

			$stringId = (int) $stringId;

			foreach ($langs as $langCode => $value) {
				$langCode = sanitize_text_field((string) $langCode);
				$value = sanitize_textarea_field((string) $value);

				StringRepository::saveTranslation($stringId, $langCode, $value, $userId);
			}
		}

		wp_safe_redirect(add_query_arg('message', 'strings_saved', wp_get_referer() ?: admin_url('admin.php?page=signocore-ml-strings')));
		exit;
	}

	/**
	 * Handle AJAX inline save for a single translation.
	 */
	public function handleAjaxSave(): void
	{
		if (!check_ajax_referer(Constants::AJAX_NONCE, '_ajax_nonce', false)) {
			wp_send_json_error(__('Security check failed.', 'signocore-multilanguage'), 403);
		}

		if (!current_user_can('manage_options')) {
			wp_send_json_error(__('You do not have permission to perform this action.', 'signocore-multilanguage'), 403);
		}

		$stringId = (int) ($_POST['string_id'] ?? 0);
		$langCode = sanitize_text_field($_POST['lang_code'] ?? '');
		$value = sanitize_textarea_field($_POST['value'] ?? '');

		if ($stringId < 1 || $langCode === '') {
			wp_send_json_error(__('Missing required fields.', 'signocore-multilanguage'));
		}

		$string = StringRepository::findStringById($stringId);
		if ($string === null) {
			wp_send_json_error(__('String not found.', 'signocore-multilanguage'));
		}

		$userId = get_current_user_id();
		$result = StringRepository::saveTranslation($stringId, $langCode, $value, $userId);

		if (!$result) {
			wp_send_json_error(__('Failed to save translation.', 'signocore-multilanguage'));
		}

		wp_send_json_success([
			'string_id' => $stringId,
			'lang_code' => $langCode,
			'status' => $value !== '' ? 'translated' : 'needs_translation',
			'message' => __('Translation saved.', 'signocore-multilanguage'),
			'saved_at' => current_time('mysql'),
		]);
	}

	/**
	 * Handle AJAX bulk save for multiple translations.
	 */
	public function handleAjaxBulkSave(): void
	{
		if (!check_ajax_referer(Constants::AJAX_NONCE, '_ajax_nonce', false)) {
			wp_send_json_error(__('Security check failed.', 'signocore-multilanguage'), 403);
		}

		if (!current_user_can('manage_options')) {
			wp_send_json_error(__('You do not have permission to perform this action.', 'signocore-multilanguage'), 403);
		}

		$itemsJson = wp_unslash($_POST['items_json'] ?? '');
		$items = json_decode(is_string($itemsJson) ? $itemsJson : '', true);

		if (!is_array($items) || empty($items)) {
			wp_send_json_error(__('No translations to save.', 'signocore-multilanguage'));
		}

		$userId = get_current_user_id();
		$savedItems = [];
		$failedCount = 0;

		foreach ($items as $item) {
			if (!is_array($item)) {
				$failedCount++;
				continue;
			}

			$stringId = isset($item['string_id']) ? (int) $item['string_id'] : 0;
			$langCode = sanitize_text_field((string) ($item['lang_code'] ?? ''));
			$value = sanitize_textarea_field((string) ($item['value'] ?? ''));

			if ($stringId < 1 || $langCode === '') {
				$failedCount++;
				continue;
			}

			$string = StringRepository::findStringById($stringId);
			if ($string === null) {
				$failedCount++;
				continue;
			}

			$result = StringRepository::saveTranslation($stringId, $langCode, $value, $userId);
			if (!$result) {
				$failedCount++;
				continue;
			}

			$savedItems[] = [
				'string_id' => $stringId,
				'lang_code' => $langCode,
				'status' => $value !== '' ? 'translated' : 'needs_translation',
				'message' => __('Translation saved.', 'signocore-multilanguage'),
				'saved_at' => current_time('mysql'),
			];
		}

		if (empty($savedItems)) {
			wp_send_json_error(__('Failed to save translations.', 'signocore-multilanguage'));
		}

		wp_send_json_success([
			'items' => $savedItems,
			'saved_count' => count($savedItems),
			'failed_count' => $failedCount,
			'saved_at' => current_time('mysql'),
		]);
	}

	/**
	 * Build status counters for the current language and active filters.
	 *
	 * @return array{all: int, translated: int, needs_update: int, needs_translation: int}
	 */
	private function buildStatusCounts(string $langCode, ?string $context, string $search): array
	{
		if ($langCode === '') {
			return [
				'all' => 0,
				'translated' => 0,
				'needs_update' => 0,
				'needs_translation' => 0,
			];
		}

		if ($search !== '') {
			$all = StringRepository::countSearchStrings($search, $context, null, $langCode);
			$translated = StringRepository::countSearchStrings($search, $context, 'translated', $langCode);
			$needsUpdate = StringRepository::countSearchStrings($search, $context, 'needs_update', $langCode);
			$needsTranslation = StringRepository::countSearchStrings($search, $context, 'needs_translation', $langCode);
		} else {
			$all = StringRepository::countStringsWithStatus($context, null, $langCode);
			$translated = StringRepository::countStringsWithStatus($context, 'translated', $langCode);
			$needsUpdate = StringRepository::countStringsWithStatus($context, 'needs_update', $langCode);
			$needsTranslation = StringRepository::countStringsWithStatus($context, 'needs_translation', $langCode);
		}

		return [
			'all' => $all,
			'translated' => $translated,
			'needs_update' => $needsUpdate,
			'needs_translation' => $needsTranslation,
		];
	}
}
