<?php

/**
 * Yoast SEO Importer
 *
 * @package ProRank\SEO\Core\Importers
 * @since   1.0.0
 */

declare(strict_types=1);

namespace ProRank\SEO\Core\Importers;

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


/**
 * YoastImporter class
 * 
 * Imports data from Yoast SEO plugin
 */


class YoastImporter extends BaseImporter {
    
    /**
     * Yoast meta key mappings
     *
     * @var array
     */
    private array $meta_key_map = [
        '_yoast_wpseo_title' => '_prorank_seo_title',
        '_yoast_wpseo_metadesc' => '_prorank_seo_description',
        // Focus keywords handled in import_single_post_meta() via FocusKeywords::save().
        '_yoast_wpseo_canonical' => '_prorank_seo_canonical_url',
        // Robots handled specially in import_single_post_meta() → _prorank_meta_robots array.
        '_yoast_wpseo_opengraph-title' => '_prorank_og_title',
        '_yoast_wpseo_opengraph-description' => '_prorank_og_description',
        '_yoast_wpseo_opengraph-image' => '_prorank_og_image_id',
        '_yoast_wpseo_twitter-title' => '_prorank_twitter_title',
        '_yoast_wpseo_twitter-description' => '_prorank_twitter_description',
        '_yoast_wpseo_twitter-image' => '_prorank_twitter_image_id',
    ];
    
    /**
     * Check if Yoast is available
     *
     * @return bool
     */
    public function is_available(): bool {
        return defined('WPSEO_VERSION') || 
               class_exists('WPSEO_Options') || 
               $this->has_yoast_data();
    }
    
    /**
     * Check if Yoast data exists in database
     *
     * @return bool
     */
    private function has_yoast_data(): bool {
        global $wpdb;
        
        $result = $wpdb->get_var(
            "SELECT COUNT(*) FROM {$wpdb->postmeta} 
             WHERE meta_key LIKE '_yoast_wpseo_%' 
             LIMIT 1"
        );
        
        return (int) $result > 0;
    }
    
    /**
     * Run the import
     *
     * @return array
     */
    public function import(): array {
        if (!$this->is_available()) {
            return [
                'success' => false,
                'message' => __('Yoast SEO data not found', 'prorank-seo'),
                'stats' => $this->stats,
            ];
        }
        
        try {
            // Import post/page meta
            $this->import_post_meta();
            
            // Import term meta
            $this->import_term_meta();
            
            // Import settings
            $this->import_settings();
            
            // Import redirects if available
            $this->import_redirects();
            
            // Import schema settings
            $this->import_schema();

            // Import local SEO locations
            $this->import_locations();
            
            return [
                'success' => true,
                'message' => __('Yoast SEO data imported successfully', 'prorank-seo'),
                'stats' => $this->stats,
            ];
            
        } catch (\Exception $e) {
            $this->log_error('Import failed: ' . $e->getMessage());
            
            return [
                'success' => false,
                'message' => $e->getMessage(),
                'stats' => $this->stats,
            ];
        }
    }
    
