<?php
/**
 * Rank Math migration adapter.
 *
 * Rank Math stores per-post meta in `rank_math_*` postmeta keys and redirects
 * in `wp_rank_math_redirections` (custom table) when the Redirections module
 * is active.
 *
 * @package Brainwerk SEO Suite
 */

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

class Seoforge_Migrate_RankMath {

    public static function source_label() {
        return 'Rank Math';
    }

    public static function is_available() {
        global $wpdb;
        return defined( 'RANK_MATH_VERSION' )
            || (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->postmeta} WHERE meta_key = 'rank_math_title' LIMIT 1" ) > 0;
    }

    public static function count_posts() {
        global $wpdb;
        return (int) $wpdb->get_var( "SELECT COUNT(DISTINCT post_id) FROM {$wpdb->postmeta} WHERE meta_key LIKE 'rank_math_%'" );
    }

    public static function count_redirects() {
        return count( self::list_redirects() );
    }

    public static function map_post_meta( $post_id ) {
        $get = function ( $k ) use ( $post_id ) {
            return get_post_meta( (int) $post_id, 'rank_math_' . $k, true );
        };
        $title  = $get( 'title' );
        $desc   = $get( 'description' );
        $focus  = $get( 'focus_keyword' );
        $robots = (array) $get( 'robots' );
        $canon  = $get( 'canonical_url' );
        $og_t   = $get( 'facebook_title' );
        $og_d   = $get( 'facebook_description' );
        $og_img = $get( 'facebook_image' );
        // twitter_title/twitter_description have no matching Seoforge_Meta field
        // (Twitter card output always falls back to the OG title/description —
        // see class-seoforge-meta.php) so they're not fetched here; twitter_image
        // still feeds the og_image fallback below.
        $tw_img = $get( 'twitter_image' );

        $row = array();
        if ( $title )  { $row['seo_title']       = self::expand_rm_vars( $title ); }
        if ( $desc )   { $row['seo_description'] = self::expand_rm_vars( $desc ); }
        if ( $focus )  {
            // Rank Math may store comma-separated keywords; we keep the first.
            $first = trim( (string) explode( ',', $focus )[0] );
            $row['focus_keyword'] = $first;
        }
        if ( $og_t )    { $row['og_title']       = self::expand_rm_vars( $og_t ); }
        if ( $og_d )    { $row['og_description'] = self::expand_rm_vars( $og_d ); }
        if ( $og_img )  { $row['og_image']       = $og_img; }
        if ( ! $og_img && $tw_img ) { $row['og_image'] = $tw_img; }
        if ( $canon )   { $row['canonical']      = $canon; }
        if ( in_array( 'noindex', $robots, true ) )  { $row['robots_noindex']  = 1; }
        if ( in_array( 'nofollow', $robots, true ) ) { $row['robots_nofollow'] = 1; }
        return $row;
    }

    public static function expand_rm_vars( $tpl ) {
        $tpl = (string) $tpl;
        $repl = array(
            '%sitename%'    => wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES ),
            '%sitedesc%'    => wp_specialchars_decode( get_bloginfo( 'description' ), ENT_QUOTES ),
            '%sep%'         => '–',
            '%currentdate%' => date_i18n( get_option( 'date_format' ) ),
            '%currentyear%' => date_i18n( 'Y' ),
        );
        return strtr( $tpl, $repl );
    }

    public static function list_redirects() {
        global $wpdb;
        $tbl = $wpdb->prefix . 'rank_math_redirections';
        $exists = (bool) $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $tbl ) );
        if ( ! $exists ) {
            return array();
        }
        $rows = $wpdb->get_results( $wpdb->prepare( "SELECT sources, url_to, header_code, status FROM %i WHERE status = 'active' LIMIT 5000", $tbl ), ARRAY_A );
        $out = array();
        foreach ( (array) $rows as $r ) {
            $sources = maybe_unserialize( $r['sources'] );
            if ( ! is_array( $sources ) ) { continue; }
            foreach ( $sources as $src ) {
                if ( empty( $src['pattern'] ) ) { continue; }
                $type = isset( $src['comparison'] ) ? $src['comparison'] : 'exact';
                $match = ( 'start' === $type || 'contains' === $type ) ? 'prefix' : 'exact';
                $out[] = array(
                    'source_path' => '/' . ltrim( (string) $src['pattern'], '/' ),
                    'target_url'  => (string) $r['url_to'],
                    'status_code' => (int) $r['header_code'] ?: 301,
                    'match_type'  => $match,
                    'note'        => 'imported from Rank Math',
                );
            }
        }
        return $out;
    }
}
