<?php

/**
 * Schema Markup Module
 *
 * @package ProRank\SEO\Modules\OnPageSEO
 * @since   0.1.0
 */

declare(strict_types=1);

namespace ProRank\SEO\Modules\OnPageSEO;

use ProRank\SEO\Modules\BaseModule;
use ProRank\SEO\Core\Schema\SchemaOutputManager;

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


/**
 * Schema Markup module class
 *
 * Handles basic structured data and rich snippets for FREE tier
 */


class SchemaMarkupModule extends BaseModule {
    /**
     * Module slug
     *
     * @var string
     */
    protected string $slug = 'schema-markup';
    
    /**
     * Module name
     *
     * @var string
     */
    protected string $name = 'Schema Markup';
    
    /**
     * Module description
     *
     * @var string
     */
    protected string $description = 'Basic structured data and rich snippets (Article, Organization, WebSite)';
    
    /**
     * Required tier
     *
     * @var string
     */
    protected string $feature_tier = 'free';
    
    /**
     * Parent module
     *
     * @var string|null
     */
    protected ?string $parent_slug = 'on-page-seo';
    
    /**
     * Initialize module hooks
     *
     * @return void
     */
    public function init_hooks(): void {
        // Settings should be available even if module is toggled off.
        add_action('rest_api_init', [$this, 'register_rest_routes']);

        if (!$this->is_enabled()) {
            return;
        }

        // 2025 Enhancement: Register schemas with centralized output manager
        SchemaOutputManager::instance();
        add_action('prorank_seo_register_schemas', [$this, 'register_basic_schemas'], 5);
    }
    
    /**
     * Register REST routes for settings
     *
     * @return void
     */
    public function register_rest_routes(): void {
        register_rest_route('prorank-seo/v1', '/settings/basic-schema', [
            'methods' => 'GET',
            'callback' => [$this, 'get_settings'],
            'permission_callback' => function() {
                return current_user_can('manage_options');
            }
        ]);
        
        register_rest_route('prorank-seo/v1', '/settings/basic-schema', [
            'methods' => 'POST',
            'callback' => [$this, 'update_settings'],
            'permission_callback' => function() {
                return current_user_can('manage_options');
            }
        ]);
    }
    
    /**
     * Get settings
     *
     * @return array
     */
    public function get_settings(): array {
        $stored = get_option('prorank_basic_schema_settings', []);
        if (!is_array($stored)) {
            $stored = [];
        }

        return wp_parse_args($stored, $this->get_default_settings());
    }
    
    /**
     * Update settings
     *
     * @param \WP_REST_Request $request Request object
     * @return array
     */
    public function update_settings(\WP_REST_Request $request): array {
        $settings = $request->get_json_params();
        if (!is_array($settings)) {
            $settings = [];
        }

        $defaults = $this->get_default_settings();
        $sanitized = [
            'enable_website_schema' => isset($settings['enable_website_schema']) ? (bool) $settings['enable_website_schema'] : $defaults['enable_website_schema'],
            'enable_organization_schema' => isset($settings['enable_organization_schema']) ? (bool) $settings['enable_organization_schema'] : $defaults['enable_organization_schema'],
            'enable_article_schema' => isset($settings['enable_article_schema']) ? (bool) $settings['enable_article_schema'] : $defaults['enable_article_schema'],
            'enable_breadcrumb_schema' => isset($settings['enable_breadcrumb_schema']) ? (bool) $settings['enable_breadcrumb_schema'] : $defaults['enable_breadcrumb_schema'],
            'organization_name' => isset($settings['organization_name']) ? sanitize_text_field($settings['organization_name']) : $defaults['organization_name'],
            'organization_logo' => isset($settings['organization_logo']) ? esc_url_raw($settings['organization_logo']) : $defaults['organization_logo'],
            'organization_type' => isset($settings['organization_type']) ? sanitize_text_field($settings['organization_type']) : $defaults['organization_type'],
        ];

        update_option('prorank_basic_schema_settings', $sanitized);
        return $sanitized;
    }
    
