<?php
namespace UM_Elementor\Helpers;

if (!defined('ABSPATH')) {
    exit; // Exit if accessed directly
}

/**
 * User Meta Field Renderer
 * 
 * Centralized class for rendering Ultimate Member user meta fields
 * in Elementor widgets with consistent formatting and field type support.
 */
class UM_User_Meta_Renderer
{
    /**
     * Special field identifiers
     */
    private const SPECIAL_FIELDS = [
        'USER_AVATAR' => 'User Avatar',
        'PROFILE_PHOTO' => 'profile_photo',
        'COVER_PHOTO' => 'cover_photo'
    ];

    /**
     * YouTube URL patterns for video extraction
     */
    private const YOUTUBE_PATTERNS = [
        '/watch\?v=([a-zA-Z0-9_-]+)/',
        '/youtu\.be\/([a-zA-Z0-9_-]+)/',
        '/embed\/([a-zA-Z0-9_-]+)/',
        '/v\/([a-zA-Z0-9_-]+)/'
    ];

    /**
     * Render user meta fields from widget settings
     * 
     * @param array $settings Widget settings
     * @param string $control_name Settings key for meta fields
     * @return string Rendered HTML
     */
    public function render_meta_fields(array $settings, string $control_name = 'um_user_meta_control'): string
    {
        if (empty($settings[$control_name])) {
            return '';
        }

        $field_count = count($settings[$control_name]);

        ob_start();

        foreach ($settings[$control_name] as $item) {
            $standardized_item = $this->standardize_item($item);
            $this->render_single_meta_field($standardized_item);
        }

        return ob_get_clean();
    }

    /**
     * Render a single meta field item (for table widgets and specialized layouts)
     * 
     * @param array $item Field configuration array
     * @return string Rendered field HTML
     */
    public function render_single_field(array $item): string
    {
        if (!isset($item['um_user_meta_field_value'])) {
            return '';
        }

        $field_key = $item['um_user_meta_field_value'];
        $meta_value = um_user($field_key);

        if (empty($meta_value)) {
            return '';
        }

        ob_start();

        $this->render_field_label($item, $field_key);
        $this->render_field_value($field_key, $meta_value);

        return ob_get_clean();
    }

    /**
     * Render user meta with avatar (for specific layouts)
     * 
     * @param array $settings Widget settings
     * @param string $control_name Settings key
     */
    public function render_with_avatar(array $settings, string $control_name): void
    {
        if (empty($settings[$control_name])) {
            return;
        }

        foreach ($settings[$control_name] as $item) {
            $field_key = $item['um_user_meta_field_value'];

            if ($field_key === 'user_avatar') {
                $this->render_user_avatar();
            } else {
                $this->render_single_meta_field($item);
            }
        }
    }

    /**
     * Render Friends & Followers (specific for FNF module)
     * 
     * @param array $listing FNF configuration
     * @param int $user_id User ID
     */
    public function render_fnf(array $listing, int $user_id): void
    {
        $type = $listing['select'] ?? 'friends';

        $render_methods = [
            'friends' => 'render_friends',
            'following' => 'render_following',
            'followers' => 'render_followers'
        ];

        if (isset($render_methods[$type])) {
            $this->{$render_methods[$type]}($user_id);
        }
    }

    /**
     * Standardize item array for consistent processing
     * 
     * @param array $item Raw item array
     * @return array Standardized item array
     */
    private function standardize_item(array $item): array
    {
        $field_key = $item['um_user_meta_field_value'] ?? $item['um_user_meta_field_value_front'] ?? '';
        $show_label = $item['um_user_meta_field_label'] ?? $item['um_user_meta_field_label_front'] ?? 1;

        $out = [
            'um_user_meta_field_value' => $field_key,
            'um_user_meta_field_label' => $show_label,
        ];

        if (isset($item['field_visibility'])) {
            $out['field_visibility'] = $item['field_visibility'];
        }
        if (isset($item['field_visibility_roles'])) {
            $out['field_visibility_roles'] = $item['field_visibility_roles'];
        }

        foreach ( [
            'field_value_condition_enable',
            'field_value_condition_key',
            'field_value_condition_operator',
            'field_value_condition_value',
        ] as $vc_key ) {
            if ( isset( $item[ $vc_key ] ) ) {
                $out[ $vc_key ] = $item[ $vc_key ];
            }
        }

        return $out;
    }

    /**
     * Render a single meta field with wrapper
     * 
     * @param array $item Field configuration
     */
    private function render_single_meta_field(array $item): void
    {
        if (class_exists('\UM_Elementor_Field_Visibility') && ! \UM_Elementor_Field_Visibility::can_view($item, (int) um_user('ID'))) {
            return;
        }

        $field_key = $item['um_user_meta_field_value'] ?? '';
        $show_label = $item['um_user_meta_field_label'] ?? 1;

        if (empty($field_key)) {
            return;
        }

        if ($this->is_special_field($field_key)) {
            $this->render_special_field($field_key);
            return;
        }

        $this->render_regular_field($field_key, $show_label);
    }

