<?php

declare(strict_types=1);

namespace BadamSoft\WooProductExporter\Core;

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

use BadamSoft\WooProductExporter\Access\AccessManager;
use BadamSoft\WooProductExporter\Admin\AdminPage;
use BadamSoft\WooProductExporter\Api\RestApi;
use BadamSoft\WooProductExporter\Exporter\Exporter;
use BadamSoft\WooProductExporter\Exporter\Meta\MetaFieldDetector;
use BadamSoft\WooProductExporter\Exporter\Formats\CsvWriter;
use BadamSoft\WooProductExporter\Exporter\Formats\FormatManager;
use BadamSoft\WooProductExporter\Exporter\Queries\QueryBuilder;
use BadamSoft\WooProductExporter\Filters\FilterManager;
use BadamSoft\WooProductExporter\Scheduled\ChunkProcessor;
use BadamSoft\WooProductExporter\Scheduler\Installer;
use BadamSoft\WooProductExporter\Scheduler\ScheduledExportManager;
use BadamSoft\WooProductExporter\Templates\TemplateController;
use BadamSoft\WooProductExporter\Templates\TemplateManager;
use BadamSoft\WooProductExporter\Settings\SettingsRepository;
use BadamSoft\WooProductExporter\Settings\SettingsRestController;
use function current_time;
use function home_url;
use function in_array;
use Throwable;

class Plugin {
    private static ?self $instance = null;
    private const OPTIMIZE_HOOK = 'prodexfo_optimize_export_tables';
    public const MANUAL_EXPORT_ASYNC_HOOK = 'prodexfo_manual_export_async_run';

    private string $plugin_file;
    private string $plugin_url;
    private string $plugin_path;
    private AdminPage $admin_page;
    private RestApi $rest_api;
    private AccessManager $access_manager;
    private Exporter $exporter;
    private $license_manager = null;
    private $license_service = null;
    private FilterManager $filter_manager;
    private QueryBuilder $query_builder;
    private ChunkProcessor $chunk_processor;
    private FormatManager $format_manager;
    private MetaFieldDetector $meta_field_detector;
    private TemplateManager $template_manager;
    private TemplateController $template_controller;
    private SettingsRepository $settings_repository;
    private SettingsRestController $settings_rest_controller;

    /**
     * Translation map cache keyed by locale.
     *
     * @var array<string, array<string, string>>
     */
    private array $translation_map = [];

    private function __construct(string $plugin_file) {
        $this->plugin_file = $plugin_file;
        $this->plugin_path = plugin_dir_path($plugin_file);
        $this->plugin_url  = plugin_dir_url($plugin_file);

        $this->bootstrap_core_services();

        $this->register_hooks();
    }

    /**
     * Bootstrap core plugin services.
     *
     * @return ScheduledExportManager
     */
    private function bootstrap_core_services(): ScheduledExportManager {
        $this->filter_manager     = new FilterManager();
        $this->chunk_processor    = new ChunkProcessor();
        $this->access_manager     = new AccessManager();
        $this->template_manager   = new TemplateManager();
        $this->query_builder      = new QueryBuilder($this->filter_manager);
        $this->format_manager     = $this->bootstrap_format_manager();
        $this->settings_repository = new SettingsRepository();

        global $wpdb;

        $this->meta_field_detector = new MetaFieldDetector($wpdb);
        $scheduled_manager         = new ScheduledExportManager($wpdb);

        $this->exporter  = new Exporter(
            $this,
            $this->filter_manager,
            $this->query_builder,
            $this->chunk_processor,
            $this->format_manager,
            $this->template_manager,
            $scheduled_manager,
            $this->meta_field_detector
        );

        $this->admin_page = new AdminPage(
            $this,
            $this->exporter,
            $this->template_manager,
            $scheduled_manager,
            $this->access_manager,
            $this->filter_manager,
            $this->settings_repository
        );

        $this->template_controller = new TemplateController($this->template_manager, $this->exporter, $this->access_manager);
        $this->rest_api            = new RestApi($this->template_manager, $this->exporter, $this->access_manager, $scheduled_manager, $this->settings_repository);
        $this->settings_rest_controller = new SettingsRestController($this->settings_repository, $this->access_manager, $this);

        return $scheduled_manager;
    }