    /**
     * Get default settings
     *
     * @return array
     */
    private function get_default_settings(): array {
        $site_basics = get_option('prorank_seo_site_basics', []);
        if (!is_array($site_basics)) {
            $site_basics = [];
        }

        $site_name = get_bloginfo('name');
        $org_name = !empty($site_basics['org_name']) ? $site_basics['org_name'] : $site_name;
        $org_logo = !empty($site_basics['org_logo']) ? $site_basics['org_logo'] : '';
        $is_person = ($site_basics['org_or_person'] ?? 'organization') === 'person';
        $is_local_business = !$is_person && !empty($site_basics['org_local_business_enabled']);
        $schema_type = $is_person ? 'Person' : ($is_local_business ? 'LocalBusiness' : 'Organization');

        return [
            'enable_website_schema' => true,
            'enable_organization_schema' => true,
            'enable_article_schema' => true,
            'enable_breadcrumb_schema' => true,
            'organization_name' => $org_name,
            'organization_logo' => $org_logo,
            'organization_type' => $schema_type,
        ];
    }
    
    /**
     * Register basic schemas with output manager
     *
     * 2025 Enhancement: Uses SchemaOutputManager for consolidated output
     *
     * @param \ProRank\SEO\Core\Schema\SchemaOutputManager $manager Schema output manager
     * @return void
     */
    public function register_basic_schemas($manager): void {
        $settings = $this->get_settings();

        // Website Schema
        if ($settings['enable_website_schema']) {
            $schema = $this->get_website_schema();
            if ($schema) {
                $manager->register_schema($schema, 5, 'SchemaMarkupModule::WebSite');
            }
        }

        // Organization Schema
        if ($settings['enable_organization_schema'] && is_front_page()) {
            $schema = $this->get_organization_schema($settings);
            if ($schema) {
                $manager->register_schema($schema, 5, 'SchemaMarkupModule::Organization');
            }
        }

        // Article Schema for posts
        if ($settings['enable_article_schema'] && is_singular('post')) {
            $schema = $this->get_article_schema();
            if ($schema) {
                $manager->register_schema($schema, 5, 'SchemaMarkupModule::Article');
            }
        }

        // Breadcrumb Schema
        if ($settings['enable_breadcrumb_schema'] && !is_front_page()) {
            $schema = $this->get_breadcrumb_schema();
            if ($schema) {
                $manager->register_schema($schema, 5, 'SchemaMarkupModule::BreadcrumbList');
            }
        }
    }
    
    /**
     * Get the current page language, accounting for multilingual plugins
     *
     * @return string Language code (e.g., 'en-US', 'de-DE')
     */
    private function get_page_language(): string {
        // Check for WPML
        if (defined('ICL_LANGUAGE_CODE') && ICL_LANGUAGE_CODE) {
            global $sitepress;
            if ($sitepress && method_exists($sitepress, 'get_locale')) {
                return str_replace('_', '-', $sitepress->get_locale(ICL_LANGUAGE_CODE));
            }
            return ICL_LANGUAGE_CODE;
        }

        // Check for Polylang
        if (function_exists('pll_current_language')) {
            $locale = pll_current_language('locale');
            if ($locale) {
                return str_replace('_', '-', $locale);
            }
        }

        // Check for TranslatePress
        global $TRP_LANGUAGE;
        if (!empty($TRP_LANGUAGE)) {
            return str_replace('_', '-', $TRP_LANGUAGE);
        }

        // Fallback to WordPress locale
        return str_replace('_', '-', get_locale());
    }

    /**
     * Get website schema
     *
     * @return array
     */
    private function get_website_schema(): array {
        $schema = [
            '@type' => 'WebSite',
            '@id' => home_url('/#website'),
            'url' => home_url('/'),
            'name' => get_bloginfo('name'),
            'description' => get_bloginfo('description'),
            'inLanguage' => $this->get_page_language(),
        ];
        
        // Add search action
        $schema['potentialAction'] = [
            '@type' => 'SearchAction',
            'target' => [
                '@type' => 'EntryPoint',
                'urlTemplate' => home_url('/?s={search_term_string}')
            ],
            'query-input' => 'required name=search_term_string'
        ];
        
        return $schema;
    }
    
