<?php
/**
 * DBA_LuxStrat_Anti_Orphan — Cross-linking + Luxembourg authority links
 *
 * 1. Appends "Related Luxembourg Structuring" block to new post → 2-3 existing
 * 2. Injects backlinks FROM related posts → new post
 * 3. Injects LUXEMBOURG AUTHORITY outbound links (CSSF, Guichet.lu, RCS, etc.)
 * 4. 30-min verification cron + weekly audit across all themes
 *
 * Theme-based (not country/city): cross-links by theme affinity.
 * ALL LuxStrat-specific: _dba_luxstrat_* meta, DBA_LuxStrat_* class.
 * Drop into /luxstrat/ folder.
 *
 * @since 2.17.0
 */
if ( ! defined( 'ABSPATH' ) ) exit;

class DBA_LuxStrat_Anti_Orphan {

    private static $instance = null;
    public static function get_instance() { if(!self::$instance) self::$instance=new self(); return self::$instance; }

    const RELATED_CLASS  = 'dba-luxstrat-related';
    const AUTH_LINK_CLASS = 'dba-luxstrat-auth-link';
    const VERIFY_HOOK    = 'dba_luxstrat_verify_link';
    const AUDIT_HOOK     = 'dba_luxstrat_weekly_orphan_audit';

    /* ══════════════════════════════════════════════════════════════════
     *  LUXEMBOURG AUTHORITY URLs — institutional outbound links
     *  Boosts E-E-A-T by linking to official Luxembourg sources
     * ══════════════════════════════════════════════════════════════════ */
    private static $authority_urls = array(
        'cssf' => array(
            'url'   => 'https://www.cssf.lu',
            'label' => 'CSSF (Commission de Surveillance du Secteur Financier)',
            'short' => 'CSSF',
            'keywords' => array( 'CSSF', 'Commission de Surveillance', 'financial regulator', 'Luxembourg regulator', 'CSSF circular', 'CSSF supervision' ),
        ),
        'guichet' => array(
            'url'   => 'https://guichet.public.lu',
            'label' => 'Guichet.lu — Luxembourg Business Portal',
            'short' => 'Guichet.lu',
            'keywords' => array( 'Guichet', 'business portal', 'company formation', 'business registration', 'Luxembourg portal' ),
        ),
        'rcs' => array(
            'url'   => 'https://www.lbr.lu',
            'label' => 'Luxembourg Business Registers (RCS)',
            'short' => 'RCS',
            'keywords' => array( 'RCS', 'Business Register', 'Luxembourg register', 'Registre de Commerce', 'RCSL', 'trade register' ),
        ),
        'tax' => array(
            'url'   => 'https://impotsdirects.public.lu',
            'label' => 'Luxembourg Tax Administration',
            'short' => 'ACD',
            'keywords' => array( 'tax authority', 'Administration des Contributions Directes', 'Luxembourg tax', 'ACD', 'direct tax', 'corporate income tax', 'subscription tax' ),
        ),
        'legilux' => array(
            'url'   => 'https://legilux.public.lu',
            'label' => 'Legilux — Official Luxembourg Legislation',
            'short' => 'Legilux',
            'keywords' => array( 'Legilux', 'legislation', 'Law of 10 August 1915', 'Law of 23 July 2016', 'Journal Officiel', 'Luxembourg law', 'legal framework' ),
        ),
    );

    /* ── Theme affinity map — which themes are closely related ── */
    private static $theme_affinity = array(
        'scsp'           => array( 'raif', 'sicav_raif', 'depositary_bank' ),
        'raif'           => array( 'sicav_raif', 'scsp', 'depositary_bank' ),
        'depositary_bank'=> array( 'raif', 'sicav_raif', 'scsp' ),
        'sicav_raif'     => array( 'raif', 'depositary_bank', 'scsp' ),
    );

