<?php

namespace WPSN\Modules\AuthorSEO;

use WPSN\Core\AbstractModule;
use WPSN\Domain\SeoDocumentContext;
use WPSN\SEO\UserMetaKeys;

defined('ABSPATH') || exit;

/**
 * Author SEO (E-E-A-T):
 * - Adds author profile fields (image, job title, sameAs)
 * - Exposes variables for TemplateEngine (%author_name%, etc.)
 * - Person schema enrichment is handled by SchemaGraphBuilder when this module is enabled.
 */
final class AuthorSEOModule extends AbstractModule
{
    public function id(): string
    {
        return 'author_seo';
    }

    public function name(): string
    {
        return __('Author SEO', 'wp-seo-next');
    }

    public function description(): string
    {
        return __('Author profile fields + Person schema enrichment (E‑E‑A‑T).', 'wp-seo-next');
    }

    public function defaultEnabled(): bool
    {
        return true;
    }

    public function register(): void
    {
        // Register user meta keys so they can be stored consistently and (optionally) exposed in REST.
        add_action('init', [$this, 'registerUserMeta'], 1);

        // Template variables (%author_name%, %author_job_title%, etc.).
        add_filter('wpsn/template_variables', [$this, 'addTemplateVariables'], 20, 2);

        if (is_admin()) {
            add_action('show_user_profile', [$this, 'renderUserProfileFields']);
            add_action('edit_user_profile', [$this, 'renderUserProfileFields']);

            add_action('personal_options_update', [$this, 'saveUserProfileFields']);
            add_action('edit_user_profile_update', [$this, 'saveUserProfileFields']);

            add_action('admin_enqueue_scripts', [$this, 'enqueueAssets']);
        }
    }

    public function enqueueAssets(string $hook): void
    {
        // User profile screens.
        if (!in_array($hook, ['profile.php', 'user-edit.php'], true)) {
            return;
        }

        // Media picker for author image.
        if (function_exists('wp_enqueue_media')) {
            wp_enqueue_media();
        }

        // Reuse our generic media-picker helper (URL-based field).
        wp_enqueue_script(
            'wpsn-media-picker',
            WPSN_PLUGIN_URL . 'assets/admin/media-picker.js',
            ['jquery'],
            WPSN_VERSION,
            true
        );
    }

    public function registerUserMeta(): void
    {
        // Author image URL.
        register_meta('user', UserMetaKeys::AUTHOR_IMAGE_URL, [
            'type' => 'string',
            'single' => true,
            'show_in_rest' => true,
            'sanitize_callback' => 'esc_url_raw',
            'auth_callback' => static function (): bool {
                return current_user_can('edit_users');
            },
        ]);

        // Author job title.
        register_meta('user', UserMetaKeys::AUTHOR_JOB_TITLE, [
            'type' => 'string',
            'single' => true,
            'show_in_rest' => true,
            'sanitize_callback' => 'sanitize_text_field',
            'auth_callback' => static function (): bool {
                return current_user_can('edit_users');
            },
        ]);

        // sameAs list (newline-separated URLs).
        register_meta('user', UserMetaKeys::AUTHOR_SAME_AS, [
            'type' => 'string',
            'single' => true,
            'show_in_rest' => true,
            'sanitize_callback' => static function ($v): string {
                return is_string($v) ? trim($v) : '';
            },
            'auth_callback' => static function (): bool {
                return current_user_can('edit_users');
            },
        ]);

        // Per-user schema toggle.
        register_meta('user', UserMetaKeys::AUTHOR_SCHEMA_ENABLED, [
            'type' => 'string',
            'single' => true,
            'show_in_rest' => true,
            'sanitize_callback' => static function ($v): string {
                $v = is_string($v) ? $v : '';
                return $v === '0' ? '0' : '1';
            },
            'auth_callback' => static function (): bool {
                return current_user_can('edit_users');
            },
        ]);
    }