    /**
     * Get organization schema
     *
     * @param array $settings Module settings
     * @return array
     */
    private function get_organization_schema(array $settings): array {
        $site_basics = get_option('prorank_seo_site_basics', []);
        $stored_schema_settings = get_option('prorank_basic_schema_settings', []);
        if (!is_array($stored_schema_settings)) {
            $stored_schema_settings = [];
        }

        $has_schema_type_override = isset($stored_schema_settings['organization_type']) && $stored_schema_settings['organization_type'] !== '';
        $has_schema_name_override = isset($stored_schema_settings['organization_name']) && $stored_schema_settings['organization_name'] !== '';
        $has_schema_logo_override = isset($stored_schema_settings['organization_logo']) && $stored_schema_settings['organization_logo'] !== '';
        $schema_type_override = $has_schema_type_override ? sanitize_text_field((string) $stored_schema_settings['organization_type']) : '';
        $schema_name_override = $has_schema_name_override ? sanitize_text_field((string) $stored_schema_settings['organization_name']) : '';
        $schema_logo_override = $has_schema_logo_override ? esc_url_raw((string) $stored_schema_settings['organization_logo']) : '';

        $is_person = ($site_basics['org_or_person'] ?? 'organization') === 'person';
        $is_local_business = !$is_person && !empty($site_basics['org_local_business_enabled']);
        $fallback_name = !empty($site_basics['org_name'])
            ? $site_basics['org_name']
            : get_bloginfo('name');
        $fallback_logo = !empty($site_basics['org_logo']) ? $site_basics['org_logo'] : '';
        $selected_user = null;

        if ($is_person && !empty($site_basics['person_user_id'])) {
            $selected_user = get_user_by('id', (int) $site_basics['person_user_id']);
        }

        $schema_type = $is_person
            ? 'Person'
            : ($is_local_business ? 'LocalBusiness' : (!empty($schema_type_override) ? $schema_type_override : 'Organization'));
        $schema_name = !empty($schema_name_override)
            ? $schema_name_override
            : $fallback_name;

        if ($selected_user && !empty($selected_user->display_name)) {
            $schema_name = $selected_user->display_name;
        }

        $schema = [
            '@type' => $schema_type,
            '@id' => home_url($is_person ? '/#person' : '/#organization'),
            'name' => $schema_name,
            'url' => home_url('/'),
        ];

        // Alternate name
        if (!empty($site_basics['org_alternate_name'])) {
            $schema['alternateName'] = $site_basics['org_alternate_name'];
        } elseif (!empty($site_basics['site_alternate_name'])) {
            $schema['alternateName'] = $site_basics['site_alternate_name'];
        }

        // Description
        if (!empty($site_basics['org_description'])) {
            $schema['description'] = $site_basics['org_description'];
        } elseif (!empty($site_basics['site_tagline'])) {
            $schema['description'] = $site_basics['site_tagline'];
        }

        // Add logo if available
        $logo_value = !empty($schema_logo_override)
            ? $schema_logo_override
            : $fallback_logo;
        if ($is_person) {
            $image_value = '';

            if (!empty($site_basics['person_logo'])) {
                $image_value = $site_basics['person_logo'];
            } elseif (!empty($site_basics['person_logo_id'])) {
                $image_value = (string) wp_get_attachment_url((int) $site_basics['person_logo_id']);
            } elseif ($selected_user) {
                $image_value = (string) get_avatar_url($selected_user->ID);
            } elseif (!empty($logo_value)) {
                $image_value = $logo_value;
            }

            if (!empty($image_value)) {
                $schema['image'] = $image_value;
            }
        } elseif (!empty($logo_value)) {
            $schema['logo'] = [
                '@type' => 'ImageObject',
                'url' => $logo_value
            ];
        } elseif (has_custom_logo()) {
            $logo_id = get_theme_mod('custom_logo');
            $logo_url = wp_get_attachment_image_url($logo_id, 'full');
            if ($logo_url) {
                $schema['logo'] = [
                    '@type' => 'ImageObject',
                    'url' => $logo_url
                ];
            }
        }

        // Contact info
        if ($is_person) {
            if (!empty($site_basics['org_email'])) {
                $schema['email'] = $site_basics['org_email'];
            }
            if (!empty($site_basics['org_phone'])) {
                $schema['telephone'] = $site_basics['org_phone'];
            }
        } elseif (!empty($site_basics['org_email']) || !empty($site_basics['org_phone'])) {
            $contactPoint = [
                '@type' => 'ContactPoint',
                'contactType' => 'customer service',
            ];
            if (!empty($site_basics['org_email'])) {
                $contactPoint['email'] = $site_basics['org_email'];
            }
            if (!empty($site_basics['org_phone'])) {
                $contactPoint['telephone'] = $site_basics['org_phone'];
            }
            $schema['contactPoint'] = $contactPoint;
        }

        // Address
        if (!empty($site_basics['org_street_address']) ||
            !empty($site_basics['org_address_locality']) ||
            !empty($site_basics['org_address_region']) ||
            !empty($site_basics['org_postal_code']) ||
            !empty($site_basics['org_address_country'])) {

            $address = ['@type' => 'PostalAddress'];
            if (!empty($site_basics['org_street_address'])) {
                $address['streetAddress'] = $site_basics['org_street_address'];
            }
            if (!empty($site_basics['org_address_locality'])) {
                $address['addressLocality'] = $site_basics['org_address_locality'];
            }
            if (!empty($site_basics['org_address_region'])) {
                $address['addressRegion'] = $site_basics['org_address_region'];
            }
            if (!empty($site_basics['org_postal_code'])) {
                $address['postalCode'] = $site_basics['org_postal_code'];
            }
            if (!empty($site_basics['org_address_country'])) {
                $address['addressCountry'] = $site_basics['org_address_country'];
            }
            $schema['address'] = $address;
        }

        // Social profiles (sameAs) — read from site_basics option
        $social_profiles = [];
        if ($is_person && !empty($site_basics['facebook_authorship'])) {
            $social_profiles[] = $site_basics['facebook_authorship'];
        } elseif (!empty($site_basics['facebook_page_url'])) {
            $social_profiles[] = $site_basics['facebook_page_url'];
        }
        if (!empty($site_basics['twitter_username'])) {
            $social_profiles[] = 'https://twitter.com/' . ltrim($site_basics['twitter_username'], '@');
        }
        if (!empty($site_basics['linkedin_url'])) {
            $social_profiles[] = $site_basics['linkedin_url'];
        }
        if (!empty($site_basics['instagram_url'])) {
            $social_profiles[] = $site_basics['instagram_url'];
        }
        if (!empty($site_basics['youtube_url'])) {
            $social_profiles[] = $site_basics['youtube_url'];
        }
        if (!empty($site_basics['pinterest_url'])) {
            $social_profiles[] = $site_basics['pinterest_url'];
        }
        if (!empty($site_basics['tiktok_url'])) {
            $social_profiles[] = $site_basics['tiktok_url'];
        }
        if (!empty($site_basics['threads_url'])) {
            $social_profiles[] = $site_basics['threads_url'];
        }
        if (!empty($site_basics['mastodon_url'])) {
            $social_profiles[] = $site_basics['mastodon_url'];
        }
        // Additional profiles
        if (!empty($site_basics['additional_profiles']) && is_array($site_basics['additional_profiles'])) {
            foreach ($site_basics['additional_profiles'] as $profile) {
                if (!empty($profile['url'])) {
                    $social_profiles[] = $profile['url'];
                }
            }
        }
        if (!empty($social_profiles)) {
            $schema['sameAs'] = $social_profiles;
        }

        if (!$is_person) {
            if (!empty($site_basics['org_founding_date'])) {
                $schema['foundingDate'] = $site_basics['org_founding_date'];
            }
            if (!empty($site_basics['org_legal_name'])) {
                $schema['legalName'] = $site_basics['org_legal_name'];
            }
            if (!empty($site_basics['org_num_employees'])) {
                $schema['numberOfEmployees'] = [
                    '@type' => 'QuantitativeValue',
                    'value' => $site_basics['org_num_employees'],
                ];
            }

            if (!empty($site_basics['org_vat_id'])) {
                $schema['vatID'] = $site_basics['org_vat_id'];
            }
            if (!empty($site_basics['org_tax_id'])) {
                $schema['taxID'] = $site_basics['org_tax_id'];
            }
            if (!empty($site_basics['org_iso_6523'])) {
                $schema['iso6523Code'] = $site_basics['org_iso_6523'];
            }
            if (!empty($site_basics['org_duns'])) {
                $schema['duns'] = $site_basics['org_duns'];
            }
            if (!empty($site_basics['org_lei_code'])) {
                $schema['leiCode'] = $site_basics['org_lei_code'];
            }
            if (!empty($site_basics['org_naics'])) {
                $schema['naics'] = $site_basics['org_naics'];
            }
        }

        // Policy pages
        if (!empty($site_basics['publishing_principles_page'])) {
            $schema['publishingPrinciples'] = get_permalink($site_basics['publishing_principles_page']);
        }
        if (!empty($site_basics['ownership_funding_page'])) {
            $schema['ownershipFundingInfo'] = get_permalink($site_basics['ownership_funding_page']);
        }
        if (!empty($site_basics['actionable_feedback_page'])) {
            $schema['actionableFeedbackPolicy'] = get_permalink($site_basics['actionable_feedback_page']);
        }
        if (!empty($site_basics['corrections_policy_page'])) {
            $schema['correctionsPolicy'] = get_permalink($site_basics['corrections_policy_page']);
        }
        if (!empty($site_basics['ethics_policy_page'])) {
            $schema['ethicsPolicy'] = get_permalink($site_basics['ethics_policy_page']);
        }
        if (!empty($site_basics['diversity_policy_page'])) {
            $schema['diversityPolicy'] = get_permalink($site_basics['diversity_policy_page']);
        }
        if (!empty($site_basics['diversity_staffing_page'])) {
            $schema['diversityStaffingReport'] = get_permalink($site_basics['diversity_staffing_page']);
        }
        if (!$is_person && !empty($site_basics['privacy_policy_page'])) {
            $schema['privacyPolicy'] = get_permalink($site_basics['privacy_policy_page']);
        }
        if (!$is_person && !empty($site_basics['terms_of_service_page'])) {
            $schema['termsOfService'] = get_permalink($site_basics['terms_of_service_page']);
        }

        return $schema;
    }
    
