<?php
/**
 * Settings sanitization helpers for admin screens.
 *
 * @package WPR_Translate
 */

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

/**
 * Return post types that must be excluded from automatic translation flows.
 *
 * @return array<int,string>
 */
function wpr_translate_get_auto_translation_excluded_post_types() {
    $excluded_post_types = array(
        'attachment',
        'nav_menu_item',
        'wp_navigation',
        'wp_template',
        'wp_template_part',
        'wp_block',
        'elementor_library',
        'wp_font_family',
        'wp_font_face',
        // Transactional records should not be translated.
        'wpestate_booking',
        'wpestate_invoice',
    );

    $excluded_post_types = apply_filters( 'wpr_translate_auto_translation_excluded_post_types', $excluded_post_types );

    if ( ! is_array( $excluded_post_types ) ) {
        return array();
    }

    $sanitized = array();

    foreach ( $excluded_post_types as $post_type ) {
        $post_type = sanitize_key( (string) $post_type );

        if ( '' === $post_type ) {
            continue;
        }

        $sanitized[] = $post_type;
    }

    return array_values( array_unique( $sanitized ) );
}

/**
 * Sanitize the languages option payload.
 *
 * @param array $languages Submitted languages list.
 *
 * @return array
 */
function wpr_translate_admin_sanitize_languages( $languages ) {
    if ( ! is_array( $languages ) ) {
        return array();
    }

    $sanitized    = array();
    $default_code = '';

    foreach ( $languages as $language ) {
        if ( ! is_array( $language ) ) {
            continue;
        }

        // Merge defaults so each language has a consistent shape.
        $language = wp_parse_args(
            $language,
            array(
                'code'          => '',
                'locale'        => '',
                'name'          => '',
                'slug'          => '',
                'is_default'    => false,
                'is_active'     => false,
                'is_public'     => false,
                'flag'          => '',
                'date_format'   => '',
                'time_format'   => '',
                'display_order' => 0,
            )
        );

        $language['code'] = sanitize_text_field( $language['code'] );

        if ( '' === $language['code'] ) {
            continue;
        }

        // Sanitize individual language fields.
        $language['locale']      = sanitize_text_field( $language['locale'] );
        $language['name']        = sanitize_text_field( $language['name'] );
        $language['slug']        = sanitize_title( $language['slug'] );
        $language['is_active']   = ! empty( $language['is_active'] );
        $language['is_public']   = ! empty( $language['is_public'] );
        $language['flag']        = sanitize_key( $language['flag'] );
        $language['date_format'] = sanitize_text_field( $language['date_format'] );
        $language['time_format'] = sanitize_text_field( $language['time_format'] );

        $language['display_order'] = isset( $language['display_order'] ) ? absint( $language['display_order'] ) : 0;

        if ( ! empty( $language['is_default'] ) && '' === $default_code ) {
            // Track the first default language encountered.
            $default_code = $language['code'];
        }

        $sanitized[] = $language;
    }

    if ( empty( $sanitized ) ) {
        return array();
    }

    // Sort by display order for consistent ordering.
    usort(
        $sanitized,
        static function ( $a, $b ) {
            return $a['display_order'] <=> $b['display_order'];
        }
    );

    $unique = array();

    foreach ( $sanitized as $language ) {
        // Ensure one entry per language code.
        $unique[ $language['code'] ] = $language;
    }

    $sanitized = array_values( $unique );

    if ( '' === $default_code ) {
        foreach ( $sanitized as $language ) {
            if ( $language['is_active'] ) {
                // Use the first active language as the default.
                $default_code = $language['code'];
                break;
            }
        }
    }

    if ( '' === $default_code && isset( $sanitized[0]['code'] ) ) {
        // Fall back to the first language entry.
        $default_code = $sanitized[0]['code'];
    }

    foreach ( $sanitized as $index => &$language ) {
        // Normalize display order and ensure a single default.
        $language['display_order'] = $index;
        $language['is_default']    = ( $language['code'] === $default_code );

        if ( $language['is_default'] ) {
            // Default language is always active.
            $language['is_active'] = true;
        }
    }

    unset( $language );

    $previous_languages = get_option( 'wpr_translate_languages', array() );

    if ( function_exists( 'wpr_translate_admin_maybe_install_language_packs' ) ) {
        // Download language packs for any newly added locales.
        wpr_translate_admin_maybe_install_language_packs( $previous_languages, $sanitized );
    }

    if ( $previous_languages !== $sanitized && function_exists( 'flush_rewrite_rules' ) ) {
        // Refresh rewrites so language-prefixed URLs resolve after language changes.
        flush_rewrite_rules();
    }

    return $sanitized;
}