    /**
     * Bootstrap license services if available.
     */
    private function bootstrap_license_services(): void {
        return;
    }

    /**
     * Register WordPress hooks and actions.
     */
    private function register_hooks(): void {
        add_action('init', [$this, 'load_textdomain']);
        add_action('init', [$this, 'register_translation_filters'], 1);
        add_action('init', [$this, 'ensure_cleanup_cron_event']);
        add_action('init', [$this, 'ensure_optimize_cron_event']);

        add_action('admin_menu', [$this->admin_page, 'register_menu_page']);
        add_action('admin_init', [$this->admin_page, 'maybe_handle_export']);
        add_action('admin_enqueue_scripts', [$this->admin_page, 'enqueue_admin_assets']);

        add_action( self::MANUAL_EXPORT_ASYNC_HOOK, [ $this, 'handle_manual_export_async_run' ], 10, 1 );

        add_action('prodexfo_cleanup_exports', [$this, 'maybe_cleanup_exports']);
        add_action(self::OPTIMIZE_HOOK, [$this, 'maybe_optimize_database']);
    }

    /**
     * Background export handler (Action Scheduler).
     *
     * @param int $run_id Export run ID.
     */
    public function handle_manual_export_async_run( int $run_id ): void {
        $run_id = (int) $run_id;

        if ( $run_id <= 0 ) {
            return;
        }

        global $wpdb;

        $scheduled_manager = new ScheduledExportManager( $wpdb );
        $run              = $scheduled_manager->get_run( $run_id );

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

        $fields   = isset( $run['fields'] ) && is_array( $run['fields'] ) ? $run['fields'] : [];
        $filters  = isset( $run['filters'] ) && is_array( $run['filters'] ) ? $run['filters'] : [];
        $settings = isset( $run['settings'] ) && is_array( $run['settings'] ) ? $run['settings'] : [];
        $format   = isset( $run['file_format'] ) ? (string) $run['file_format'] : '';

        if ( '' === $format ) {
            $format = $this->exporter->get_default_format_key();
        }

        $format = strtoupper( sanitize_key( $format ) );

        $scheduled_manager->update_run_file_meta(
            $run_id,
            [
                'status'      => 'running',
                'finished_at' => current_time( 'mysql' ),
                'file_format' => $format,
            ]
        );

        $upload_dir = wp_upload_dir();

        if ( ! empty( $upload_dir['error'] ) || empty( $upload_dir['basedir'] ) ) {
            $scheduled_manager->update_run_file_meta(
                $run_id,
                [
                    'status'      => 'error',
                    'finished_at' => current_time( 'mysql' ),
                    'file_format' => $format,
                    'log'         => \BadamSoft\WooProductExporter\Helpers\RunLogFormatter::formatFailureLog(
                        [
                            'error' => 'Uploads directory is not writable.',
                        ]
                    ),
                ]
            );
            return;
        }

        $root_dir = $this->settings_repository->resolve_export_root_directory( (string) ( $upload_dir['basedir'] ?? '' ) );
        $base_dir = trailingslashit( $root_dir . 'manual' );

        if ( ! wp_mkdir_p( $base_dir ) ) {
            $scheduled_manager->update_run_file_meta(
                $run_id,
                [
                    'status'      => 'error',
                    'finished_at' => current_time( 'mysql' ),
                    'file_format' => $format,
                    'log'         => \BadamSoft\WooProductExporter\Helpers\RunLogFormatter::formatFailureLog(
                        [
                            'error' => 'Unable to prepare the export directory.',
                        ]
                    ),
                ]
            );
            return;
        }

        $resolved_name = $this->exporter->resolve_filename_for_format( $settings, $format );
        $filename      = wp_unique_filename( $base_dir, $resolved_name );
        $file_path     = trailingslashit( $base_dir ) . $filename;

        try {
            $result = $this->exporter->export_to_file( $fields, $filters, $format, $settings, $file_path );
        } catch ( Throwable $exception ) {
            $scheduled_manager->update_run_file_meta(
                $run_id,
                [
                    'status'      => 'error',
                    'finished_at' => current_time( 'mysql' ),
                    'file_format' => $format,
                    'log'         => \BadamSoft\WooProductExporter\Helpers\RunLogFormatter::formatFailureLog(
                        [
                            'error' => $exception->getMessage(),
                        ]
                    ),
                ]
            );
            return;
        }

        $rows_exported = (int) ( $result['rows'] ?? 0 );
        $zip_path      = isset( $result['images_zip_path'] ) ? (string) $result['images_zip_path'] : '';
        $zip_size      = isset( $result['images_zip_size'] ) ? (int) $result['images_zip_size'] : 0;
        $file_size     = file_exists( $file_path ) ? (int) filesize( $file_path ) : 0;

        $scheduled_manager->update_run_file_meta(
            $run_id,
            [
                'status'        => 'success',
                'finished_at'   => current_time( 'mysql' ),
                'rows_exported' => $rows_exported,
                'file_path'     => $file_path,
                'file_size'     => $file_size,
                'file_format'   => $format,
                'log'           => \BadamSoft\WooProductExporter\Helpers\RunLogFormatter::formatSuccessLog(
                    [
                        'rows'        => $rows_exported,
                        'file_path'   => $file_path,
                        'file_format' => $format,
                    ]
                ),
            ]
        );

        if ( '' !== trim( $zip_path ) ) {
            $scheduled_manager->update_run_zip_meta( $run_id, $zip_path, $zip_size );
        }
    }