    /**
     * Get article schema
     *
     * @return array
     */
    private function get_article_schema(): array {
        global $post;

        $author_id = isset($post->post_author) ? (int) $post->post_author : 0;
        $author_name = $this->resolve_article_author_name($author_id);
        
        $schema = [
            '@type' => 'Article',
            '@id' => get_permalink() . '#article',
            'headline' => get_the_title(),
            'datePublished' => get_the_date('c'),
            'dateModified' => get_the_modified_date('c'),
            'mainEntityOfPage' => [
                '@type' => 'WebPage',
                '@id' => get_permalink()
            ],
            'author' => [
                '@type' => 'Person',
                'name' => $author_name,
            ],
            'publisher' => [
                '@type' => 'Organization',
                'name' => get_bloginfo('name'),
                '@id' => home_url('/#organization')
            ]
        ];

        if ($author_id > 0) {
            $schema['author']['url'] = get_author_posts_url($author_id);
        }
        
        // Add description
        if (has_excerpt()) {
            $schema['description'] = get_the_excerpt();
        }
        
        // Add featured image
        if (has_post_thumbnail()) {
            $image_id = get_post_thumbnail_id();
            $image_url = wp_get_attachment_image_url($image_id, 'full');
            $image_meta = wp_get_attachment_metadata($image_id);
            
            if ($image_url) {
                $schema['image'] = [
                    '@type' => 'ImageObject',
                    'url' => $image_url,
                    'width' => $image_meta['width'] ?? '',
                    'height' => $image_meta['height'] ?? ''
                ];
            }
        }
        
        // Add word count
        $content = get_post_field('post_content', $post->ID);
        $word_count = str_word_count(wp_strip_all_tags($content));
        $schema['wordCount'] = $word_count;
        
        // Add article section (categories)
        $categories = get_the_category();
        if (!empty($categories)) {
            $schema['articleSection'] = $categories[0]->name;
        }
        
        // Add keywords (tags)
        $tags = get_the_tags();
        if ($tags) {
            $schema['keywords'] = implode(', ', wp_list_pluck($tags, 'name'));
        }
        
        return $schema;
    }