    /**
     * Check if field is a special field type
     * 
     * @param string $field_key Field key to check
     * @return bool True if special field
     */
    private function is_special_field(string $field_key): bool
    {
        return in_array($field_key, self::SPECIAL_FIELDS, true);
    }

    /**
     * Render special field types
     * 
     * @param string $field_key Special field key
     */
    private function render_special_field(string $field_key): void
    {
        switch ($field_key) {
            case self::SPECIAL_FIELDS['USER_AVATAR']:
                $this->render_user_avatar_with_name();
                break;
            case self::SPECIAL_FIELDS['PROFILE_PHOTO']:
                $this->render_user_avatar();
                break;
            case self::SPECIAL_FIELDS['COVER_PHOTO']:
                $this->render_cover_photo();
                break;
        }
    }

    /**
     * Render regular meta field
     * 
     * @param string $field_key Field key
     * @param bool $show_label Whether to show label
     */
    private function render_regular_field(string $field_key, bool $show_label): void
    {
        $user_id = um_user('ID');
        um_fetch_user($user_id);
        $meta_value = um_user($field_key);

        if (empty($meta_value)) {
            return;
        }

        $this->output_meta_field($field_key, $meta_value, $show_label);
    }

    /**
     * Output meta field HTML with wrapper
     * 
     * @param string $field_key Field key
     * @param mixed $meta_value Field value
     * @param bool $show_label Whether to show field label
     */
    private function output_meta_field(string $field_key, $meta_value, bool $show_label): void
    {
        echo '<span class="um-meta-field">';

        if ($show_label) {
            $this->render_field_label_html($field_key);
        }

        echo '<span class="um-custom-field">';
        $this->render_field_value($field_key, $meta_value);
        echo '</span>';
        echo '</span>';
    }

    /**
     * Render field label if enabled
     * 
     * @param array $item Field item
     * @param string $field_key Field key
     */
    private function render_field_label(array $item, string $field_key): void
    {
        if (isset($item['um_user_meta_field_label']) && $item['um_user_meta_field_label']) {
            echo "<span class='um-custom-label'>" . esc_attr(UM()->Fields()->get_label($field_key)) . ":</span> ";
        }
    }

    /**
     * Render field label HTML
     * 
     * @param string $field_key Field key
     */
    private function render_field_label_html(string $field_key): void
    {
        $label = UM()->Fields()->get_label($field_key);
        echo '<span class="um-custom-label">' . esc_attr($label) . ':</span>';
    }

    /**
     * Render field value based on its type
     * 
     * @param string $field_key Field key
     * @param mixed $meta_value Field value
     */
    private function render_field_value(string $field_key, $meta_value): void
    {
        if ($field_key === 'full_name') {
            $first_name = trim((string) um_user('first_name'));
            $last_name = trim((string) um_user('last_name'));
            $full_name = trim($first_name . ' ' . $last_name);
            if ($full_name === '') {
                $full_name = (string) um_user('display_name');
            }
            echo esc_html($full_name);
            return;
        }

        if ($field_key === 'registration_date') {
            $registered = (string) um_user('user_registered');
            if ($registered !== '') {
                echo esc_html(date_i18n(get_option('date_format'), strtotime($registered)));
            }
            return;
        }

        if ($field_key === 'profile_url') {
            echo esc_url(um_user_profile_url());
            return;
        }

        if ($this->is_special_field($field_key)) {
            $this->render_special_field($field_key);
            return;
        }

        $field_type = UM()->Fields()->get_field_type($field_key);
        $this->render_field_by_type($field_key, $meta_value, $field_type);
    }

    /**
     * Render field based on its type
     * 
     * @param string $field_key Field key
     * @param mixed $meta_value Field value
     * @param string $field_type Field type
     */
    private function render_field_by_type(string $field_key, $meta_value, string $field_type): void
    {
        $field_renderers = [
            'url' => 'render_url_field',
            'tel' => 'render_tel_field',
            'image' => 'render_image_field',
            'file' => 'render_file_field',
            'youtube_video' => 'render_youtube_field'
        ];

        if (isset($field_renderers[$field_type])) {
            $method = $field_renderers[$field_type];
            
            if ($field_type === 'image' || $field_type === 'file') {
                $this->$method($field_key);
            } else {
                $this->$method($meta_value);
            }
        } else {
            $this->render_default_field($meta_value);
        }
    }