    /**
     * Register gettext filters used for runtime translation overrides.
     */
    public function register_translation_filters(): void {
        add_filter('gettext', [$this, 'translate_text'], 10, 3);
        add_filter('gettext_with_context', [$this, 'translate_text_with_context'], 10, 4);
    }

    /**
     * Register custom cron schedules used by the scheduler.
     */
    public function register_cron_filters(): void {
        return;
    }

    /**
     * Ensure the daily cleanup cron event is scheduled.
     */
    public function ensure_cleanup_cron_event(): void {
        if (!wp_next_scheduled('prodexfo_cleanup_exports')) {
            wp_schedule_event(time() + DAY_IN_SECONDS, 'daily', 'prodexfo_cleanup_exports');
        }
    }

    /**
     * Ensure the weekly database optimization cron event is scheduled
     * or unscheduled, depending on settings.
     */
    public function ensure_optimize_cron_event(): void {
        $state                 = $this->settings_repository->get_state();
        $auto_optimize_weekly  = !empty($state['database']['autoOptimizeWeekly'] ?? false);
        $scheduled_timestamp   = wp_next_scheduled(self::OPTIMIZE_HOOK);

        if ($auto_optimize_weekly) {
            if (!$scheduled_timestamp) {
                wp_schedule_event(time() + WEEK_IN_SECONDS, 'weekly', self::OPTIMIZE_HOOK);
            }

            return;
        }

        if ($scheduled_timestamp) {
            wp_unschedule_event($scheduled_timestamp, self::OPTIMIZE_HOOK);
        }
    }

    /**
     * Periodic task: clean up old export files and history rows.
     */
    public function maybe_cleanup_exports(): void {
        $state             = $this->settings_repository->get_state();
        $auto_cleanup      = !empty($state['general']['autoCleanup'] ?? false);
        $history_retention = isset($state['database']['historyRetention']) ? (string)$state['database']['historyRetention'] : 'all';

        global $wpdb;

        $manager = new ScheduledExportManager($wpdb);
        $table   = $this->get_validated_runs_table_name( $wpdb, $manager->get_runs_table() );

        if ( '' === $table ) {
            return;
        }

        if ($auto_cleanup) {
            $this->cleanup_old_export_files($wpdb, $table, 7);
        }

        $this->cleanup_history_by_retention($wpdb, $table, $history_retention);
    }