    /**
     * Import single post meta
     *
     * @param int $post_id Post ID
     * @return void
     */
    protected function import_single_post_meta(int $post_id): void {
        foreach ($this->meta_key_map as $yoast_key => $prorank_key) {
            $value = get_post_meta($post_id, $yoast_key, true);

            if (!empty($value)) {
                update_post_meta($post_id, $prorank_key, $this->sanitize_meta_value($value));
            }
        }

        // Build _prorank_meta_robots array from Yoast noindex/nofollow flags.
        $robots = [];
        $noindex = get_post_meta($post_id, '_yoast_wpseo_meta-robots-noindex', true);
        if ($noindex === '1') {
            $robots[] = 'noindex';
        }
        $nofollow = get_post_meta($post_id, '_yoast_wpseo_meta-robots-nofollow', true);
        if ($nofollow === '1') {
            $robots[] = 'nofollow';
        }
        if (!empty($robots)) {
            update_post_meta($post_id, '_prorank_meta_robots', $robots);
        }

        // Import focus keywords via multi-keyword model.
        // Primary: _yoast_wpseo_focuskw (Free + Premium)
        // Additional: _yoast_wpseo_focuskeywords (Premium only, JSON array of strings)
        $primary_kw = trim((string) get_post_meta($post_id, '_yoast_wpseo_focuskw', true));
        if ($primary_kw === '') {
            $primary_kw = trim((string) get_post_meta($post_id, '_yoast_wpseo_focuskw_text_input', true));
        }

        if ($primary_kw !== '') {
            $kw_input = [['keyword' => $primary_kw, 'primary' => true]];

            // Yoast Premium stores additional keyphrases as JSON array of strings.
            $additional_raw = get_post_meta($post_id, '_yoast_wpseo_focuskeywords', true);
            if (!empty($additional_raw)) {
                $additional = is_string($additional_raw) ? json_decode($additional_raw, true) : $additional_raw;
                if (is_array($additional)) {
                    foreach ($additional as $extra) {
                        // Yoast Premium format: array of {"keyword":"...", "synonyms":["..."]}
                        $extra_kw = '';
                        if (is_string($extra)) {
                            $extra_kw = trim($extra);
                        } elseif (is_array($extra) && !empty($extra['keyword'])) {
                            $extra_kw = trim((string) $extra['keyword']);
                        }
                        if ($extra_kw !== '' && $extra_kw !== $primary_kw) {
                            $kw_input[] = ['keyword' => $extra_kw, 'primary' => false];
                        }
                    }
                }
            }

            \ProRank\SEO\Core\FocusKeywords::save($post_id, $kw_input);
        }

        // Import primary category
        $primary_category = get_post_meta($post_id, '_yoast_wpseo_primary_category', true);
        if ($primary_category) {
            update_post_meta($post_id, '_prorank_seo_primary_category', $primary_category);
        }

        // Import breadcrumb title
        $breadcrumb_title = get_post_meta($post_id, '_yoast_wpseo_bctitle', true);
        if ($breadcrumb_title) {
            update_post_meta($post_id, '_prorank_seo_breadcrumb_title', $breadcrumb_title);
        }

        // Import content score
        $content_score = get_post_meta($post_id, '_yoast_wpseo_content_score', true);
        if ($content_score !== '') {
            update_post_meta($post_id, '_prorank_seo_score', intval($content_score));
        }

        // Import schema page type
        $schema_page_type = get_post_meta($post_id, '_yoast_wpseo_schema_page_type', true);
        if (!empty($schema_page_type)) {
            update_post_meta($post_id, '_prorank_seo_schema_type', sanitize_text_field((string) $schema_page_type));
        }
    }
    
    /**
     * Import single term meta
     *
     * @param int $term_id Term ID
     * @return void
     */
    protected function import_single_term_meta(int $term_id): void {
        // Get Yoast term meta from options table (older versions)
        $term_meta = get_option('wpseo_taxonomy_meta');
        
        if ($term_meta && is_array($term_meta)) {
            foreach ($term_meta as $taxonomy => $terms) {
                if (isset($terms[$term_id])) {
                    $meta = $terms[$term_id];
                    
                    // Map Yoast term meta to ProRank
                    if (isset($meta['wpseo_title'])) {
                        update_term_meta($term_id, '_prorank_seo_title', $meta['wpseo_title']);
                    }
                    if (isset($meta['wpseo_desc'])) {
                        update_term_meta($term_id, '_prorank_seo_description', $meta['wpseo_desc']);
                    }
                    if (isset($meta['wpseo_canonical'])) {
                        update_term_meta($term_id, '_prorank_seo_canonical', $meta['wpseo_canonical']);
                    }
                    if (isset($meta['wpseo_noindex'])) {
                        $noindex = $meta['wpseo_noindex'] === 'noindex' ? 'noindex' : 'index';
                        update_term_meta($term_id, '_prorank_seo_noindex', $noindex);
                    }
                }
            }
        }
        
        // Also check for newer term meta format
        $title = get_term_meta($term_id, 'wpseo_title', true);
        if ($title) {
            update_term_meta($term_id, '_prorank_seo_title', $title);
        }
        
        $desc = get_term_meta($term_id, 'wpseo_desc', true);
        if ($desc) {
            update_term_meta($term_id, '_prorank_seo_description', $desc);
        }
    }
    