    /**
     * Render URL field with consistent formatting
     * 
     * @param string $meta_value URL value
     */
    public function render_url_field(string $meta_value): void
    {
        if (empty($meta_value)) {
            return;
        }

        $link_url = esc_url($meta_value);
        $display_url = esc_html($link_url);

        echo wp_kses_post("<a href='{$link_url}' target='_blank' rel='noopener noreferrer'>{$display_url}</a>");
        echo wp_kses_post("<i class='um-faicon-link'></i>");
    }

    /**
     * Render telephone field with consistent formatting
     * 
     * @param string $meta_value Telephone value
     */
    public function render_tel_field(string $meta_value): void
    {
        if (empty($meta_value)) {
            return;
        }

        $link_tel = esc_attr($meta_value);
        $display_tel = esc_html($meta_value);

        echo wp_kses_post("<a href='tel:{$link_tel}'>{$display_tel}</a>");
        echo wp_kses_post("<i class='um-faicon-phone'></i>");
    }

    /**
     * Render image field with consistent formatting
     * 
     * @param string $field_key Field key
     */
    public function render_image_field(string $field_key): void
    {
        $image_filename = um_user($field_key);

        if (empty($image_filename)) {
            return;
        }

        $image_url = $this->get_upload_file_url($image_filename);
        if (empty($image_url)) {
            return;
        }

        echo wp_kses_post("<img src='{$image_url}' alt='" . esc_attr($image_filename) . "' loading='lazy'>");
    }

    /**
     * Render file field with consistent formatting
     * 
     * @param string $field_key Field key
     */
    public function render_file_field(string $field_key): void
    {
        $image_filename = um_user($field_key);

        if (empty($image_filename)) {
            return;
        }

        $image_url = $this->get_upload_file_url($image_filename);
        if (empty($image_url)) {
            return;
        }

        $file_name = $this->get_file_display_name($field_key, $image_filename);

        echo wp_kses_post("<a href='{$image_url}' target='_blank' rel='noopener noreferrer'>{$file_name}</a>");
        echo wp_kses_post("<i class='um-faicon-file-text-o'></i>");
    }

    /**
     * Get display name for file
     * 
     * @param string $field_key Field key
     * @param string $filename Default filename
     * @return string Display name
     */
    private function get_file_display_name(string $field_key, string $filename): string
    {
        $file_info = um_user($field_key . "_metadata");
        $file_name = isset($file_info['original_name']) ? $file_info['original_name'] : $filename;
        
        return esc_html($file_name);
    }

    /**
     * Render YouTube video field with consistent formatting
     * 
     * @param string $meta_value YouTube URL
     */
    public function render_youtube_field(string $meta_value): void
    {
        if (empty($meta_value)) {
            return;
        }

        $yt_url = esc_url($meta_value);
        $code = $this->extract_youtube_code($yt_url);

        if (empty($code)) {
            echo wp_kses_post("<a href='{$yt_url}' target='_blank' rel='noopener noreferrer'>{$yt_url}</a>");
            return;
        }

        $this->render_youtube_iframe($code);
    }

    /**
     * Render YouTube iframe
     * 
     * @param string $code YouTube video code
     */
    private function render_youtube_iframe(string $code): void
    {
        $iframe_attributes = [
            'width' => '560',
            'height' => '315',
            'src' => 'https://www.youtube.com/embed/' . esc_attr($code),
            'title' => 'YouTube video player',
            'frameborder' => '0',
            'allow' => 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture',
            'allowfullscreen' => '',
            'loading' => 'lazy'
        ];

        $iframe_html = '<iframe';
        foreach ($iframe_attributes as $attr => $value) {
            $iframe_html .= " {$attr}=\"{$value}\"";
        }
        $iframe_html .= '></iframe>';
        echo wp_kses_post($iframe_html);
    }

    /**
     * Render default field types with consistent formatting
     * 
     * @param mixed $meta_value Field value
     */
    public function render_default_field($meta_value): void
    {
        if (is_array($meta_value)) {
            $values = array_map('esc_attr', $meta_value);
            echo wp_kses_post(implode(', ', $values));
        } else {
            echo esc_attr($meta_value);
        }
    }

    /**
     * Render user avatar
     */
    public function render_user_avatar(): void
    {
        $user_id = um_user('ID');
        $display_name = um_user('display_name');
        $profile_url = um_user_profile_url();

        echo '<div class="um-elementor-member-image">';
        echo '<a title="' . esc_attr($display_name) . '" href="' . esc_url($profile_url) . '">';
        echo wp_kses_post(um_get_avatar('', $user_id, 100));
        echo '</a>';
        echo '</div>';
    }