    /**
     * Delete export files older than specified days.
     *
     * @param \wpdb  $wpdb  WordPress database instance.
     * @param string $table Table name.
     * @param int    $days  Number of days to keep files.
     */
    private function cleanup_old_export_files(\wpdb $wpdb, string $table, int $days): void {
        $cutoff_timestamp = current_time('timestamp') - $days * DAY_IN_SECONDS;
        $cutoff           = \wp_date('Y-m-d H:i:s', $cutoff_timestamp);

        /** @var array<int, array<string, mixed>>|null $rows */
        $cache_group = 'prodexfo';
        $cache_key   = 'cleanup_old_export_files:' . md5( $table . '|' . $cutoff );
        $rows        = wp_cache_get( $cache_key, $cache_group );
        if ( false === $rows ) {
            $rows = $wpdb->get_results( // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter,WordPress.DB.DirectDatabaseQuery.DirectQuery
                $wpdb->prepare( 'SELECT id, file_path, images_zip_path FROM ' . $table . ' WHERE finished_at < %s AND (file_path IS NOT NULL OR images_zip_path IS NOT NULL)', $cutoff ), // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
                ARRAY_A
            );
            wp_cache_set( $cache_key, $rows, $cache_group, HOUR_IN_SECONDS );
        }

        if (!is_array($rows) || empty($rows)) {
            return;
        }

        foreach ($rows as $row) {
            $this->delete_export_file($row['file_path'] ?? '');
            $this->delete_export_file($row['images_zip_path'] ?? '');
        }
    }

    /**
     * Delete history records and files based on retention setting.
     *
     * @param \wpdb  $wpdb      WordPress database instance.
     * @param string $table     Table name.
     * @param string $retention Retention setting value.
     */
    private function cleanup_history_by_retention(\wpdb $wpdb, string $table, string $retention): void {
        $retention_days = $this->parse_history_retention_days($retention);

        if (null === $retention_days) {
            return;
        }

        $retention_cutoff_timestamp = current_time('timestamp') - ($retention_days * DAY_IN_SECONDS);
        $retention_cutoff           = \wp_date('Y-m-d H:i:s', $retention_cutoff_timestamp);

        $cache_group = 'prodexfo';
        $cache_key   = 'cleanup_history_by_retention:' . md5( $table . '|' . $retention_cutoff );
        $rows        = wp_cache_get( $cache_key, $cache_group );
        if ( false === $rows ) {
            $rows = $wpdb->get_results( // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter,WordPress.DB.DirectDatabaseQuery.DirectQuery
                $wpdb->prepare( 'SELECT id, file_path, images_zip_path FROM ' . $table . ' WHERE finished_at IS NOT NULL AND finished_at < %s', $retention_cutoff ), // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
                ARRAY_A
            );
            wp_cache_set( $cache_key, $rows, $cache_group, HOUR_IN_SECONDS );
        }

        if (is_array($rows) && !empty($rows)) {
            foreach ($rows as $row) {
                $this->delete_export_file($row['file_path'] ?? '');
                $this->delete_export_file($row['images_zip_path'] ?? '');
            }
        }

        $wpdb->query( // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter,WordPress.DB.DirectDatabaseQuery.DirectQuery
            $wpdb->prepare( 'DELETE FROM ' . $table . ' WHERE finished_at IS NOT NULL AND finished_at < %s', $retention_cutoff ) // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
        );

        wp_cache_delete( $cache_key, $cache_group );
    }

    /**
     * Safely delete an export file if it exists and is a local path.
     *
     * @param string $path File path to delete.
     */
    private function delete_export_file(string $path): void {
        $path = trim($path);

        if ('' === $path) {
            return;
        }

        if (preg_match('#^https?://#i', $path)) {
            return;
        }

        if (file_exists($path)) {
            wp_delete_file( $path );
        }
    }

    private function parse_history_retention_days(string $retention): ?int {
        if ('all' === $retention) {
            return null;
        }

        $allowed = [
            '30'  => 30,
            '90'  => 90,
            '180' => 180,
            '365' => 365,
        ];

        return $allowed[$retention] ?? null;
    }

