<?php
/**
 * ACF Integration class - handles Advanced Custom Fields translation
 * 
 * @package LangForge
 */

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

// IDE hints for autoloaded classes
if (false) {
    class LF_Core {}
    class LF_Post_Translation {}
}

class LF_ACF_Integration {
    
    private static $instance = null;
    
    public static function instance() {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    private function __construct() {
        // Bootstrap unconditionally — individual handlers guard for ACF / FieldForge
        // presence at fire time. The previous `class_exists('ACF')` early-return
        // skipped registration on Forge Suite sites that use FieldForge as the
        // ACF replacement, so options-page values were never resolved per language.
        $this->init_hooks();
    }
    
    private function init_hooks() {
        // Add translation info to ACF fields in admin
        add_action('acf/render_field_settings', [$this, 'add_translation_setting'], 10, 1);

        // Filter ACF field values based on language
        add_filter('acf/load_value', [$this, 'maybe_load_translated_value'], 10, 3);

        // Handle ACF options pages - language-specific options
        add_filter('acf/validate_save_post', [$this, 'add_language_to_options']);

        // Push current/default language into ACF settings on every request so
        // `get_field('foo', 'option')` / `have_rows('bar', 'option')` automatically
        // resolve to language-suffixed wp_options keys (`options_en_*`, `options_uz_*`).
        
        // ACF's built-in `acf_get_valid_post_id` already appends `_<lang>` to the
        // 'options' post_id when `default_language` ≠ `current_language`. We just
        // feed it the values — same contract WPML's ACFML add-on uses, so any
        // theme that worked with WPML + ACF Options Page works with LangForge
        // unchanged. (Summary: footer/contacts read address/phone/socials per
        // language; without this sync the EN frontend rendered RU values.)
        
        // Two hooks: `init` priority 99 catches the frontend / wp-admin path
        // (after LF_Core::detect_language at priority 1), `acf/init` covers
        // contexts where ACF boots later (REST, AJAX, CLI).
        add_action('init', [$this, 'sync_languages_to_acf'], 99);
        add_action('acf/init', [$this, 'sync_languages_to_acf']);

        // Same contract for FieldForge's ACF compatibility shim — used as the
        // ACF replacement on Forge Suite sites where ACF Pro isn't active.
        // FieldForge calls apply_filters('fieldforge/options_post_id', 'options', $orig)
        // when resolving an options-page post_id; we append the current language
        // suffix so reads/writes target separate wp_options + wp_fieldforge_options
        // partitions per language (`options_en_*`, `options_uz_*`, …).
        add_filter('fieldforge/options_post_id', [$this, 'filter_options_post_id'], 10, 2);
    }

    /**
 * Append the current LangForge language to FieldForge's options post_id so
 * ACF-style options-page lookups resolve to per-language wp_options rows.
 *
 * Honours the admin `?lf_lang=<code>` switcher so the theme settings page
 * reads/writes against the language tab the editor selected.
 */
    public function filter_options_post_id($post_id, $orig_post_id = null) {
        if (!is_string($post_id) || $post_id !== 'options') return $post_id;

        if (!class_exists('LF_Core')) return $post_id;
        $core    = LF_Core::instance();
        $default = $core->get_default_language();
        $current = $core->get_current_language();

        if (is_admin() && !empty($_GET['lf_lang'])) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only admin UI language routing, no data mutation.
            $override = sanitize_text_field((string) wp_unslash($_GET['lf_lang'])); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only ACF screen state, no data mutation.
            if ($override !== '') $current = $override;
        }

        if (!$current || $current === $default) return $post_id;

        return 'options_' . $current;
    }

    /**
 * Mirror LangForge current/default language into ACF settings.
 *
 * Admin override: when an admin URL carries `?lf_lang=<code>` (theme
 * settings page language switcher), that language is used so the options
 * form RENDERS and SAVES against that language's option keys.
 */
    public function sync_languages_to_acf() {
        if (!function_exists('acf_update_setting')) return;

        $core    = LF_Core::instance();
        $default = $core->get_default_language();
        $current = $core->get_current_language();

        if (is_admin() && !empty($_GET['lf_lang'])) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only admin UI language routing, no data mutation.
            $override = sanitize_text_field((string) wp_unslash($_GET['lf_lang'])); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only ACF screen state, no data mutation.
            if ($override !== '') {
                $current = $override;
            }
        }