    /**
     * Render user avatar with name (for table layouts)
     */
    public function render_user_avatar_with_name(): void
    {
        $user_id = um_user('ID');
        $display_name = um_user('display_name');
        $profile_url = um_user_profile_url();

        echo '<div class="um-table-column-avatar">';
        echo '<a title="' . esc_attr($display_name) . '" href="' . esc_url($profile_url) . '" class="user-avatar-link">';
        echo wp_kses_post(um_get_avatar('', $user_id, 70));
        echo '</a>';
        echo '<a title="' . esc_attr($display_name) . '" href="' . esc_url($profile_url) . '" class="user-avatar-name">';
        echo '<h6 class="user-avatar-name-text">' . esc_html($display_name) . '</h6>';
        echo '</a>';
        echo '</div>';
    }

    /**
     * Render cover photo
     */
    public function render_cover_photo(): void
    {
        $user_id = um_user('ID');
        $cover_url = $this->get_cover_photo_url($user_id);

        if (empty($cover_url)) {
            return;
        }

        $display_name = um_user('display_name');

        echo '<div class="um-elementor-cover-photo">';
        echo '<img src="' . esc_url($cover_url) . '" alt="' . esc_attr($display_name) . ' cover photo" loading="lazy">';
        echo '</div>';
    }

    /**
     * Get cover photo URL
     * 
     * @param int $user_id User ID
     * @return string|null Cover photo URL or null
     */
    private function get_cover_photo_url(int $user_id): ?string
    {
        if (function_exists('um_get_cover_photo_url')) {
            return um_get_cover_photo_url($user_id);
        }

        $cover_photo = get_user_meta($user_id, 'cover_photo', true);
        if (empty($cover_photo)) {
            return null;
        }

        $upload_dir = wp_upload_dir();
        return esc_url($upload_dir['baseurl'] . '/ultimatemember/' . $user_id . '/' . $cover_photo);
    }

    /**
     * Get upload file URL with error handling
     * 
     * @param string $filename File name
     * @return string|null File URL or null on error
     */
    private function get_upload_file_url(string $filename): ?string
    {
        if (empty($filename)) {
            return null;
        }

        $upload_dir = wp_upload_dir();
        if (empty($upload_dir['baseurl'])) {
            return null;
        }

        $user_id = um_user('ID');
        if (empty($user_id)) {
            return null;
        }

        return esc_url($upload_dir['baseurl'] . '/ultimatemember/' . $user_id . '/' . $filename);
    }

    /**
     * Extract YouTube video code from URL
     * 
     * @param string $url YouTube URL
     * @return string|null Video code or null on error
     */
    private function extract_youtube_code(string $url): ?string
    {
        if (empty($url)) {
            return null;
        }

        foreach (self::YOUTUBE_PATTERNS as $pattern) {
            if (preg_match($pattern, $url, $matches)) {
                return $matches[1];
            }
        }

        return null;
    }

    /**
     * Render friends list
     * 
     * @param int $user_id User ID
     */
    private function render_friends(int $user_id): void
    {
        if (!function_exists('um_friends_get_friends')) {
            return;
        }

        $friends = um_friends_get_friends($user_id, 5);
        $this->render_user_list($friends);
    }

    /**
     * Render following list
     * 
     * @param int $user_id User ID
     */
    private function render_following(int $user_id): void
    {
        if (!function_exists('um_followers_get_following')) {
            return;
        }

        $following = um_followers_get_following($user_id, 5);
        $this->render_user_list($following);
    }

    /**
     * Render followers list
     * 
     * @param int $user_id User ID
     */
    private function render_followers(int $user_id): void
    {
        if (!function_exists('um_followers_get_followers')) {
            return;
        }

        $followers = um_followers_get_followers($user_id, 5);
        $this->render_user_list($followers);
    }

    /**
     * Render list of users
     * 
     * @param array $users Array of user IDs
     */
    private function render_user_list(array $users): void
    {
        if (empty($users)) {
            echo '<p>' . esc_html__('No users found.', 'ultimate-member-widgets-for-elementor') . '</p>';
            return;
        }

        echo '<div class="um-followers-list">';
        foreach ($users as $user_id) {
            $this->render_user_list_item($user_id);
        }
        echo '</div>';
    }

    /**
     * Render individual user list item
     * 
     * @param int $user_id User ID
     */
    private function render_user_list_item(int $user_id): void
    {
        $profile_url = um_user_profile_url($user_id);
        $display_name = um_user('display_name', $user_id);

        echo '<div class="um-followers-user">';
        echo '<div class="um-followers-user-photo">';
        echo '<a href="' . esc_url($profile_url) . '">';
        echo wp_kses_post(um_get_avatar('', $user_id, 40));
        echo '</a>';
        echo '</div>';
        echo '<div class="um-followers-user-name">';
        echo '<a href="' . esc_url($profile_url) . '">';
        echo esc_html($display_name);
        echo '</a>';
        echo '</div>';
        echo '</div>';
    }
}