    /**
     * Import Yoast settings
     *
     * @return void
     */
    protected function import_settings(): void {
        $site_basics = [];

        // Import general settings from wpseo and wpseo_titles.
        $wpseo = get_option('wpseo');
        $wpseo_titles = get_option('wpseo_titles');
        if (($wpseo && is_array($wpseo)) || ($wpseo_titles && is_array($wpseo_titles))) {
            $settings = [];

            // Map separator
            $separator = $wpseo_titles['separator'] ?? $wpseo['separator'] ?? null;
            if ($separator !== null) {
                $separator_map = [
                    'sc-dash' => '-',
                    'sc-ndash' => '–',
                    'sc-mdash' => '—',
                    'sc-colon' => ':',
                    'sc-middot' => '·',
                    'sc-bull' => '•',
                    'sc-star' => '*',
                    'sc-smstar' => '⋆',
                    'sc-pipe' => '|',
                    'sc-tilde' => '~',
                ];
                $settings['title_separator'] = $separator_map[(string) $separator] ?? '-';
                $site_basics['title_separator'] = $settings['title_separator'];
            }

            // Sitemap setting (Yoast stores this in wpseo option).
            if (isset($wpseo['enablexmlsitemap'])) {
                $this->merge_option_array('prorank_seo_sitemap', [
                    'enable_sitemap' => $this->to_bool($wpseo['enablexmlsitemap']),
                ]);
                $this->stats['settings']++;
            }

            if ($wpseo_titles && is_array($wpseo_titles)) {
                $title_settings = [];

                if (isset($wpseo_titles['title-home-wpseo'])) {
                    $title_settings['homepage_title'] = $wpseo_titles['title-home-wpseo'];
                }
                if (isset($wpseo_titles['metadesc-home-wpseo'])) {
                    $title_settings['homepage_description'] = $wpseo_titles['metadesc-home-wpseo'];
                }

                if (!empty($title_settings)) {
                    $this->merge_option_array('prorank_seo_titles_meta', $title_settings);
                    $this->stats['settings']++;
                }
            }

            // Save settings
            if (!empty($settings)) {
                $this->merge_option_array('prorank_seo_settings', $settings);
                $this->stats['settings']++;
            }

            if ($wpseo_titles && is_array($wpseo_titles)) {
                if (!empty($wpseo_titles['website_name'])) {
                    $site_basics['site_name'] = sanitize_text_field((string) $wpseo_titles['website_name']);
                }
                if (!empty($wpseo_titles['alternate_website_name'])) {
                    $site_basics['site_alternate_name'] = sanitize_text_field((string) $wpseo_titles['alternate_website_name']);
                }
                if (!empty($wpseo_titles['company_or_person'])) {
                    $site_basics['site_representation'] = sanitize_text_field((string) $wpseo_titles['company_or_person']);
                } elseif (!empty($wpseo_titles['company_or_person_user'])) {
                    $site_basics['site_representation'] = sanitize_text_field((string) $wpseo_titles['company_or_person_user']);
                }
                if (!empty($wpseo_titles['company_name'])) {
                    $site_basics['organization_name'] = sanitize_text_field((string) $wpseo_titles['company_name']);
                } elseif (!empty($wpseo_titles['company_name_user'])) {
                    $site_basics['organization_name'] = sanitize_text_field((string) $wpseo_titles['company_name_user']);
                }
                if (!empty($wpseo_titles['company_logo'])) {
                    $site_basics['organization_logo'] = esc_url_raw((string) $wpseo_titles['company_logo']);
                }
            }

            if ($wpseo && is_array($wpseo)) {
                $verification_map = [
                    'googleverify' => 'google_verification',
                    'msverify' => 'bing_verification',
                    'yandexverify' => 'yandex_verification',
                ];
                foreach ($verification_map as $source_key => $target_key) {
                    if (!empty($wpseo[$source_key])) {
                        $site_basics[$target_key] = sanitize_text_field((string) $wpseo[$source_key]);
                    }
                }
            }
        }
        
        // Import social settings
        $social = get_option('wpseo_social');
        if ($social && is_array($social)) {
            $social_settings = [];
            
            if (isset($social['facebook_site'])) {
                $social_settings['facebook_page_url'] = $social['facebook_site'];
            }
            if (isset($social['twitter_site'])) {
                $social_settings['twitter_username'] = str_replace('@', '', $social['twitter_site']);
            }
            
            if (!empty($social_settings)) {
                $this->merge_option_array('prorank_seo_social', $social_settings);
                $this->merge_site_basics($social_settings);
                $this->stats['settings']++;
            }
        }

        $this->merge_site_basics($site_basics);
    }
    
