<?php

namespace Silvanus\blocks\sliders\TestimonialSlider;

use Silvanus\includes\blocks\BlockModuleInterface;
use Timber\Timber;

final class Module implements BlockModuleInterface
{
    public function register(): void
    {
        add_filter('timber/acf-gutenberg-blocks-data/testimonial-slider', [$this, 'addContext'], 20);
        add_filter('acf/load_field/name=fields_to_show', [$this, 'acfPopulateFieldsToShowChoices'], 20);
    }

    public function acfPopulateFieldsToShowChoices(array $field): array
    {
        // Guard: only affect our block field (prevents collisions with other fields also named fields_to_show)
        $key = (string) ($field['key'] ?? '');
        if ($key === '' || !str_contains($key, 'testimonial_slider')) {
            return $field;
        }

        $field['choices'] = $this->getTestimonialCptAcfChoices();

        return $field;
    }

    /**
     * Reads content/types/testimonial.cpt.php and extracts ACF field names/labels
     * from the returned `acf_field_groups` definitions.
     *
     * @return array<string, string> choices as [ field_name => label ]
     */
    private function getTestimonialCptAcfChoices(): array
    {
        $path = get_template_directory() . '/content/types/testimonial.cpt.php';
        if (!is_readable($path)) {
            return [];
        }

        $def = require $path;
        if (!is_array($def)) {
            return [];
        }

        $groups = $def['acf_field_groups'] ?? [];
        if (!is_array($groups) || empty($groups)) {
            return [];
        }

        $choices = [];

        foreach ($groups as $group) {
            if (!is_array($group)) {
                continue;
            }
            $fields = $group['fields'] ?? [];
            if (!is_array($fields)) {
                continue;
            }

            $this->extractAcfFieldChoicesRecursive($fields, $choices);
        }

        // Optional: stable ordering by label
        asort($choices);

        return $choices;
    }

    /**
     * @param array<int, array> $fields
     * @param array<string, string> $choices
     */
    private function extractAcfFieldChoicesRecursive(array $fields, array &$choices): void
    {
        foreach ($fields as $f) {
            if (!is_array($f)) {
                continue;
            }

            $name = isset($f['name']) && is_string($f['name']) ? trim($f['name']) : '';
            $label = isset($f['label']) && is_string($f['label']) ? trim($f['label']) : '';

            if ($name !== '') {
                $choices[$name] = $label !== '' ? $label : $name;
            }

            // Recurse into groups/repeaters/flexible layouts if ever added later
            $sub = $f['sub_fields'] ?? null;
            if (is_array($sub) && !empty($sub)) {
                $this->extractAcfFieldChoicesRecursive($sub, $choices);
            }
        }
    }

    public function addContext(array $context): array
    {
        $fields = $context['fields'] ?? [];
        if (!is_array($fields)) {
            $fields = [];
        }

        $source = $fields['source'] ?? [];
        if (!is_array($source)) {
            $source = [];
        }

        $useManual = !empty($source['use_manual']);
        $manualIds = $source['manual_testimonials'] ?? [];

        if ($useManual && is_array($manualIds) && !empty($manualIds)) {
            $ids = array_values(array_filter(array_map('intval', $manualIds)));

            $posts = Timber::get_posts([
                'post_type' => 'testimonial',
                'post__in' => $ids,
                'orderby' => 'post__in',
                'posts_per_page' => count($ids),
                'post_status' => 'publish',
            ]);
        } else {
            $max = (int) ($source['max_posts'] ?? 6);
            if ($max < 1) {
                $max = 6;
            }

            $posts = Timber::get_posts([
                'post_type' => 'testimonial',
                'posts_per_page' => $max,
                'post_status' => 'publish',
                'orderby' => 'date',
                'order' => 'DESC',
            ]);
        }

        $selected = $fields['fields_to_show'] ?? [];
        $selected = is_array($selected) ? array_values(array_filter($selected, 'is_string')) : [];

        // Allow only fields that exist in the CPT ACF group definition (prevents arbitrary meta access)
        $allowedChoices = $this->getTestimonialCptAcfChoices(); // [name => label]
        $allowedNames = array_fill_keys(array_keys($allowedChoices), true);

        $selectedSafe = [];
        foreach ($selected as $name) {
            $name = trim($name);
            if ($name !== '' && isset($allowedNames[$name])) {
                $selectedSafe[] = $name;
            }
        }

        $testimonials = [];
        foreach ($posts as $p) {
            $id = (int) ($p->ID ?? 0);
            if ($id <= 0) {
                continue;
            }

            $meta = [];
            foreach ($selectedSafe as $fieldName) {
                $val = get_field($fieldName, $id);

                if (is_string($val)) {
                    $val = trim($val);
                }

                // Light sanitation for known URL fields (optional)
                if (in_array($fieldName, ['client_website', 'project_link'], true) && is_string($val)) {
                    $val = esc_url_raw($val);
                }

                $meta[$fieldName] = $val;
            }

            // Convenience: formatted date when the selected field is testimonial_date
            if (isset($meta['testimonial_date']) && is_string($meta['testimonial_date']) && $meta['testimonial_date'] !== '') {
                $ts = strtotime($meta['testimonial_date']);
                if ($ts) {
                    $meta['testimonial_date_formatted'] = date_i18n(get_option('date_format') ?: 'F j, Y', $ts);
                }
            }

            $testimonials[] = [
                'ID' => $id,
                'title' => (string) get_the_title($id),
                'meta' => $meta,
            ];
        }

        $context['testimonials'] = $testimonials;
        $context['testimonial_fields_to_show'] = array_fill_keys($selectedSafe, true);

        return $context;
    }
}