    private function __construct() {
        add_action( self::VERIFY_HOOK, array( $this, 'verify_link' ), 10, 1 );
        add_action( self::AUDIT_HOOK,  array( $this, 'run_weekly_audit' ) );
        if ( ! wp_next_scheduled( self::AUDIT_HOOK ) ) {
            wp_schedule_event( time() + WEEK_IN_SECONDS, 'weekly', self::AUDIT_HOOK );
        }
    }

    /* ══════════════════════════════════════════════════════════════════
     *  INJECT AUTHORITY LINKS into article content
     * ══════════════════════════════════════════════════════════════════ */
    public static function inject_authority_links( $content, $theme_slug = '' ) {
        $injected = 0;
        $max_links = 2; // max 2 authority outbound links per article

        foreach ( self::$authority_urls as $key => $auth ) {
            if ( $injected >= $max_links ) break;
            if ( strpos( $content, $auth['url'] ) !== false ) continue; // already linked

            // Find a keyword match in a <p> tag
            foreach ( $auth['keywords'] as $kw ) {
                if ( $injected >= $max_links ) break;
                $kw_esc = preg_quote( $kw, '/' );
                $pattern = '/(<p[^>]*>)((?:(?!<\/p>).)*?)(\b' . $kw_esc . '\b)((?:(?!<\/p>).)*?)(<\/p>)/siu';

                $content = preg_replace_callback(
                    $pattern,
                    function( $m ) use ( $auth, &$injected, $max_links ) {
                        if ( $injected >= $max_links ) return $m[0];
                        if ( preg_match( '/<a\s/i', $m[2] . $m[3] ) ) return $m[0]; // already inside a link
                        $injected++;
                        $link = '<a href="' . esc_url( $auth['url'] ) . '" target="_blank" rel="noopener noreferrer" class="' . self::AUTH_LINK_CLASS . '" title="' . esc_attr( $auth['label'] ) . '">' . $m[3] . '</a>';
                        return $m[1] . $m[2] . $link . $m[4] . $m[5];
                    },
                    $content,
                    1 // only first match per keyword
                );

                if ( $injected > 0 && strpos( $content, $auth['url'] ) !== false ) break; // this auth source done
            }
        }

        return $content;
    }

    /* ══════════════════════════════════════════════════════════════════
     *  APPEND "Related Luxembourg Structuring" block
     * ══════════════════════════════════════════════════════════════════ */
    public static function append_related_block( $post_id, $theme_slug ) {
        global $wpdb;

        // Get affine themes for cross-linking
        $affine = self::$theme_affinity[ $theme_slug ] ?? array_keys( self::$theme_affinity );

        // Score: same theme = high, affine theme = medium
        $related = $wpdb->get_results( $wpdb->prepare(
            "SELECT p.ID, p.post_title, pt.meta_value AS theme_slug FROM {$wpdb->posts} p
             INNER JOIN {$wpdb->postmeta} pm ON p.ID=pm.post_id AND pm.meta_key='_dba_luxstrat_auto_created'
             LEFT JOIN {$wpdb->postmeta} pt ON p.ID=pt.post_id AND pt.meta_key='_dba_luxstrat_theme'
             WHERE p.post_status='publish' AND p.ID!=%d
             ORDER BY
               CASE WHEN pt.meta_value=%s THEN 0 ELSE 1 END,
               p.post_date DESC
             LIMIT 3",
            $post_id, $theme_slug
        ), ARRAY_A );

        if ( empty( $related ) ) return false;

        $block = "\n\n<!-- LuxStrat Anti-Orphan Related Block -->\n"
            . '<div class="' . self::RELATED_CLASS . '" style="background:#f8fafc;border:1px solid #e2e8f0;border-radius:6px;padding:18px 22px;margin:28px 0;">'
            . "\n<h3 style=\"margin-top:0;color:#1a365d;\">Related Luxembourg Structuring Insights</h3>\n<ul>\n";

        foreach ( $related as $r ) {
            $url = get_permalink( $r['ID'] );
            if ( ! $url ) continue;
            $block .= '<li><a href="' . esc_url( $url ) . '">' . esc_html( $r['post_title'] ) . '</a></li>' . "\n";
        }

        $block .= "</ul>\n</div>\n";

        $content = get_post_field( 'post_content', $post_id );
        $content .= $block;

        $wpdb->update( $wpdb->posts, array( 'post_content' => $content ), array( 'ID' => $post_id ) );
        clean_post_cache( $post_id );
        return count( $related );
    }