    public function renderUserProfileFields(\WP_User $user): void
    {
        if (!$user instanceof \WP_User) {
            return;
        }

        if (!current_user_can('edit_user', (int) $user->ID)) {
            return;
        }

        $imageUrl = (string) get_user_meta((int) $user->ID, UserMetaKeys::AUTHOR_IMAGE_URL, true);
        $jobTitle = (string) get_user_meta((int) $user->ID, UserMetaKeys::AUTHOR_JOB_TITLE, true);
        $sameAs   = (string) get_user_meta((int) $user->ID, UserMetaKeys::AUTHOR_SAME_AS, true);
        $schemaEnabledRaw = (string) get_user_meta((int) $user->ID, UserMetaKeys::AUTHOR_SCHEMA_ENABLED, true);
        $schemaEnabled = $schemaEnabledRaw === '' ? true : ($schemaEnabledRaw !== '0');

        echo '<h2>' . esc_html__('WP SEO Next — Author SEO', 'wp-seo-next') . '</h2>';
        echo '<p class="description">' . esc_html__('Optional author profile fields used for Person schema and template variables (E‑E‑A‑T).', 'wp-seo-next') . '</p>';

        wp_nonce_field('wpsn_save_author_seo', 'wpsn_author_nonce');

        echo '<table class="form-table" role="presentation">';

        // Author image.
        echo '<tr>';
        echo '<th><label for="wpsn_author_image_url">' . esc_html__('Author image', 'wp-seo-next') . '</label></th>';
        echo '<td>';
        echo '<div class="wpsn-media-field">';
        echo '<input id="wpsn_author_image_url" type="url" class="regular-text wpsn-media-url" name="wpsn_author[image_url]" value="' . esc_attr($imageUrl) . '" placeholder="https://..." /> ';
        echo '<button class="button wpsn-media-select" data-title="' . esc_attr__('Select author image', 'wp-seo-next') . '" data-button="' . esc_attr__('Use this image', 'wp-seo-next') . '">' . esc_html__('Select', 'wp-seo-next') . '</button> ';
        echo '<button class="button wpsn-media-clear">' . esc_html__('Clear', 'wp-seo-next') . '</button>';
        $preview = $imageUrl !== '' ? $imageUrl : '';
        echo '<div style="margin-top:10px;">';
        echo '<img class="wpsn-media-preview" src="' . esc_url($preview) . '" alt="" style="max-width:120px;height:auto;' . ($preview !== '' ? '' : 'display:none;') . '" />';
        echo '</div>';
        echo '</div>';
        echo '<p class="description">' . esc_html__('Used as Person.image and can be used as a social fallback on author pages.', 'wp-seo-next') . '</p>';
        echo '</td>';
        echo '</tr>';

        // Job title.
        echo '<tr>';
        echo '<th><label for="wpsn_author_job_title">' . esc_html__('Job title', 'wp-seo-next') . '</label></th>';
        echo '<td>';
        echo '<input id="wpsn_author_job_title" type="text" class="regular-text" name="wpsn_author[job_title]" value="' . esc_attr($jobTitle) . '" />';
        echo '<p class="description">' . esc_html__('Optional. Output as Person.jobTitle in JSON‑LD.', 'wp-seo-next') . '</p>';
        echo '</td>';
        echo '</tr>';

        // sameAs.
        echo '<tr>';
        echo '<th><label for="wpsn_author_same_as">' . esc_html__('SameAs URLs', 'wp-seo-next') . '</label></th>';
        echo '<td>';
        echo '<textarea id="wpsn_author_same_as" class="large-text" rows="5" name="wpsn_author[same_as]" placeholder="https://twitter.com/...\nhttps://www.linkedin.com/in/...">' . esc_textarea($sameAs) . '</textarea>';
        echo '<p class="description">' . esc_html__('One URL per line. Used as Person.sameAs (social profiles, Wikipedia, etc.).', 'wp-seo-next') . '</p>';
        echo '</td>';
        echo '</tr>';

        // Schema enabled.
        echo '<tr>';
        echo '<th>' . esc_html__('Person schema', 'wp-seo-next') . '</th>';
        echo '<td>';
        echo '<label>';
        echo '<input type="checkbox" name="wpsn_author[schema_enabled]" value="1" ' . checked($schemaEnabled, true, false) . ' /> ';
        echo esc_html__('Enable Person schema for this author', 'wp-seo-next');
        echo '</label>';
        echo '<p class="description">' . esc_html__('If unchecked, we will not output a Person node for this author (posts and author archive pages).', 'wp-seo-next') . '</p>';
        echo '</td>';
        echo '</tr>';

        echo '</table>';
    }