/**
 * Sanitize plugin settings payload.
 *
 * @param array $settings Submitted settings.
 *
 * @return array
 */
function wpr_translate_admin_sanitize_settings( $settings ) {
    // Merge settings with defaults.
    $settings = wp_parse_args(
        $settings,
        array(
            'default_language'        => '',
            'url_strategy'            => 'subdirectory',
            'sync_media'              => true,
            'elementor_compatibility' => true,
            'taxonomy_modes'          => array(),
            'taxonomy_auto_duplicate' => array(),
            'menu_language_switcher'  => array(),
        )
    );

    $settings['default_language']        = sanitize_text_field( $settings['default_language'] );
    // Only the subdirectory strategy is supported in the settings UI.
    $settings['url_strategy']            = 'subdirectory';
    $settings['sync_media']              = (bool) $settings['sync_media'];
    $settings['elementor_compatibility'] = (bool) $settings['elementor_compatibility'];
    unset( $settings['auto_update_glossary'] );

    $taxonomy_modes          = array();
    $taxonomy_auto_duplicate = array();
    $menu_language_switcher  = array();

    if ( isset( $settings['taxonomy_modes'] ) && is_array( $settings['taxonomy_modes'] ) ) {
        foreach ( $settings['taxonomy_modes'] as $taxonomy => $mode ) {
            $taxonomy = sanitize_key( $taxonomy );

            if ( '' === $taxonomy ) {
                continue;
            }

            $mode = sanitize_key( $mode );

            if ( ! in_array( $mode, array( 'translate', 'not_translatable' ), true ) ) {
                $mode = 'translate';
            }

            // Store validated taxonomy modes.
            $taxonomy_modes[ $taxonomy ] = $mode;
        }
    }

    $settings['taxonomy_modes'] = $taxonomy_modes;

    if ( isset( $settings['taxonomy_auto_duplicate'] ) && is_array( $settings['taxonomy_auto_duplicate'] ) ) {
        foreach ( $settings['taxonomy_auto_duplicate'] as $taxonomy => $enabled ) {
            $taxonomy = sanitize_key( $taxonomy );

            if ( '' === $taxonomy ) {
                continue;
            }

            // Store auto-duplicate settings per taxonomy.
            $taxonomy_auto_duplicate[ $taxonomy ] = ! empty( $enabled );
        }
    }

    $settings['taxonomy_auto_duplicate'] = $taxonomy_auto_duplicate;

    if ( isset( $settings['menu_language_switcher'] ) && is_array( $settings['menu_language_switcher'] ) ) {
        // Keep only valid menu locations and positions for inserting the language switcher.
        $registered_locations = function_exists( 'get_registered_nav_menus' ) ? get_registered_nav_menus() : array();
        $allowed_locations    = array();

        if ( ! empty( $registered_locations ) ) {
            foreach ( $registered_locations as $location => $label ) {
                $location_key = sanitize_key( $location );

                if ( '' !== $location_key ) {
                    // Track allowed menu locations.
                    $allowed_locations[ $location_key ] = true;
                }
            }
        }

        foreach ( $settings['menu_language_switcher'] as $location => $position ) {
            $location_key = sanitize_key( $location );
            $position_key = sanitize_key( $position );

            if ( '' === $location_key || ! in_array( $position_key, array( 'before', 'after' ), true ) ) {
                continue;
            }

            if ( ! empty( $allowed_locations ) && ! isset( $allowed_locations[ $location_key ] ) ) {
                continue;
            }

            // Store the validated location/position pair.
            $menu_language_switcher[ $location_key ] = $position_key;
        }
    }

    $settings['menu_language_switcher'] = $menu_language_switcher;

    return $settings;
}

