<?php
namespace Softech_Addons_for_Elementor\Includes\Dynamic_Tags\Tags\Post_Tags;

use Elementor\Controls_Manager;
use Elementor\Core\DynamicTags\Tag;
use Elementor\Modules\DynamicTags\Module;
use Softech_Addons_for_Elementor\Includes\Dynamic_Tags\Groups\Softech_Post_Group;

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

/**
 * ACF Field Group – Dynamic Tag
 *
 * Exposes any ACF (Advanced Custom Fields) field value as an Elementor
 * dynamic tag.  The user selects the ACF field group from a dropdown,
 * then picks a field within that group from a second dropdown.
 * The meta key is resolved automatically from the selected field, but can
 * also be entered manually (handy for sub-fields or fields not yet
 * registered in ACF's field-group UI).
 *
 * Supports:
 *  - Text, textarea, number, email, URL, select, radio, checkbox fields
 *  - Term and user contexts (not just posts)
 *  - Graceful fallback when ACF is not active
 *
 * Placed in: includes/dynamic-tags/tags/post-tags/
 * Auto-discovered by the plugin's register_dynamic_tags() loader.
 */
class Softech_Acf_Field_Group extends Tag {

    // ─────────────────────────────────────────────────────────────────────────
    // Identity
    // ─────────────────────────────────────────────────────────────────────────

    public function get_name() {
        return 'softech-acf-field-group';
    }

    public function get_title() {
        return esc_html__( 'ACF Field Group', 'softech-addons-for-elementor' );
    }

    public function get_group() {
        return Softech_Post_Group::get_name();
    }

    public function get_categories() {
        return [
            Module::TEXT_CATEGORY,
            Module::POST_META_CATEGORY,
            Module::NUMBER_CATEGORY,
            Module::URL_CATEGORY,
        ];
    }

    // ─────────────────────────────────────────────────────────────────────────
    // Controls
    // ─────────────────────────────────────────────────────────────────────────

    protected function register_controls() {

        // ── Field Group selector ──────────────────────────────────────────
        $this->add_control(
            'acf_field_group',
            [
                'label'       => esc_html__( 'Field Group', 'softech-addons-for-elementor' ),
                'type'        => Controls_Manager::SELECT,
                'options'     => $this->get_acf_field_group_options(),
                'default'     => '',
                'description' => esc_html__( 'Select the ACF field group that contains your field.', 'softech-addons-for-elementor' ),
                'dynamic'     => [ 'active' => false ],
            ]
        );

        // ── Field selector (populated from the chosen group) ──────────────
        // Because Elementor dynamic-tag controls are static (no Ajax
        // dependency), we list every field from every group and show the
        // meta key alongside the label so the user always knows what key
        // will be used.
        $this->add_control(
            'acf_field_key',
            [
                'label'       => esc_html__( 'Field', 'softech-addons-for-elementor' ),
                'type'        => Controls_Manager::SELECT,
                'options'     => $this->get_acf_field_options(),
                'default'     => '',
                'description' => esc_html__( 'Pick a field. Its meta key is used to retrieve the value.', 'softech-addons-for-elementor' ),
                'dynamic'     => [ 'active' => false ],
            ]
        );

        // ── Manual meta key override ──────────────────────────────────────
        $this->add_control(
            'meta_key_override',
            [
                'label'       => esc_html__( 'Meta Key (manual override)', 'softech-addons-for-elementor' ),
                'type'        => Controls_Manager::TEXT,
                'placeholder' => esc_html__( 'e.g. _my_custom_field', 'softech-addons-for-elementor' ),
                'description' => esc_html__( 'Optional. Leave blank to use the field selected above. Useful for sub-fields or keys not visible in the dropdown.', 'softech-addons-for-elementor' ),
                'dynamic'     => [ 'active' => false ],
            ]
        );

        // ── Output format ─────────────────────────────────────────────────
        $this->add_control(
            'output_format',
            [
                'label'   => esc_html__( 'Output Format', 'softech-addons-for-elementor' ),
                'type'    => Controls_Manager::SELECT,
                'options' => [
                    'formatted' => esc_html__( 'Formatted (ACF get_field)', 'softech-addons-for-elementor' ),
                    'raw'       => esc_html__( 'Raw (get_post_meta)', 'softech-addons-for-elementor' ),
                ],
                'default'     => 'formatted',
                'description' => esc_html__( '"Formatted" uses ACF\'s get_field() which respects field type. "Raw" reads the database value directly.', 'softech-addons-for-elementor' ),
                'dynamic'     => [ 'active' => false ],
            ]
        );

        // ── Separator for array/checkbox values ───────────────────────────
        $this->add_control(
            'array_separator',
            [
                'label'       => esc_html__( 'Array Separator', 'softech-addons-for-elementor' ),
                'type'        => Controls_Manager::TEXT,
                'default'     => ', ',
                'description' => esc_html__( 'Used when the field returns multiple values (e.g. checkboxes). Default: ", "', 'softech-addons-for-elementor' ),
                'dynamic'     => [ 'active' => false ],
            ]
        );

        // ── Fallback text ─────────────────────────────────────────────────
        $this->add_control(
            'fallback_text',
            [
                'label'       => esc_html__( 'Fallback Text', 'softech-addons-for-elementor' ),
                'type'        => Controls_Manager::TEXT,
                'placeholder' => esc_html__( 'Shown when field is empty', 'softech-addons-for-elementor' ),
                'dynamic'     => [ 'active' => false ],
            ]
        );
    }