    /**
     * Import Yoast Premium redirects
     *
     * @return void
     */
    protected function import_redirects(): void {
        global $wpdb;
        
        // Check if Yoast Premium redirects table exists
        $table = $wpdb->prefix . 'yoast_seo_redirects';
        if ($wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $table)) !== $table) {
            return;
        }
        
        $redirects = $wpdb->get_results("SELECT * FROM $table WHERE status = 'enabled'");
        
        foreach ($redirects as $redirect) {
            $is_regex = false;
            if (isset($redirect->format) && in_array((string) $redirect->format, ['regex', 'plain-regex'], true)) {
                $is_regex = true;
            }
            if (isset($redirect->regex) && intval($redirect->regex) === 1) {
                $is_regex = true;
            }

            // Store redirect in ProRank format
            $prorank_redirect = [
                'from' => isset($redirect->origin) ? (string) $redirect->origin : '',
                'to' => isset($redirect->target) ? (string) $redirect->target : '',
                'type' => isset($redirect->type) ? intval($redirect->type) : 301,
                'is_regex' => $is_regex,
                'status' => 'active',
                'notes' => 'Imported from Yoast SEO',
            ];
            
            if ($this->save_redirect($prorank_redirect)) {
                $this->stats['redirects']++;
            }
        }
    }
    
    /**
     * Import schema settings
     *
     * @return void
     */
    protected function import_schema(): void {
        $schema = get_option('wpseo_schema');
        if (!$schema || !is_array($schema)) {
            $schema = get_option('wpseo_titles');
        }
        
        if ($schema && is_array($schema)) {
            // Map Yoast schema settings to ProRank
            $prorank_schema = [];
            
            if (isset($schema['company_or_person'])) {
                $prorank_schema['site_representation'] = $schema['company_or_person'];
            } elseif (isset($schema['company_or_person_user'])) {
                $prorank_schema['site_representation'] = $schema['company_or_person_user'];
            }
            
            if (isset($schema['company_name'])) {
                $prorank_schema['organization_name'] = $schema['company_name'];
            } elseif (isset($schema['company_name_user'])) {
                $prorank_schema['organization_name'] = $schema['company_name_user'];
            }
            
            if (isset($schema['company_logo'])) {
                $prorank_schema['organization_logo'] = $schema['company_logo'];
            } elseif (isset($schema['company_logo_id'])) {
                $prorank_schema['organization_logo'] = $schema['company_logo_id'];
            }
            
            if (!empty($prorank_schema)) {
                $this->merge_option_array('prorank_seo_schema', $prorank_schema);
                $this->merge_site_basics($prorank_schema);
                $this->stats['settings']++;
            }
        }
    }

    /**
     * Import Yoast Local SEO locations.
     *
     * @return void
     */
    protected function import_locations(): void {
        if (!in_array('locations', $this->import_types, true)) {
            return;
        }

        $imported = 0;

        $settings = $this->get_yoast_local_settings();
        if (!empty($settings)) {
            $from_settings = $this->build_location_from_yoast_settings($settings);
            if (!empty($from_settings) && $this->save_location($from_settings)) {
                $imported++;
            }
        }

        $location_posts = $this->get_yoast_location_posts();
        foreach ($location_posts as $location_post) {
            $location = $this->build_location_from_yoast_post((int) $location_post->ID);
            if (!empty($location) && $this->save_location($location)) {
                $imported++;
            }
        }

        $this->stats['locations'] += $imported;
    }
    
    /**
     * Map meta key
     *
     * @param string $competitor_key Yoast meta key
     * @return string ProRank meta key
     */
    protected function map_meta_key(string $competitor_key): string {
        return $this->meta_key_map[$competitor_key] ?? $competitor_key;
    }
    
    /**
     * Save redirect into ProRank redirect storage.
     *
     * @param array $redirect Redirect data
     * @return bool
     */
    protected function save_redirect(array $redirect): bool {
        return parent::save_redirect($redirect);
    }

    /**
     * Normalize truthy/falsy values from Yoast options.
     *
     * @param mixed $value Raw value.
     * @return bool
     */
    private function to_bool($value): bool {
        if (is_bool($value)) {
            return $value;
        }

        if (is_numeric($value)) {
            return (int) $value === 1;
        }

        $value = strtolower((string) $value);
        return in_array($value, ['1', 'yes', 'on', 'true', 'enabled'], true);
    }

    /**
     * Fetch Yoast Local SEO option payload.
     *
     * @return array
     */
    private function get_yoast_local_settings(): array {
        $option_names = [
            'wpseo_local',
            'yoast_wpseo_local',
            'wpseo_local_business_info',
        ];

        foreach ($option_names as $option_name) {
            $raw = get_option($option_name);
            if (!$raw) {
                continue;
            }

            if (is_string($raw)) {
                $decoded = json_decode($raw, true);
                if (is_array($decoded)) {
                    $raw = $decoded;
                } else {
                    $raw = maybe_unserialize($raw);
                }
            }

            if (is_array($raw) && !empty($raw)) {
                return $raw;
            }
        }

        return [];
    }

    /**
     * Build ProRank location payload from Yoast settings.
     *
     * @param array $settings Yoast local settings.
     * @return array
     */
    private function build_location_from_yoast_settings(array $settings): array {
        $name = $this->extract_nested_value($settings, [
            'company_or_store_name',
            'company_name',
            'business_name',
            'name',
        ]);

        $address = $this->extract_nested_value($settings, [
            'street_address',
            'address',
            'address_street',
        ]);

        $city = $this->extract_nested_value($settings, ['address_locality', 'city', 'locality']);
        $state = $this->extract_nested_value($settings, ['address_region', 'state', 'region']);
        $postal = $this->extract_nested_value($settings, ['postal_code', 'zipcode', 'zip']);
        $country = $this->extract_nested_value($settings, ['address_country', 'country']);

        if (empty($name) && empty($address) && empty($city)) {
            return [];
        }

        return [
            'name' => (string) ($name ?: get_bloginfo('name')),
            'description' => (string) ($this->extract_nested_value($settings, ['description']) ?? ''),
            'address' => (string) ($address ?? ''),
            'city' => (string) ($city ?? ''),
            'state' => (string) ($state ?? ''),
            'postalCode' => (string) ($postal ?? ''),
            'country' => (string) ($country ?? ''),
            'phone' => (string) ($this->extract_nested_value($settings, ['phone', 'telephone']) ?? ''),
            'email' => (string) ($this->extract_nested_value($settings, ['email']) ?? ''),
            'latitude' => (float) ($this->extract_nested_value($settings, ['coords_lat', 'latitude', 'lat']) ?? 0),
            'longitude' => (float) ($this->extract_nested_value($settings, ['coords_long', 'longitude', 'lng']) ?? 0),
            'openingHours' => $this->normalize_yoast_opening_hours($this->extract_nested_value($settings, ['opening_hours', 'openingHours'])),
            'status' => 'active',
            'isPrimary' => true,
        ];
    }

    /**
     * Get location posts created by Yoast Local SEO.
     *
     * @return array
     */
    private function get_yoast_location_posts(): array {
        $post_types = ['wpseo_locations', 'yoast_locations'];
        $found = [];

        foreach ($post_types as $post_type) {
            if (!post_type_exists($post_type)) {
                continue;
            }

            $posts = get_posts([
                'post_type' => $post_type,
                'posts_per_page' => -1,
                'post_status' => ['publish', 'private', 'draft', 'pending'],
            ]);

            if (!empty($posts)) {
                $found = array_merge($found, $posts);
            }
        }

        return $found;
    }

    /**
     * Build ProRank location payload from a Yoast location post.
     *
     * @param int $post_id Location post id.
     * @return array
     */
    private function build_location_from_yoast_post(int $post_id): array {
        $name = get_the_title($post_id);
        $address = $this->get_meta_any($post_id, [
            '_wpseo_business_address',
            'wpseo_business_address',
            '_yoast_wpseo_business_address',
            'address',
        ]);
        $city = $this->get_meta_any($post_id, [
            '_wpseo_business_city',
            'wpseo_business_city',
            '_yoast_wpseo_business_city',
            'city',
        ]);

        if (empty($name) && empty($address) && empty($city)) {
            return [];
        }

        $status = get_post_status($post_id);

        return [
            'id' => 'loc_yoast_' . $post_id,
            'name' => $name,
            'description' => wp_strip_all_tags((string) get_post_field('post_content', $post_id)),
            'address' => (string) ($address ?? ''),
            'city' => (string) ($city ?? ''),
            'state' => (string) ($this->get_meta_any($post_id, ['_wpseo_business_state', 'wpseo_business_state', '_yoast_wpseo_business_state', 'state']) ?? ''),
            'postalCode' => (string) ($this->get_meta_any($post_id, ['_wpseo_business_zipcode', 'wpseo_business_zipcode', '_yoast_wpseo_business_zipcode', 'postal_code', 'zip']) ?? ''),
            'country' => (string) ($this->get_meta_any($post_id, ['_wpseo_business_country', 'wpseo_business_country', '_yoast_wpseo_business_country', 'country']) ?? ''),
            'phone' => (string) ($this->get_meta_any($post_id, ['_wpseo_business_phone', 'wpseo_business_phone', '_yoast_wpseo_business_phone', 'phone']) ?? ''),
            'email' => (string) ($this->get_meta_any($post_id, ['_wpseo_business_email', 'wpseo_business_email', '_yoast_wpseo_business_email', 'email']) ?? ''),
            'latitude' => (float) ($this->get_meta_any($post_id, ['_wpseo_business_lat', 'wpseo_business_lat', '_yoast_wpseo_business_lat', 'latitude', 'lat']) ?? 0),
            'longitude' => (float) ($this->get_meta_any($post_id, ['_wpseo_business_long', 'wpseo_business_long', '_yoast_wpseo_business_long', 'longitude', 'lng']) ?? 0),
            'openingHours' => $this->normalize_yoast_opening_hours($this->get_meta_any($post_id, ['_wpseo_opening_hours', 'wpseo_opening_hours', '_yoast_wpseo_opening_hours'])),
            'status' => ($status === 'publish') ? 'active' : 'inactive',
            'isPrimary' => false,
        ];
    }

    /**
     * Read first non-empty post meta from candidate keys.
     *
     * @param int   $post_id Post id.
     * @param array $keys    Candidate keys.
     * @return mixed|null
     */
    private function get_meta_any(int $post_id, array $keys) {
        foreach ($keys as $key) {
            $value = get_post_meta($post_id, (string) $key, true);
            if ($value !== '' && $value !== null) {
                return $value;
            }
        }

        return null;
    }

    /**
     * Extract first non-empty value from nested arrays.
     *
     * @param array $data  Source data.
     * @param array $keys  Candidate keys.
     * @param int   $depth Internal recursion depth.
     * @return mixed|null
     */
    private function extract_nested_value(array $data, array $keys, int $depth = 0) {
        if ($depth > 5) {
            return null;
        }

        foreach ($keys as $key) {
            if (array_key_exists($key, $data) && $data[$key] !== '' && $data[$key] !== null) {
                return $data[$key];
            }
        }

        foreach ($data as $value) {
            if (!is_array($value)) {
                continue;
            }

            $nested = $this->extract_nested_value($value, $keys, $depth + 1);
            if ($nested !== null && $nested !== '') {
                return $nested;
            }
        }

        return null;
    }

    /**
     * Normalize Yoast opening hours payload.
     *
     * @param mixed $hours Raw opening hours value.
     * @return array
     */
    private function normalize_yoast_opening_hours($hours): array {
        if (is_string($hours)) {
            $decoded = json_decode($hours, true);
            if (is_array($decoded)) {
                $hours = $decoded;
            } else {
                $hours = maybe_unserialize($hours);
            }
        }

        if (!is_array($hours)) {
            return [];
        }

        return $this->normalize_opening_hours($hours);
    }
}