        if ($default) acf_update_setting('default_language', $default);
        if ($current) acf_update_setting('current_language', $current);
    }
    
    public function add_translation_setting($field) {
        // Only render the ACF field-settings UI when ACF is actually present.
        if (!function_exists('acf_render_field_setting')) return;
        acf_render_field_setting($field, [
            'label' => __('Translatable', 'langforge'),
            'instructions' => __('Should this field be translated?', 'langforge'),
            'name' => 'lf_translatable',
            'type' => 'true_false',
            'ui' => 1,
            'default_value' => 1,
        ]);
    }
    
    public function maybe_load_translated_value($value, $post_id, $field) {
        // Skip if not translatable
        if (isset($field['lf_translatable']) && !$field['lf_translatable']) {
            return $value;
        }
        
        // Skip in admin
        if (is_admin()) {
            return $value;
        }
        
        // Check if we need to load from translation
        $current_lang = LF_Core::instance()->get_current_language();
        $post_lang = get_post_meta($post_id, '_lf_language', true);
        
        if ($post_lang && $post_lang !== $current_lang) {
            // Try to get translation
            $translation_id = LF_Post_Translation::instance()->get_translation($post_id, $current_lang);
            if ($translation_id) {
                $translated_value = get_field($field['name'], $translation_id, false);
                if ($translated_value !== null) {
                    return $translated_value;
                }
            }
        }
        
        return $value;
    }
    
    public function add_language_to_options() {
        // For options pages, append language to option name
        // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Read-only check of ACF's own submitted screen marker; no data mutation here (ACF verifies its own nonce on save).
        if (isset($_POST['acf']) && isset($_POST['_acf_screen']) && $_POST['_acf_screen'] === 'options') {
            // Options are handled separately
        }
    }
    
    /**
 * Copy ACF fields from one post to another
 */
    public function copy_acf_fields($source_post_id, $target_post_id) {
        if (!class_exists('ACF')) {
            return;
        }
        
        $field_groups = acf_get_field_groups(['post_id' => $source_post_id]);
        
        foreach ($field_groups as $field_group) {
            $fields = acf_get_fields($field_group);
            
            if (!$fields) {
                continue;
            }
            
            foreach ($fields as $field) {
                $this->copy_field_value($source_post_id, $target_post_id, $field);
            }
        }
    }
    
    private function copy_field_value($source_post_id, $target_post_id, $field) {
        $value = get_field($field['name'], $source_post_id, false);
        
        if ($value === null || $value === '') {
            return;
        }
        
        // Handle different field types
        switch ($field['type']) {
            case 'repeater':
                $this->copy_repeater_field($source_post_id, $target_post_id, $field);
                break;
                
            case 'flexible_content':
                $this->copy_flexible_content_field($source_post_id, $target_post_id, $field);
                break;
                
            case 'group':
                $this->copy_group_field($source_post_id, $target_post_id, $field);
                break;
                
            case 'image':
            case 'file':
            case 'gallery':
                // Copy media references as-is
                update_field($field['name'], $value, $target_post_id);
                break;
                
            case 'relationship':
            case 'post_object':
                // Keep original references, translations should be linked separately
                update_field($field['name'], $value, $target_post_id);
                break;
                
            default:
                update_field($field['name'], $value, $target_post_id);
                break;
        }
    }
    
    private function copy_repeater_field($source_post_id, $target_post_id, $field) {
        $value = get_field($field['name'], $source_post_id, false);
        
        if (!is_array($value)) {
            return;
        }
        
        // For repeaters, we copy the raw value
        update_field($field['name'], $value, $target_post_id);
    }
    
    private function copy_flexible_content_field($source_post_id, $target_post_id, $field) {
        $value = get_field($field['name'], $source_post_id, false);
        
        if (!is_array($value)) {
            return;
        }
        
        update_field($field['name'], $value, $target_post_id);
    }
    
    private function copy_group_field($source_post_id, $target_post_id, $field) {
        $value = get_field($field['name'], $source_post_id, false);
        
        if (!is_array($value)) {
            return;
        }
        
        update_field($field['name'], $value, $target_post_id);
    }
    
    /**
 * Get translatable ACF field groups
 */
    public function get_translatable_field_groups() {
        if (!function_exists('acf_get_field_groups')) {
            return [];
        }
        
        $groups = acf_get_field_groups();
        $translatable = [];
        
        foreach ($groups as $group) {
            $fields = acf_get_fields($group);
            $has_translatable = false;
            
            foreach ($fields as $field) {
                if (!isset($field['lf_translatable']) || $field['lf_translatable']) {
                    $has_translatable = true;
                    break;
                }
            }
            
            if ($has_translatable) {
                $translatable[] = $group;
            }
        }
        
        return $translatable;
    }
    
    /**
 * Sync media between translations (keep same media)
 */
    public function sync_media_fields($source_post_id, $target_post_id) {
        if (!class_exists('ACF')) {
            return;
        }
        
        $field_groups = acf_get_field_groups(['post_id' => $source_post_id]);
        
        foreach ($field_groups as $field_group) {
            $fields = acf_get_fields($field_group);
            
            if (!$fields) {
                continue;
            }
            
            foreach ($fields as $field) {
                if (in_array($field['type'], ['image', 'file', 'gallery'])) {
                    $value = get_field($field['name'], $source_post_id, false);
                    if ($value) {
                        update_field($field['name'], $value, $target_post_id);
                    }
                }
            }
        }
    }
}