    private function get_validated_runs_table_name( \wpdb $wpdb, string $table ): string {
        $table = trim( $table );

        if ( '' === $table ) {
            return '';
        }

        $expected = $wpdb->prefix . 'prodexfo_export_runs';

        if ( $table !== $expected ) {
            return '';
        }

        return $table;
    }

    /**
     * Periodic task: run MySQL OPTIMIZE TABLE on export tables when enabled.
     */
    public function maybe_optimize_database(): void {
        $state                = $this->settings_repository->get_state();
        $auto_optimize_weekly = !empty($state['database']['autoOptimizeWeekly'] ?? false);

        if (!$auto_optimize_weekly) {
            $timestamp = wp_next_scheduled(self::OPTIMIZE_HOOK);

            if ($timestamp) {
                wp_unschedule_event($timestamp, self::OPTIMIZE_HOOK);
            }

            return;
        }

        global $wpdb;

        $manager = new ScheduledExportManager($wpdb);

        $tables  = [ $this->get_validated_runs_table_name( $wpdb, $manager->get_runs_table() ) ];

        foreach ($tables as $table) {
            if (empty($table)) {
                continue;
            }

            $wpdb->query( 'OPTIMIZE TABLE ' . $table ); // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.DirectDatabaseQuery.NoCaching
        }
    }

    private function bootstrap_format_manager(): FormatManager {
        $writers = [new CsvWriter()];

        $writers = apply_filters( 'prodexfo_export_writers', $writers );

        $manager = new FormatManager($writers);

        /** This filter allows extending available formats. */
        return apply_filters('prodexfo_format_manager', $manager);
    }

    /**
     * Bootstrap the plugin singleton and register activation hook.
     *
     * @param string $plugin_file Absolute path to the main plugin file.
     */
    public static function init(string $plugin_file): void {
        if (null === self::$instance) {
            self::$instance = new self($plugin_file);
            register_activation_hook($plugin_file, [self::$instance, 'activate']);
        }
    }

    /**
     * Get the current plugin singleton instance.
     *
     * @return self|null
     */
    public static function instance(): ?self {
        return self::$instance;
    }

    /**
     * Plugin activation handler.
     */
    public function activate(): void {
        global $wpdb;
        $installer = new Installer($wpdb);
        $installer->install( false );

        $this->create_export_directory_protection();
    }

