<?php

/**
 * Site Basics Module
 *
 * @package ProRank\SEO\Modules\OnPageSEO
 * @since   1.0.0
 */

declare(strict_types=1);

namespace ProRank\SEO\Modules\OnPageSEO;

use ProRank\SEO\Modules\BaseModule;
use WP_REST_Server;
use WP_REST_Request;
use WP_REST_Response;
use WP_Error;

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


/**
 * Site Basics module class
 *
 * Manages fundamental site configuration including site info, verification, social profiles, and organization details
 */


class SiteBasicsModule extends BaseModule {
    /**
     * Module slug
     *
     * @var string
     */
    protected string $slug = 'site-basics';

    /**
     * Module name
     *
     * @var string
     */
    protected string $name = 'Site Basics';

    /**
     * Module description
     *
     * @var string
     */
    protected string $description = 'Fundamental site configuration and information';

    /**
     * Required tier
     *
     * @var string
     */
    protected string $feature_tier = 'free';

    /**
     * Parent module
     *
     * @var string|null
     */
    protected ?string $parent_slug = 'on-page-seo';

    /**
     * Default settings
     *
     * @var array
     */
    private array $default_settings = [
        // Site Information
        'site_name' => '',
        'site_alternate_name' => '',
        'site_tagline' => '',
        'title_separator' => '-',
        'site_logo' => '',
        'site_logo_id' => '',
        'site_image' => '',
        'site_image_id' => '',

        // Site Verification
        'google_verification' => '',
        'bing_verification' => '',
        'baidu_verification' => '',
        'yandex_verification' => '',
        'pinterest_verification' => '',
        'norton_verification' => '',
        'custom_meta_tags' => '',

        // Social Profiles
        'facebook_page_url' => '',
        'facebook_authorship' => '',
        'facebook_admin_id' => '',
        'facebook_app_id' => '',
        'facebook_secret' => '',
        'twitter_username' => '',
        'linkedin_url' => '',
        'instagram_url' => '',
        'youtube_url' => '',
        'pinterest_url' => '',
        'tiktok_url' => '',
        'threads_url' => '',
        'mastodon_url' => '',
        'github_url' => '',
        'additional_profiles' => [],

        // Organization Info
        'org_or_person' => 'organization',
        'org_name' => '',
        'org_alternate_name' => '',
        'org_logo' => '',
        'org_logo_id' => '',
        'person_logo' => '',
        'person_logo_id' => '',
        'person_user_id' => '',
        'org_description' => '',
        'org_email' => '',
        'org_phone' => '',
        'org_local_business_enabled' => false,
        'org_legal_name' => '',
        'org_founding_date' => '',
        'org_num_employees' => '',
        'org_vat_id' => '',
        'org_tax_id' => '',
        'org_iso_6523' => '',
        'org_duns' => '',
        'org_lei_code' => '',
        'org_naics' => '',
        'org_street_address' => '',
        'org_address_locality' => '',
        'org_address_region' => '',
        'org_postal_code' => '',
        'org_address_country' => '',

        // Site Policies
        'publishing_principles_page' => '',
        'ownership_funding_page' => '',
        'actionable_feedback_page' => '',
        'corrections_policy_page' => '',
        'ethics_policy_page' => '',
        'diversity_policy_page' => '',
        'diversity_staffing_page' => '',
        'privacy_policy_page' => '',
        'terms_of_service_page' => '',
    ];
    /**
     * Initialize module hooks
     *
     * @return void
     */
    public function init_hooks(): void {
        // Register REST routes
        add_action('rest_api_init', [$this, 'register_rest_routes']);

        // Output verification meta tags
        add_action('wp_head', [$this, 'output_verification_meta'], 1);

        // Output organization schema
        add_action('wp_head', [$this, 'output_organization_schema'], 10);

        // Output social profiles schema
        add_action('wp_head', [$this, 'output_social_profiles_schema'], 11);

        // Initialize settings on activation
        add_action('init', [$this, 'maybe_init_settings']);
    }

    /**
     * Register REST routes
     *
     * @return void
     */
    public function register_rest_routes(): void {
        // Main settings endpoint
        register_rest_route('prorank-seo/v1', '/settings/site_basics', [
            'methods' => WP_REST_Server::READABLE,
            'callback' => [$this, 'get_settings_endpoint'],
            'permission_callback' => [$this, 'check_permission'],
        ]);

        register_rest_route('prorank-seo/v1', '/settings/site_basics', [
            'methods' => WP_REST_Server::CREATABLE,
            'callback' => [$this, 'update_settings_endpoint'],
            'permission_callback' => [$this, 'check_permission'],
        ]);

        // Verification status endpoint
        register_rest_route('prorank-seo/v1', '/site-basics/verification-status', [
            'methods' => WP_REST_Server::READABLE,
            'callback' => [$this, 'get_verification_status'],
            'permission_callback' => [$this, 'check_permission'],
        ]);

        // Test verification endpoint
        register_rest_route('prorank-seo/v1', '/site-basics/test-verification', [
            'methods' => WP_REST_Server::CREATABLE,
            'callback' => [$this, 'test_verification'],
            'permission_callback' => [$this, 'check_permission'],
        ]);
    }