    /* ══════════════════════════════════════════════════════════════════
     *  INJECT BACKLINKS from related posts → new post
     * ══════════════════════════════════════════════════════════════════ */
    public static function inject_backlinks( $new_post_id, $theme_slug ) {
        global $wpdb;

        $targets = $wpdb->get_results( $wpdb->prepare(
            "SELECT p.ID, p.post_content FROM {$wpdb->posts} p
             INNER JOIN {$wpdb->postmeta} pm ON p.ID=pm.post_id AND pm.meta_key='_dba_luxstrat_auto_created'
             WHERE p.post_status='publish' AND p.ID!=%d
             ORDER BY p.post_date DESC LIMIT 3",
            $new_post_id
        ), ARRAY_A );

        $new_url   = get_permalink( $new_post_id );
        $new_title = get_the_title( $new_post_id );
        if ( ! $new_url ) return 0;

        $count = 0;
        foreach ( $targets as $t ) {
            if ( strpos( $t['post_content'], $new_url ) !== false ) continue;

            $block_html = '<li><a href="' . esc_url( $new_url ) . '">' . esc_html( $new_title ) . '</a></li>';

            if ( strpos( $t['post_content'], self::RELATED_CLASS ) !== false ) {
                $updated = str_replace( '</ul>', $block_html . "\n</ul>", $t['post_content'] );
            } else {
                $updated = $t['post_content'] . "\n<!-- LuxStrat Anti-Orphan Backlink -->\n"
                    . '<div class="' . self::RELATED_CLASS . '" style="background:#f8fafc;border:1px solid #e2e8f0;border-radius:6px;padding:18px 22px;margin:28px 0;">'
                    . "\n<h3 style=\"margin-top:0;color:#1a365d;\">Related Luxembourg Structuring Insights</h3>\n<ul>\n"
                    . $block_html . "\n</ul>\n</div>\n";
            }

            $wpdb->update( $wpdb->posts, array( 'post_content' => $updated ), array( 'ID' => $t['ID'] ) );
            clean_post_cache( $t['ID'] );
            $count++;
        }

        return $count;
    }

    /* ══════════════════════════════════════════════════════════════════
     *  FULL PIPELINE — call from generator after post creation
     * ══════════════════════════════════════════════════════════════════ */
    public static function on_post_created( $post_id, $theme_slug ) {
        // 1. Inject authority links
        $content = get_post_field( 'post_content', $post_id );
        $updated = self::inject_authority_links( $content, $theme_slug );
        if ( $updated !== $content ) {
            global $wpdb;
            $wpdb->update( $wpdb->posts, array( 'post_content' => $updated ), array( 'ID' => $post_id ) );
            clean_post_cache( $post_id );
        }

        // 2. Append related block
        $related = self::append_related_block( $post_id, $theme_slug );

        // 3. Inject backlinks from related → new
        $backlinks = self::inject_backlinks( $post_id, $theme_slug );

        // 4. Schedule 30-min verification
        wp_schedule_single_event( time() + 1800, self::VERIFY_HOOK, array( $post_id ) );

        return array(
            'auth_links' => ( $updated !== $content ) ? 1 : 0,
            'related'    => $related ?: 0,
            'backlinks'  => $backlinks,
        );
    }