    // ─────────────────────────────────────────────────────────────────────────
    // Render
    // ─────────────────────────────────────────────────────────────────────────

    public function render() {
        $meta_key = $this->resolve_meta_key();

        if ( empty( $meta_key ) ) {
            echo wp_kses_post( $this->get_settings( 'fallback_text' ) );
            return;
        }

        $value = $this->get_field_value( $meta_key );

        if ( '' === $value || null === $value || false === $value ) {
            echo wp_kses_post( $this->get_settings( 'fallback_text' ) );
            return;
        }

        echo wp_kses_post( $this->stringify_value( $value ) );
    }

    // ─────────────────────────────────────────────────────────────────────────
    // Private helpers
    // ─────────────────────────────────────────────────────────────────────────

    /**
     * Determine the final meta key to use.
     *
     * Priority order:
     *   1. Manual override (meta_key_override)
     *   2. Selected ACF field key (acf_field_key)
     */
    private function resolve_meta_key(): string {
        $override = trim( (string) $this->get_settings( 'meta_key_override' ) );
        if ( '' !== $override ) {
            return $override;
        }

        $selected = trim( (string) $this->get_settings( 'acf_field_key' ) );
        return $selected;
    }

    /**
     * Retrieve the field value from the current context (post or term).
     *
     * @param string $meta_key
     * @return mixed
     */
    private function get_field_value( string $meta_key ) {
        $format = $this->get_settings( 'output_format' );

        // ── Taxonomy-term context ─────────────────────────────────────────
        $queried_object = get_queried_object();

        if ( $queried_object instanceof \WP_Term ) {
            if ( 'formatted' === $format && function_exists( 'get_field' ) ) {
                $term_context = $queried_object->taxonomy . '_' . $queried_object->term_id;
                $value        = get_field( $meta_key, $term_context );

                if ( '' !== $value && null !== $value && false !== $value ) {
                    return $value;
                }
            }

            return get_term_meta( $queried_object->term_id, $meta_key, true );
        }

        // ── Post context ──────────────────────────────────────────────────
        $post_id = get_the_ID();

        if ( ! $post_id ) {
            return '';
        }

        if ( 'formatted' === $format && function_exists( 'get_field' ) ) {
            return get_field( $meta_key, $post_id );
        }

        return get_post_meta( $post_id, $meta_key, true );
    }