    /**
     * Get settings endpoint
     *
     * @param WP_REST_Request $request Request object.
     * @return WP_REST_Response
     */
    public function get_settings_endpoint(WP_REST_Request $request): WP_REST_Response {
        $settings = $this->get_all_settings();

        // Merge with WordPress settings
        $settings['site_name'] = $settings['site_name'] ?: get_bloginfo('name');
        $settings['site_tagline'] = $settings['site_tagline'] ?: get_bloginfo('description');

        return new WP_REST_Response([
            'success' => true,
            'settings' => $settings,
        ]);
    }

    /**
     * Update settings endpoint
     *
     * @param WP_REST_Request $request Request object.
     * @return WP_REST_Response
     */
    public function update_settings_endpoint(WP_REST_Request $request): WP_REST_Response {
        $settings = $request->get_param('settings');

        if (empty($settings)) {
            return new WP_REST_Response([
                'success' => false,
                'message' => __('No settings provided', 'prorank-seo'),
            ], 400);
        }

        // Sanitize settings
        $sanitized = $this->sanitize_settings($settings);

        // Save settings
        foreach ($sanitized as $key => $value) {
            $this->update_setting($key, $value);
        }

        // Update WordPress settings if changed
        if (isset($sanitized['site_name']) && $sanitized['site_name']) {
            update_option('blogname', $sanitized['site_name']);
        }
        if (isset($sanitized['site_tagline']) && $sanitized['site_tagline']) {
            update_option('blogdescription', $sanitized['site_tagline']);
        }

        // Clear cache
        wp_cache_delete('prorank_site_basics_settings', 'prorank_seo');

        return new WP_REST_Response([
            'success' => true,
            'message' => __('Settings saved successfully', 'prorank-seo'),
            'settings' => $this->get_all_settings(),
        ]);
    }

    /**
     * Get verification status
     *
     * @return WP_REST_Response
     */
    public function get_verification_status(): WP_REST_Response {
        $settings = $this->get_all_settings();
        $status = [];

        $services = [
            'google' => 'google_verification',
            'bing' => 'bing_verification',
            'pinterest' => 'pinterest_verification',
            'yandex' => 'yandex_verification',
            'baidu' => 'baidu_verification',
            'norton' => 'norton_verification',
        ];

        foreach ($services as $service => $key) {
            $status[$service] = [
                'configured' => !empty($settings[$key]),
                'verified' => false, // Would need actual verification check
                'code' => $settings[$key],
            ];
        }

        return new WP_REST_Response([
            'success' => true,
            'status' => $status,
        ]);
    }

    /**
     * Test verification
     *
     * @param WP_REST_Request $request Request object.
     * @return WP_REST_Response
     */
    public function test_verification(WP_REST_Request $request): WP_REST_Response {
        $service = $request->get_param('service');
        $code = $request->get_param('code');

        // Simulate verification test
        // In production, this would actually check with the service
        $verified = !empty($code);

        return new WP_REST_Response([
            'success' => true,
            'verified' => $verified,
            'message' => $verified
                ? __('Verification successful', 'prorank-seo')
                : __('Verification failed', 'prorank-seo'),
        ]);
    }