    /**
     * Resolve a non-empty author name for Article schema.
     *
     * @param int $author_id Author ID.
     * @return string
     */
    private function resolve_article_author_name(int $author_id): string {
        if ($author_id > 0) {
            $author = get_userdata($author_id);
            if ($author) {
                $candidates = [
                    (string) ($author->display_name ?? ''),
                    (string) ($author->nickname ?? ''),
                    (string) ($author->user_nicename ?? ''),
                    (string) ($author->user_login ?? ''),
                ];

                $first_name = (string) get_user_meta($author_id, 'first_name', true);
                $last_name = (string) get_user_meta($author_id, 'last_name', true);
                $full_name = trim($first_name . ' ' . $last_name);
                if ($full_name !== '') {
                    $candidates[] = $full_name;
                }

                foreach ($candidates as $candidate) {
                    $clean = trim(wp_strip_all_tags((string) $candidate));
                    if ($clean !== '') {
                        return $clean;
                    }
                }
            }
        }

        $site_name = trim(wp_strip_all_tags((string) get_bloginfo('name')));
        return $site_name !== '' ? $site_name : 'Editorial Team';
    }
    
    /**
     * Get breadcrumb schema
     *
     * @return array|null
     */
    private function get_breadcrumb_schema(): ?array {
        // Don't show on homepage
        if (is_front_page()) {
            return null;
        }
        
        $items = [];
        $position = 1;
        
        // Home
        $items[] = [
            '@type' => 'ListItem',
            'position' => $position++,
            'name' => 'Home',
            'item' => home_url('/')
        ];
        
        // Category/Archive pages
        if (is_category() || is_tag() || is_tax()) {
            $term = get_queried_object();
            $items[] = [
                '@type' => 'ListItem',
                'position' => $position++,
                'name' => $term->name,
                'item' => get_term_link($term)
            ];
        }
        
        // Single post/page
        if (is_singular()) {
            // Add categories for posts
            if (is_single() && !is_singular('page')) {
                // WooCommerce products use product_cat taxonomy
                if (is_singular('product') && function_exists('wc_get_product')) {
                    $product_cats = get_the_terms(get_the_ID(), 'product_cat');
                    if (!empty($product_cats) && !is_wp_error($product_cats)) {
                        $items[] = [
                            '@type' => 'ListItem',
                            'position' => $position++,
                            'name' => $product_cats[0]->name,
                            'item' => get_term_link($product_cats[0])
                        ];
                    }
                } else {
                    $categories = get_the_category();
                    if (!empty($categories)) {
                        $items[] = [
                            '@type' => 'ListItem',
                            'position' => $position++,
                            'name' => $categories[0]->name,
                            'item' => get_category_link($categories[0])
                        ];
                    }
                }
            }
            
            // Add current page/post
            $items[] = [
                '@type' => 'ListItem',
                'position' => $position++,
                'name' => get_the_title(),
                'item' => get_permalink()
            ];
        }
        
        if (empty($items)) {
            return null;
        }
        
        return [
            '@type' => 'BreadcrumbList',
            '@id' => get_permalink() . '#breadcrumb',
            'itemListElement' => $items
        ];
    }
}