/**
 * Sanitize automatic translation settings payload.
 *
 * @param array $settings Submitted settings.
 *
 * @return array
 */
function wpr_translate_admin_sanitize_auto_translation_settings( $settings ) {
    // Merge auto translation settings with defaults.
    $settings = wp_parse_args(
        is_array( $settings ) ? $settings : array(),
        array(
            'enabled'        => false,
            'engine'         => 'openai',
            'openai_api_key' => '',
            'openai_system_prompt' => 'You are a translator that converts WordPress post data into the requested language.',
            'openai_user_prompt'   => 'Translate the following WordPress post payload into the %1$s language.',
            'post_types'     => array(),
        )
    );

    $settings['enabled'] = ! empty( $settings['enabled'] );

    $allowed_engines = array( 'openai', 'google_translate', 'microsoft_azure', 'deepl' );
    $engine          = sanitize_key( $settings['engine'] );

    if ( ! in_array( $engine, $allowed_engines, true ) ) {
        $engine = 'openai';
    }

    $settings['engine']         = $engine;
    $settings['openai_api_key'] = sanitize_text_field( $settings['openai_api_key'] );
    $settings['openai_system_prompt'] = sanitize_textarea_field( $settings['openai_system_prompt'] );
    $settings['openai_user_prompt']   = sanitize_textarea_field( $settings['openai_user_prompt'] );

    $available_post_types = get_post_types( array( 'show_ui' => true ), 'names' );
    $available_post_types = is_array( $available_post_types ) ? $available_post_types : array();
    $excluded_post_types  = wpr_translate_get_auto_translation_excluded_post_types();

    if ( ! empty( $excluded_post_types ) ) {
        $available_post_types = array_values( array_diff( $available_post_types, $excluded_post_types ) );
    }
    $submitted_post_types = array();

    if ( isset( $settings['post_types'] ) && is_array( $settings['post_types'] ) ) {
        $submitted_post_types = $settings['post_types'];
    } else {
        // Reuse stored values when none are submitted.
        $existing_settings = get_option( 'wpr_translate_auto_translation', array() );
        $existing_settings = is_array( $existing_settings ) ? $existing_settings : array();

        if ( isset( $existing_settings['post_types'] ) && is_array( $existing_settings['post_types'] ) ) {
            $submitted_post_types = $existing_settings['post_types'];
        }
    }

    $post_type_settings = array();

    if ( ! empty( $submitted_post_types ) ) {
        // Sanitize post type preferences.
        foreach ( $submitted_post_types as $post_type_name => $preference ) {
            $post_type_name = sanitize_key( $post_type_name );

            if ( '' === $post_type_name || ! in_array( $post_type_name, $available_post_types, true ) ) {
                continue;
            }

            $post_type_settings[ $post_type_name ] = ( 'yes' === $preference ) ? 'yes' : 'no';
        }
    }

    $settings['post_types'] = $post_type_settings;

    return $settings;
}

/**
 * Sanitize glossary entries.
 *
 * @param array $glossary Submitted glossary.
 *
 * @return array
 */
function wpr_translate_admin_sanitize_glossary( $glossary ) {
    if ( ! is_array( $glossary ) ) {
        return array();
    }

    // Sanitize each glossary entry.
    return array_map(
        static function ( $entry ) {
            $entry = wp_parse_args(
                $entry,
                array(
                    'source'      => '',
                    'translation' => '',
                    'context'     => '',
                )
            );

            $entry['source']      = sanitize_text_field( $entry['source'] );
            $entry['translation'] = sanitize_text_field( $entry['translation'] );
            $entry['context']     = sanitize_text_field( $entry['context'] );

            return $entry;
        },
        $glossary
    );
}