    /**
     * Output verification meta tags
     *
     * @return void
     */
    public function output_verification_meta(): void {
        if (!is_front_page() && !is_home()) {
            return;
        }

        $settings = $this->get_all_settings();

        // Google verification
        if (!empty($settings['google_verification'])) {
            echo sprintf(
                '<meta name="google-site-verification" content="%s" />' . "\n",
                esc_attr($settings['google_verification'])
            );
        }

        // Bing verification
        if (!empty($settings['bing_verification'])) {
            echo sprintf(
                '<meta name="msvalidate.01" content="%s" />' . "\n",
                esc_attr($settings['bing_verification'])
            );
        }

        // Pinterest verification
        if (!empty($settings['pinterest_verification'])) {
            echo sprintf(
                '<meta name="p:domain_verify" content="%s" />' . "\n",
                esc_attr($settings['pinterest_verification'])
            );
        }

        // Yandex verification
        if (!empty($settings['yandex_verification'])) {
            echo sprintf(
                '<meta name="yandex-verification" content="%s" />' . "\n",
                esc_attr($settings['yandex_verification'])
            );
        }

        // Baidu verification
        if (!empty($settings['baidu_verification'])) {
            echo sprintf(
                '<meta name="baidu-site-verification" content="%s" />' . "\n",
                esc_attr($settings['baidu_verification'])
            );
        }

        // Norton verification
        if (!empty($settings['norton_verification'])) {
            echo sprintf(
                '<meta name="norton-safeweb-site-verification" content="%s" />' . "\n",
                esc_attr($settings['norton_verification'])
            );
        }

        // Custom meta tags
        if (!empty($settings['custom_meta_tags'])) {
            preg_match_all('/<meta\b[^>]*>/i', (string) $settings['custom_meta_tags'], $matches);
            $allowed_tags = [
                'meta' => [
                    'name' => [],
                    'content' => [],
                    'property' => [],
                    'http-equiv' => [],
                    'charset' => [],
                ],
            ];
            foreach ($matches[0] ?? [] as $tag) {
                $clean = trim((string) wp_kses($tag, $allowed_tags));
                if ($clean !== '') {
                    echo $clean . "\n";
                }
            }
        }
    }

    /**
     * Output organization schema
     *
     * @return void
     */
    public function output_organization_schema(): void {
        // Skip if consolidated schema output has already run (avoid duplicates)
        if (did_action('prorank_seo_register_schemas')) {
            return;
        }
        if (!is_front_page() && !is_home()) {
            return;
        }

        $settings = $this->get_all_settings();
        $is_person = ($settings['org_or_person'] ?? 'organization') === 'person';
        $selected_user = null;
        $schema_name = !empty($settings['org_name']) ? $settings['org_name'] : get_bloginfo('name');

        if ($is_person && !empty($settings['person_user_id'])) {
            $selected_user = get_user_by('id', (int) $settings['person_user_id']);
            if ($selected_user && !empty($selected_user->display_name)) {
                $schema_name = $selected_user->display_name;
            }
        }

        if (!$is_person && empty($settings['org_name'])) {
            return;
        }

        $is_local_business = !$is_person && !empty($settings['org_local_business_enabled']);

        $schema = [
            '@context' => 'https://schema.org',
            '@type' => $is_person ? 'Person' : ($is_local_business ? 'LocalBusiness' : 'Organization'),
            'name' => $schema_name,
            'url' => home_url('/'),
        ];

        if (!$is_person && !empty($settings['org_alternate_name'])) {
            $schema['alternateName'] = $settings['org_alternate_name'];
        }

        if ($is_person) {
            if (!empty($settings['person_logo'])) {
                $schema['image'] = $settings['person_logo'];
            } elseif (!empty($settings['person_logo_id'])) {
                $person_logo_url = wp_get_attachment_url((int) $settings['person_logo_id']);
                if (!empty($person_logo_url)) {
                    $schema['image'] = $person_logo_url;
                }
            } elseif ($selected_user) {
                $avatar_url = get_avatar_url($selected_user->ID);
                if (!empty($avatar_url)) {
                    $schema['image'] = $avatar_url;
                }
            } elseif (!empty($settings['org_logo'])) {
                $schema['image'] = $settings['org_logo'];
            }
        } elseif (!empty($settings['org_logo'])) {
            $schema['logo'] = $settings['org_logo'];
        }

        if (!empty($settings['org_description'])) {
            $schema['description'] = $settings['org_description'];
        }

        if (!empty($settings['org_email'])) {
            $schema['email'] = $settings['org_email'];
        }

        if (!empty($settings['org_phone'])) {
            $schema['telephone'] = $settings['org_phone'];
        }

        if (!$is_person && !empty($settings['org_founding_date'])) {
            $schema['foundingDate'] = $settings['org_founding_date'];
        }

        // Add address if available
        $street = $settings['org_street_address'] ?? '';
        $locality = $settings['org_address_locality'] ?? '';
        $postal_code = $settings['org_postal_code'] ?? '';

        if (empty($street) && !empty($settings['org_address_street'])) {
            $street = $settings['org_address_street'];
        }
        if (empty($locality) && !empty($settings['org_address_city'])) {
            $locality = $settings['org_address_city'];
        }
        if (empty($postal_code) && !empty($settings['org_address_postal'])) {
            $postal_code = $settings['org_address_postal'];
        }

        if (!empty($street) || !empty($locality)) {
            $address = [
                '@type' => 'PostalAddress',
            ];

            if (!empty($street)) {
                $address['streetAddress'] = $street;
            }
            if (!empty($locality)) {
                $address['addressLocality'] = $locality;
            }
            if (!empty($settings['org_address_region'])) {
                $address['addressRegion'] = $settings['org_address_region'];
            }
            if (!empty($postal_code)) {
                $address['postalCode'] = $postal_code;
            }
            if (!empty($settings['org_address_country'])) {
                $address['addressCountry'] = $settings['org_address_country'];
            }

            $schema['address'] = $address;
        }

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

            $publishing_principles = [];
            if (!empty($settings['publishing_principles_page'])) {
                $publishing_principles[] = get_permalink($settings['publishing_principles_page']);
            }
            if (!empty($settings['corrections_policy_page'])) {
                $publishing_principles[] = get_permalink($settings['corrections_policy_page']);
            }
            if (!empty($settings['ethics_policy_page'])) {
                $publishing_principles[] = get_permalink($settings['ethics_policy_page']);
            }
            if (!empty($settings['diversity_policy_page'])) {
                $publishing_principles[] = get_permalink($settings['diversity_policy_page']);
            }
            if (!empty($publishing_principles)) {
                $schema['publishingPrinciples'] = $publishing_principles;
            }
            if (!empty($settings['ownership_funding_page'])) {
                $schema['ownershipFundingInfo'] = get_permalink($settings['ownership_funding_page']);
            }
            if (!empty($settings['actionable_feedback_page'])) {
                $schema['actionableFeedbackPolicy'] = get_permalink($settings['actionable_feedback_page']);
            }
            if (!empty($settings['diversity_staffing_page'])) {
                $schema['diversityStaffingReport'] = get_permalink($settings['diversity_staffing_page']);
            }
            if (!empty($settings['privacy_policy_page'])) {
                $schema['privacyPolicy'] = get_permalink($settings['privacy_policy_page']);
            }
            if (!empty($settings['terms_of_service_page'])) {
                $schema['termsOfService'] = get_permalink($settings['terms_of_service_page']);
            }
        }