    /**
     * Create .htaccess protection for export directories.
     */
    private function create_export_directory_protection(): void {
        $upload_dir = wp_upload_dir();

        if ( ! empty( $upload_dir['error'] ) || empty( $upload_dir['basedir'] ) ) {
            return;
        }

        $export_root = $this->settings_repository->resolve_export_root_directory( $upload_dir['basedir'] );

        if ( ! is_dir( $export_root ) ) {
            wp_mkdir_p( $export_root );
        }

        $htaccess_path = trailingslashit( $export_root ) . '.htaccess';

        if ( file_exists( $htaccess_path ) ) {
            return;
        }

        $htaccess_content = "# Badamsoft Product Exporter for WooCommerce - Export Directory Protection\n";
        $htaccess_content .= "# Deny direct access to export files\n\n";
        $htaccess_content .= "<FilesMatch \".*\">\n";
        $htaccess_content .= "    Order Allow,Deny\n";
        $htaccess_content .= "    Deny from all\n";
        $htaccess_content .= "</FilesMatch>\n";

        file_put_contents( $htaccess_path, $htaccess_content ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents
    }

    /**
     * Get the base plugin URL.
     */
    public function get_plugin_url(): string {
        return $this->plugin_url;
    }

    /**
     * Get the base plugin path on disk.
     */
    public function get_plugin_path(): string {
        return $this->plugin_path;
    }

    /**
     * Resolve an absolute path to a view file inside views/.
     *
     * @param string $file Optional relative file name.
     * @return string
     */
    public function get_view_path(string $file = ''): string {
        $shared = trailingslashit( $this->plugin_path ) . 'views/';

        if ( '' === $file ) {
            return $shared;
        }

        $relative  = ltrim( $file, '/\\' );
        $candidate = $shared . $relative;

        if ( file_exists( $candidate ) ) {
            return $candidate;
        }

        return $candidate;
    }

    /**
     * Get the main product exporter service.
     */
    public function get_exporter(): Exporter {
        return $this->exporter;
    }

    /**
     * Get the license manager service.
     */
    public function get_license_manager(): object {
        $this->ensure_license_services();

        return $this->license_manager instanceof \stdClass ? (object) [] : ( $this->license_manager ?: (object) [] );
    }

    /**
     * Get the license service helper.
     */
    public function get_license_service(): object {
        $this->ensure_license_services();

        return $this->license_service instanceof \stdClass ? (object) [] : ( $this->license_service ?: (object) [] );
    }

    private function ensure_license_services(): void {
        if ( null !== $this->license_manager && null !== $this->license_service ) {
            return;
        }

        $license_manager_class = '\\BadamSoft\\WooProductExporter\\Licensing\\LicenseManager';
        $license_service_class = '\\BadamSoft\\WooProductExporter\\Licensing\\LicenseService';

        if ( ! class_exists( $license_manager_class ) || ! class_exists( $license_service_class ) ) {
            return;
        }

        $this->license_manager = new $license_manager_class();
        $this->license_service = new $license_service_class( $this->license_manager );
    }

    /**
     * Summary license information exposed to the frontend and REST API.
     *
     * @return array<string, scalar|null>
     */
    public function get_license_strings(): array {
        $this->ensure_license_services();

        if ( ! is_object( $this->license_manager ) || ! is_object( $this->license_service ) ) {
            return [
                'isPro'            => false,
                'license'          => '',
                'domain'           => home_url(),
                'status'           => '',
                'expires'          => '',
                'customer_email'   => '',
                'plan'             => '',
                'activated_on'     => '',
                'site_count'       => null,
                'license_limit'    => null,
                'activations_left' => null,
                'last_check'       => '',
                'message'          => '',
            ];
        }

        try {
            $status = $this->license_service->get_license_status();
        } catch ( Throwable $exception ) {
            $status = [
                'license'    => 'error',
                'message'    => $exception->getMessage(),
                'last_check' => current_time( 'mysql' ),
            ];
        }

        $license_key   = (string) $this->license_manager->get_license_key();
        $license_state = is_array( $status ) ? (string) ( $status['license'] ?? '' ) : '';
        $is_valid      = in_array( $license_state, [ 'valid', 'active' ], true );

        return [
            'isPro'            => $is_valid,
            'license'          => $license_key,
            'domain'           => (string) ( is_array( $status ) ? ( $status['site'] ?? home_url() ) : home_url() ),
            'status'           => $license_state,
            'expires'          => (string) ( is_array( $status ) ? ( $status['expires'] ?? '' ) : '' ),
            'customer_email'   => (string) ( is_array( $status ) ? ( $status['customer_email'] ?? '' ) : '' ),
            'plan'             => (string) ( is_array( $status ) ? ( $status['item_name'] ?? '' ) : '' ),
            'activated_on'     => (string) ( is_array( $status ) ? ( $status['activated'] ?? '' ) : '' ),
            'site_count'       => is_array( $status ) && isset( $status['site_count'] ) ? (int) $status['site_count'] : null,
            'license_limit'    => is_array( $status ) && isset( $status['license_limit'] ) ? (int) $status['license_limit'] : null,
            'activations_left' => is_array( $status ) && isset( $status['activations_left'] ) ? (int) $status['activations_left'] : null,
            'last_check'       => (string) ( is_array( $status ) ? ( $status['last_check'] ?? '' ) : '' ),
            'manage_url'       => (string) ( is_array( $status ) ? ( $status['manage_url'] ?? '' ) : '' ),
            'portal_url'       => (string) ( is_array( $status ) ? ( $status['portal_url'] ?? '' ) : '' ),
            'message'          => (string) ( is_array( $status ) ? ( $status['message'] ?? '' ) : '' ),
        ];
    }

    /**
     * Get the template manager service.
     */
    public function get_template_manager(): TemplateManager {
        return $this->template_manager;
    }

    public function load_textdomain(): void {
        return;
    }

    /**
     * Filter gettext strings for the plugin text domain.
     *
     * @param string $translated Already translated text.
     * @param string $text       Original text.
     * @param string $domain     Text domain.
     * @return string
     */
    public function translate_text( string $translated, string $text, string $domain ): string {
        if ( 'badamsoft-product-exporter-for-woocommerce' !== $domain ) {
            return $translated;
        }

        if ( ! apply_filters( 'prodexfo_enable_translations', true ) ) {
            return $translated;
        }

        return $this->translate_string( $text );
    }

    /**
     * Filter gettext_with_context strings for the plugin text domain.
     *
     * @param string $translated Already translated text.
     * @param string $text       Original text.
     * @param string $context    Translation context.
     * @param string $domain     Text domain.
     * @return string
     */
    public function translate_text_with_context( string $translated, string $text, string $context, string $domain ): string {
        if ( 'badamsoft-product-exporter-for-woocommerce' !== $domain ) {
            return $translated;
        }

        return $this->translate_string( $text, $context ) ?: $translated;
    }

    private function translate_string( string $text, string $context = '' ): string {
        $translations = $this->get_locale_translations();
        $key          = $context ? $context . '|' . $text : $text;

        return $translations[ $key ] ?? $text;
    }

    /**
     * @return array<string, string>
     */
    private function get_locale_translations(): array {
        $locale = determine_locale();

        if ( isset( $this->translation_map[ $locale ] ) ) {
            return $this->translation_map[ $locale ];
        }

        $translations                  = $this->load_translations_for_locale( $locale );
        $this->translation_map[ $locale ] = $translations;

        return $translations;
    }

    /**
     * @return array<string, string>
     */
    private function load_translations_for_locale( string $locale ): array {
        $locales = $this->get_supported_locale_map();

        if ( ! isset( $locales[ $locale ] ) ) {
            $locale_base = substr( $locale, 0, 2 );

            foreach ( $locales as $key => $file ) {
                if ( 0 === strpos( $key, $locale_base ) ) {
                    $locale = $key;
                    break;
                }
            }

            if ( ! isset( $locales[ $locale ] ) ) {
                return [];
            }
        }

        $file = $locales[ $locale ];

        if ( ! file_exists( $file ) ) {
            return [];
        }

        $data = include $file;
        $translations = is_array( $data ) ? $data : [];

        return $translations;
    }

    /**
     * @return array<string, string>
     */
    /**
     * Get the list of supported locale keys for custom translations.
     *
     * @return array<string, string>
     */
    public function get_supported_locale_keys(): array {
        return array_keys( $this->get_supported_locale_map() );
    }

    /**
     * @return array<string, string>
     */
    private function get_supported_locale_map(): array {
        $path = trailingslashit( $this->plugin_path ) . 'languages/';

        return [
            'en_US' => $path . 'badamsoft-product-exporter-for-woocommerce-en_US.php',
            'pt_BR' => $path . 'badamsoft-product-exporter-for-woocommerce-pt_BR.php',
            'ru_RU' => $path . 'badamsoft-product-exporter-for-woocommerce-ru_RU.php',
            'es_ES' => $path . 'badamsoft-product-exporter-for-woocommerce-es_ES.php',
            'fr_FR' => $path . 'badamsoft-product-exporter-for-woocommerce-fr_FR.php',
            'de_DE' => $path . 'badamsoft-product-exporter-for-woocommerce-de_DE.php',
            'he_IL' => $path . 'badamsoft-product-exporter-for-woocommerce-he_IL.php',
            'tr_TR' => $path . 'badamsoft-product-exporter-for-woocommerce-tr_TR.php',
            'zh_CN' => $path . 'badamsoft-product-exporter-for-woocommerce-zh_CN.php',
            'ar_AE' => $path . 'badamsoft-product-exporter-for-woocommerce-ar_AE.php',
            'hi_IN' => $path . 'badamsoft-product-exporter-for-woocommerce-hi_IN.php',
            'it_IT' => $path . 'badamsoft-product-exporter-for-woocommerce-it_IT.php',
        ];
    }
}