    /**
     * Convert any value (array, object, scalar) to a printable string.
     *
     * @param mixed $value
     * @return string
     */
    private function stringify_value( $value ): string {
        // ── Already a string ──────────────────────────────────────────────
        if ( is_string( $value ) ) {
            return $value;
        }

        // ── Numeric scalar ────────────────────────────────────────────────
        if ( is_numeric( $value ) ) {
            return (string) $value;
        }

        // ── Array (checkboxes, multi-select, etc.) ────────────────────────
        if ( is_array( $value ) ) {
            $separator = $this->get_settings( 'array_separator' );
            if ( '' === $separator ) {
                $separator = ', ';
            }

            // Handle ACF choice-field arrays: ['value' => 'label', …]
            // When ACF returns formatted values these are already label strings.
            $parts = [];
            foreach ( $value as $item ) {
                if ( is_scalar( $item ) ) {
                    $parts[] = (string) $item;
                } elseif ( is_array( $item ) && isset( $item['label'] ) ) {
                    $parts[] = (string) $item['label'];
                } elseif ( is_array( $item ) && isset( $item['value'] ) ) {
                    $parts[] = (string) $item['value'];
                }
            }

            return implode( $separator, $parts );
        }

        // ── WP_Post object ────────────────────────────────────────────────
        if ( $value instanceof \WP_Post ) {
            return $value->post_title;
        }

        // ── WP_Term object ────────────────────────────────────────────────
        if ( $value instanceof \WP_Term ) {
            return $value->name;
        }

        // ── WP_User object ────────────────────────────────────────────────
        if ( $value instanceof \WP_User ) {
            return $value->display_name;
        }

        // ── Boolean ───────────────────────────────────────────────────────
        if ( is_bool( $value ) ) {
            return $value ? '1' : '';
        }

        return '';
    }

    // ─────────────────────────────────────────────────────────────────────────
    // Control option builders
    // ─────────────────────────────────────────────────────────────────────────

    /**
     * Build the options array for the Field Group dropdown.
     *
     * Returns an empty option first so the control has a neutral default,
     * then one entry per ACF field group (keyed by the group's post ID so
     * we can cross-reference with acf_get_fields() later).
     *
     * Falls back to a single "ACF not active" entry when the plugin is absent.
     *
     * @return array<string, string>
     */
    private function get_acf_field_group_options(): array {
        $options = [ '' => esc_html__( '— Select Group —', 'softech-addons-for-elementor' ) ];

        if ( ! function_exists( 'acf_get_field_groups' ) ) {
            $options['no_acf'] = esc_html__( 'ACF plugin not active', 'softech-addons-for-elementor' );
            return $options;
        }

        $groups = acf_get_field_groups();

        if ( empty( $groups ) ) {
            $options['no_groups'] = esc_html__( 'No ACF field groups found', 'softech-addons-for-elementor' );
            return $options;
        }

        foreach ( $groups as $group ) {
            $options[ $group['key'] ] = esc_html( $group['title'] );
        }

        return $options;
    }

    /**
     * Build the options array for the Field dropdown.
     *
     * Each option value is the field's meta key (name) so it can be passed
     * directly to get_field() / get_post_meta().  The label includes the
     * field type for clarity.
     *
     * @return array<string, string>
     */
    private function get_acf_field_options(): array {
        $options = [ '' => esc_html__( '— Select Field —', 'softech-addons-for-elementor' ) ];

        if ( ! function_exists( 'acf_get_field_groups' ) || ! function_exists( 'acf_get_fields' ) ) {
            $options['no_acf'] = esc_html__( 'ACF plugin not active', 'softech-addons-for-elementor' );
            return $options;
        }

        $groups = acf_get_field_groups();

        foreach ( $groups as $group ) {
            $fields = acf_get_fields( $group['key'] );

            if ( empty( $fields ) ) {
                continue;
            }

            foreach ( $fields as $field ) {
                // Skip layout / tab / message fields that have no meta value
                if ( in_array( $field['type'], [ 'tab', 'accordion', 'message', 'clone' ], true ) ) {
                    continue;
                }

                $label = sprintf(
                    '%s › %s (%s)',
                    esc_html( $group['title'] ),
                    esc_html( $field['label'] ),
                    esc_html( $field['type'] )
                );

                // Use the field's meta key (name) as the option value
                $options[ $field['name'] ] = $label;
            }
        }

        return $options;
    }
}