        // Output schema
        echo '<script type="application/ld+json">' . "\n";
        // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- JSON-LD script body.
        echo wp_json_encode($schema, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
        echo "\n" . '</script>' . "\n";
    }

    /**
     * Output social profiles schema
     *
     * @return void
     */
    public function output_social_profiles_schema(): void {
        // Skip if consolidated schema output has already run (avoid duplicates)
        if (did_action('prorank_seo_register_schemas')) {
            return;
        }
        if (!is_front_page() && !is_home()) {
            return;
        }

        $settings = $this->get_all_settings();
        $profiles = [];

        // Collect social profiles
        if (!empty($settings['facebook_page_url'])) {
            $profiles[] = $settings['facebook_page_url'];
        }
        if (!empty($settings['twitter_username'])) {
            $profiles[] = 'https://twitter.com/' . ltrim($settings['twitter_username'], '@');
        }
        if (!empty($settings['linkedin_url'])) {
            $profiles[] = $settings['linkedin_url'];
        }
        if (!empty($settings['instagram_url'])) {
            $profiles[] = $settings['instagram_url'];
        }
        if (!empty($settings['youtube_url'])) {
            $profiles[] = $settings['youtube_url'];
        }
        if (!empty($settings['pinterest_url'])) {
            $profiles[] = $settings['pinterest_url'];
        }
        if (!empty($settings['tiktok_url'])) {
            $profiles[] = $settings['tiktok_url'];
        }
        if (!empty($settings['threads_url'])) {
            $profiles[] = $settings['threads_url'];
        }
        if (!empty($settings['mastodon_url'])) {
            $profiles[] = $settings['mastodon_url'];
        }
        if (!empty($settings['github_url'])) {
            $profiles[] = $settings['github_url'];
        }

        // Add additional profiles
        if (!empty($settings['additional_profiles']) && is_array($settings['additional_profiles'])) {
            foreach ($settings['additional_profiles'] as $profile) {
                if (!empty($profile['url'])) {
                    $profiles[] = $profile['url'];
                }
            }
        }

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

        $schema_type = 'Organization';
        if ($settings['org_or_person'] === 'person') {
            $schema_type = 'Person';
        } elseif (!empty($settings['org_local_business_enabled'])) {
            $schema_type = 'LocalBusiness';
        }

        $schema_name = $settings['org_name'] ?: get_bloginfo('name');
        if ($schema_type === 'Person' && !empty($settings['person_user_id'])) {
            $selected_user = get_user_by('id', (int) $settings['person_user_id']);
            if ($selected_user && !empty($selected_user->display_name)) {
                $schema_name = $selected_user->display_name;
            }
        }

        $schema = [
            '@context' => 'https://schema.org',
            '@type' => $schema_type,
            'name' => $schema_name,
            'url' => home_url('/'),
            'sameAs' => array_filter($profiles),
        ];

        // Output schema
        echo '<script type="application/ld+json">' . "\n";
        // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- JSON-LD script body.
        echo wp_json_encode($schema, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
        echo "\n" . '</script>' . "\n";
    }

    /**
     * Sanitize settings
     *
     * @param array $settings Raw settings.
     * @return array
     */
    private function sanitize_settings(array $settings): array {
        $sanitized = [];

        foreach ($settings as $key => $value) {
            switch ($key) {
                case 'site_name':
                case 'site_alternate_name':
                case 'site_tagline':
                case 'org_name':
                case 'org_alternate_name':
                case 'org_legal_name':
                case 'org_description':
                    $sanitized[$key] = sanitize_text_field($value);
                    break;

                case 'site_logo':
                case 'site_image':
                case 'org_logo':
                case 'person_logo':
                case 'facebook_page_url':
                case 'linkedin_url':
                case 'instagram_url':
                case 'youtube_url':
                case 'pinterest_url':
                case 'tiktok_url':
                case 'github_url':
                    $sanitized[$key] = esc_url_raw($value);
                    break;

                case 'site_logo_id':
                case 'site_image_id':
                case 'org_logo_id':
                case 'person_logo_id':
                case 'person_user_id':
                case 'publishing_principles_page':
                case 'ownership_funding_page':
                case 'actionable_feedback_page':
                case 'corrections_policy_page':
                case 'ethics_policy_page':
                case 'diversity_policy_page':
                case 'diversity_staffing_page':
                case 'privacy_policy_page':
                case 'terms_of_service_page':
                case 'terms_conditions_page':
                    $sanitized[$key] = absint($value);
                    break;

                case 'google_verification':
                case 'bing_verification':
                case 'baidu_verification':
                case 'yandex_verification':
                case 'pinterest_verification':
                case 'norton_verification':
                    $sanitized[$key] = preg_replace('/[^a-zA-Z0-9_-]/', '', $value);
                    break;

                case 'twitter_username':
                    $sanitized[$key] = preg_replace('/[^a-zA-Z0-9_]/', '', $value);
                    break;

                case 'org_email':
                    $sanitized[$key] = sanitize_email($value);
                    break;

                case 'org_phone':
                    $sanitized[$key] = preg_replace('/[^0-9+\-\s\(\)]/', '', $value);
                    break;

                case 'org_local_business_enabled':
                    $sanitized[$key] = !empty($value);
                    break;

                case 'custom_meta_tags':
                    $sanitized[$key] = wp_kses($value, [
                        'meta' => [
                            'name' => [],
                            'content' => [],
                            'property' => [],
                        ],
                    ]);
                    break;

                case 'additional_profiles':
                    if (is_array($value)) {
                        $sanitized[$key] = array_map('esc_url_raw', $value);
                    }
                    break;

                case 'org_or_person':
                    $sanitized[$key] = in_array($value, ['organization', 'person'], true) ? $value : 'organization';
                    break;

                default:
                    $sanitized[$key] = sanitize_text_field($value);
            }
        }

        return $sanitized;
    }

    /**
     * Get all settings
     *
     * @return array
     */
    private function get_all_settings(): array {
        $cached = wp_cache_get('prorank_site_basics_settings', 'prorank_seo');
        if ($cached !== false) {
            return $cached;
        }

        $settings = [];
        foreach ($this->default_settings as $key => $default) {
            $settings[$key] = $this->get_setting($key, $default);
        }

        wp_cache_set('prorank_site_basics_settings', $settings, 'prorank_seo', 3600);

        return $settings;
    }

    /**
     * Check permission callback
     *
     * @return bool
     */
    public function check_permission(): bool {
        return current_user_can('manage_options');
    }

    /**
     * Maybe initialize settings
     *
     * @return void
     */
    public function maybe_init_settings(): void {
        $initialized = get_option('prorank_site_basics_initialized');
        if ($initialized) {
            return;
        }

        // Initialize with defaults
        foreach ($this->default_settings as $key => $default) {
            if ($this->get_setting($key) === null) {
                $this->update_setting($key, $default);
            }
        }

        // Try to auto-populate some settings
        $this->update_setting('site_name', get_bloginfo('name'));
        $this->update_setting('site_tagline', get_bloginfo('description'));

        update_option('prorank_site_basics_initialized', true);
    }
}