    public function saveUserProfileFields(int $userId): void
    {
        if ($userId <= 0) {
            return;
        }

        if (!current_user_can('edit_user', $userId)) {
            return;
        }

        if (!isset($_POST['wpsn_author_nonce']) || !wp_verify_nonce((string) wp_unslash($_POST['wpsn_author_nonce']), 'wpsn_save_author_seo')) {
            return;
        }

        $incoming = $_POST['wpsn_author'] ?? [];
        $incoming = is_array($incoming) ? wp_unslash($incoming) : [];

        $imageUrl = isset($incoming['image_url']) ? esc_url_raw((string) $incoming['image_url']) : '';
        $jobTitle = isset($incoming['job_title']) ? sanitize_text_field((string) $incoming['job_title']) : '';

        $sameAs = isset($incoming['same_as']) ? (string) $incoming['same_as'] : '';
        $sameAs = is_string($sameAs) ? trim((string) $sameAs) : '';

        $schemaEnabled = !empty($incoming['schema_enabled']);

        if ($imageUrl !== '') {
            update_user_meta($userId, UserMetaKeys::AUTHOR_IMAGE_URL, $imageUrl);
        } else {
            delete_user_meta($userId, UserMetaKeys::AUTHOR_IMAGE_URL);
        }

        if ($jobTitle !== '') {
            update_user_meta($userId, UserMetaKeys::AUTHOR_JOB_TITLE, $jobTitle);
        } else {
            delete_user_meta($userId, UserMetaKeys::AUTHOR_JOB_TITLE);
        }

        if ($sameAs !== '') {
            update_user_meta($userId, UserMetaKeys::AUTHOR_SAME_AS, $sameAs);
        } else {
            delete_user_meta($userId, UserMetaKeys::AUTHOR_SAME_AS);
        }

        // Save explicit toggle only when it differs from default (enabled).
        if ($schemaEnabled) {
            delete_user_meta($userId, UserMetaKeys::AUTHOR_SCHEMA_ENABLED);
        } else {
            update_user_meta($userId, UserMetaKeys::AUTHOR_SCHEMA_ENABLED, '0');
        }
    }

    /**
     * Add author variables to TemplateEngine.
     *
     * Available:
     * - %author_name%
     * - %author_first_name%
     * - %author_last_name%
     * - %author_bio%
     * - %author_job_title%
     *
     * @param array<string,string> $vars
     * @return array<string,string>
     */
    public function addTemplateVariables(array $vars, SeoDocumentContext $ctx): array
    {
        $authorId = 0;

        if ($ctx->isSingular() && $ctx->objectId !== null) {
            $post = get_post((int) $ctx->objectId);
            if ($post instanceof \WP_Post) {
                $authorId = (int) $post->post_author;
            }
        } elseif ($ctx->type === SeoDocumentContext::TYPE_ARCHIVE && $ctx->objectSubType === 'author' && $ctx->objectId !== null) {
            $authorId = (int) $ctx->objectId;
        }

        if ($authorId <= 0) {
            return $vars;
        }

        $dn = get_the_author_meta('display_name', $authorId);
        $fn = get_the_author_meta('first_name', $authorId);
        $ln = get_the_author_meta('last_name', $authorId);
        $bio = get_the_author_meta('description', $authorId);

        $vars['author_name'] = is_string($dn) ? trim($dn) : '';
        $vars['author_first_name'] = is_string($fn) ? trim($fn) : '';
        $vars['author_last_name'] = is_string($ln) ? trim($ln) : '';
        $vars['author_bio'] = is_string($bio) ? trim(wp_strip_all_tags($bio)) : '';

        $job = (string) get_user_meta($authorId, UserMetaKeys::AUTHOR_JOB_TITLE, true);
        $vars['author_job_title'] = trim($job);

        return $vars;
    }
}