    /* ══════════════════════════════════════════════════════════════════
     *  VERIFY — 30 min after creation
     * ══════════════════════════════════════════════════════════════════ */
    public function verify_link( $post_id ) {
        if ( get_post_status( $post_id ) !== 'publish' ) return;
        $content = get_post_field( 'post_content', $post_id );

        if ( strpos( $content, self::RELATED_CLASS ) === false ) {
            $theme = get_post_meta( $post_id, '_dba_luxstrat_theme', true );
            self::append_related_block( $post_id, $theme ?: '' );
            error_log( "LuxStrat Anti-Orphan: verify fixed orphan #{$post_id}" );
        }

        if ( strpos( $content, self::AUTH_LINK_CLASS ) === false ) {
            $theme = get_post_meta( $post_id, '_dba_luxstrat_theme', true );
            $content = get_post_field( 'post_content', $post_id );
            $updated = self::inject_authority_links( $content, $theme ?: '' );
            if ( $updated !== $content ) {
                global $wpdb;
                $wpdb->update( $wpdb->posts, array( 'post_content' => $updated ), array( 'ID' => $post_id ) );
                clean_post_cache( $post_id );
            }
        }
    }

    /* ══════════════════════════════════════════════════════════════════
     *  AUDIT — scan all LuxStrat posts, fix orphans
     * ══════════════════════════════════════════════════════════════════ */
    public static function audit_all() {
        global $wpdb;

        $ids = $wpdb->get_col(
            "SELECT p.ID FROM {$wpdb->posts} p
             INNER JOIN {$wpdb->postmeta} pm ON p.ID=pm.post_id AND pm.meta_key='_dba_luxstrat_auto_created'
             WHERE p.post_status='publish' ORDER BY p.post_date DESC"
        );

        $total = count( $ids );
        $orphaned = 0;
        $fixed = 0;

        foreach ( $ids as $pid ) {
            $content = get_post_field( 'post_content', $pid );
            $has_related = strpos( $content, self::RELATED_CLASS ) !== false;
            $has_auth = strpos( $content, self::AUTH_LINK_CLASS ) !== false;

            if ( ! $has_related ) {
                $orphaned++;
                $theme = get_post_meta( $pid, '_dba_luxstrat_theme', true );
                $result = self::append_related_block( $pid, $theme ?: '' );
                if ( $result ) $fixed++;
            }

            if ( ! $has_auth ) {
                $theme = get_post_meta( $pid, '_dba_luxstrat_theme', true );
                $content = get_post_field( 'post_content', $pid );
                $updated = self::inject_authority_links( $content, $theme ?: '' );
                if ( $updated !== $content ) {
                    $wpdb->update( $wpdb->posts, array('post_content'=>$updated), array('ID'=>$pid) );
                    clean_post_cache( $pid );
                }
            }
        }

        return array( 'total' => $total, 'orphaned' => $orphaned, 'fixed' => $fixed );
    }

    public function run_weekly_audit() {
        self::audit_all();
        error_log( 'LuxStrat Anti-Orphan: weekly audit complete' );
    }

    /* ══════════════════════════════════════════════════════════════════
     *  ADMIN HELPERS
     * ══════════════════════════════════════════════════════════════════ */
    public static function get_orphan_stats() {
        global $wpdb;
        $all = $wpdb->get_col(
            "SELECT pm.post_id FROM {$wpdb->postmeta} pm
             INNER JOIN {$wpdb->posts} p ON pm.post_id=p.ID
             WHERE pm.meta_key='_dba_luxstrat_auto_created' AND p.post_status='publish'
             ORDER BY p.post_date DESC"
        );
        $total = count($all);
        $linked = 0; $auth_linked = 0; $orphans = array();

        foreach ( $all as $pid ) {
            $c = get_post_field('post_content',$pid);
            if (strpos($c, self::RELATED_CLASS) !== false) $linked++;
            if (strpos($c, self::AUTH_LINK_CLASS) !== false) $auth_linked++;
            if (strpos($c, self::RELATED_CLASS) === false && count($orphans) < 10)
                $orphans[] = array('id'=>$pid, 'title'=>get_the_title($pid));
        }

        return array(
            'total'        => $total,
            'linked'       => $linked,
            'auth_linked'  => $auth_linked,
            'orphan_count' => $total - $linked,
            'orphans'      => $orphans,
        );
    }

    public static function get_all_authority_urls() {
        return self::$authority_urls;
    }
}
