<?php
/**
 * DBA Startup Hub Anti-Orphan Protection
 *
 * Ensures every Startup Hub article is linked FROM the hub page
 * and has cross-links to/from related articles.
 *
 * Features:
 *   - Auto-append new posts to the hub page article list
 *   - Inject "Related Ecosystems" section into existing posts
 *   - Schedule verification cron to catch missed links
 *   - Weekly audit to find and fix orphaned posts
 *
 * @since 2.16.0
 */

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

class DBA_Startup_Hub_Anti_Orphan {

    private static $instance = null;

    /** Marker comment used in the hub page to locate the article list. */
    const HUB_LIST_MARKER = '<!-- DBA_STARTUP_HUB_LIST -->';

    /** Cron hook for single-post verification. */
    const VERIFY_HOOK = 'dba_startup_hub_verify_link';

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

    private function __construct() {
        add_action( self::VERIFY_HOOK, array( $this, 'verify_single_post' ), 10, 1 );
    }

    /* =================================================================
     *  LINK FROM HUB PAGE
     *
     *  Appends the new article to the hub page's list section.
     * ================================================================= */

    /**
     * Link a new post from the hub page.
     *
     * @param int    $post_id        New post ID.
     * @param string $category_short Short category label (e.g. "FinTech").
     * @param string $city           City name.
     */
    public function link_from_hub_page( $post_id, $category_short, $city ) {
        $config = DBA_Startup_Hub_Registry::get_config();
        $hub_id = get_option( $config['hub_page_option'], 0 );

        if ( ! $hub_id || ! get_post_status( $hub_id ) || get_post_status( $hub_id ) === 'trash' ) {
            error_log( 'DBA StartupHub Anti-Orphan: No hub page found. Skipping hub link for #' . $post_id );
            return false;
        }

        $hub_content = get_post_field( 'post_content', $hub_id );
        $permalink   = get_permalink( $post_id );
        $title       = get_the_title( $post_id );

        // Already linked?
        if ( strpos( $hub_content, $permalink ) !== false ) {
            error_log( 'DBA StartupHub Anti-Orphan: Post #' . $post_id . ' already linked from hub page.' );
            return true;
        }

        // Build the link HTML
        $link_html = '<li><a href="' . esc_url( $permalink ) . '">' . esc_html( $title ) . '</a>'
            . ' — <em>' . esc_html( $category_short ) . ' in ' . esc_html( $city ) . '</em></li>';

        // Try inserting at the marker position
        if ( strpos( $hub_content, self::HUB_LIST_MARKER ) !== false ) {
            // Find or create the <ul> list after the marker
            $marker_pos = strpos( $hub_content, self::HUB_LIST_MARKER );
            $after      = substr( $hub_content, $marker_pos + strlen( self::HUB_LIST_MARKER ) );

            if ( strpos( $after, '<ul>' ) === false || strpos( $after, '<ul>' ) > 20 ) {
                // No <ul> right after marker — create one
                $new_content = substr( $hub_content, 0, $marker_pos + strlen( self::HUB_LIST_MARKER ) )
                    . "\n<ul>\n" . $link_html . "\n</ul>"
                    . $after;
            } else {
                // Insert into existing <ul> (before closing </ul>)
                $ul_close_pos = strpos( $after, '</ul>' );
                if ( $ul_close_pos !== false ) {
                    $abs_pos = $marker_pos + strlen( self::HUB_LIST_MARKER ) + $ul_close_pos;
                    $new_content = substr( $hub_content, 0, $abs_pos )
                        . $link_html . "\n"
                        . substr( $hub_content, $abs_pos );
                } else {
                    // Fallback: append before last </p> or at end
                    $new_content = $hub_content . "\n<ul>\n" . $link_html . "\n</ul>";
                }
            }
        } else {
            // No marker found — append a list section before the CTA
            $cta_pos = stripos( $hub_content, 'dba-startup-hub-cta' );
            if ( $cta_pos !== false ) {
                // Find the start of the CTA div
                $div_start = strrpos( substr( $hub_content, 0, $cta_pos ), '<div' );
                if ( $div_start !== false ) {
                    $new_content = substr( $hub_content, 0, $div_start )
                        . "\n" . self::HUB_LIST_MARKER . "\n<ul>\n" . $link_html . "\n</ul>\n\n"
                        . substr( $hub_content, $div_start );
                } else {
                    $new_content = $hub_content . "\n\n" . self::HUB_LIST_MARKER . "\n<ul>\n" . $link_html . "\n</ul>";
                }
            } else {
                $new_content = $hub_content . "\n\n" . self::HUB_LIST_MARKER . "\n<ul>\n" . $link_html . "\n</ul>";
            }
        }

        wp_update_post( array(
            'ID'           => $hub_id,
            'post_content' => $new_content,
        ) );

        error_log( 'DBA StartupHub Anti-Orphan: Linked post #' . $post_id . ' from hub page #' . $hub_id );
        return true;
    }

    /* =================================================================
     *  CROSS-LINK FROM RELATED POSTS
     *
     *  Injects a "Related Cities" / "Related Ecosystems" section
     *  into up to 3 existing posts in the same category or city.
     * ================================================================= */

    /**
     * Inject backlinks from related posts to the new post.
     *
     * @param int    $post_id  New post ID.
     * @param string $cat_slug Category slug.
     * @param string $city     City name.
     */
    public function inject_backlinks_from_related( $post_id, $cat_slug, $city ) {
        $config = DBA_Startup_Hub_Registry::get_config();

        // Find related posts: same category OR same city, excluding this post
        $related = get_posts( array(
            'post_type'      => 'post',
            'post_status'    => 'publish',
            'meta_key'       => $config['meta_auto_created'],
            'meta_compare'   => 'EXISTS',
            'posts_per_page' => 6,
            'fields'         => 'ids',
            'exclude'        => array( $post_id ),
            'meta_query'     => array(
                'relation' => 'OR',
                array( 'key' => '_dba_startup_hub_category', 'value' => $cat_slug ),
                array( 'key' => '_dba_startup_hub_city',     'value' => $city ),
            ),
        ) );

        if ( empty( $related ) ) {
            error_log( 'DBA StartupHub Anti-Orphan: No related posts found for cross-linking #' . $post_id );
            return;
        }

        $new_permalink = get_permalink( $post_id );
        $new_title     = get_the_title( $post_id );
        $linked_count  = 0;

        foreach ( array_slice( $related, 0, 3 ) as $related_id ) {
            $rel_content = get_post_field( 'post_content', $related_id );

            // Skip if already linked
            if ( strpos( $rel_content, $new_permalink ) !== false ) continue;

            // Build the related section
            $section = "\n\n" . '<div class="startup-hub-related" style="background:#f9fafb;border:1px solid #e5e7eb;border-radius:6px;padding:16px 20px;margin:24px 0;">'
                . '<h3 style="margin:0 0 8px;font-size:1em;">Related Ecosystems</h3>'
                . '<p style="margin:0;"><a href="' . esc_url( $new_permalink ) . '">' . esc_html( $new_title ) . '</a></p>'
                . '</div>';

            // Inject before CTA if present, otherwise append
            $cta_pos = stripos( $rel_content, 'dba-startup-hub-cta' );
            if ( $cta_pos !== false ) {
                $div_start = strrpos( substr( $rel_content, 0, $cta_pos ), '<div' );
                if ( $div_start !== false ) {
                    $updated = substr( $rel_content, 0, $div_start ) . $section . "\n" . substr( $rel_content, $div_start );
                } else {
                    $updated = $rel_content . $section;
                }
            } else {
                $updated = $rel_content . $section;
            }

            wp_update_post( array(
                'ID'           => $related_id,
                'post_content' => $updated,
            ) );

            $linked_count++;
        }

        error_log( 'DBA StartupHub Anti-Orphan: Injected backlinks in ' . $linked_count . ' related posts for #' . $post_id );
    }

    /* =================================================================
     *  VERIFICATION SCHEDULING
     * ================================================================= */

    /**
     * Schedule a one-time verification for a post (30 min after publish).
     *
     * @param int $post_id
     */
    public function schedule_verification( $post_id ) {
        $timestamp = time() + ( 30 * MINUTE_IN_SECONDS );
        wp_schedule_single_event( $timestamp, self::VERIFY_HOOK, array( $post_id ) );
    }

    /**
     * Verify that a published post is linked from the hub page.
     * If not, re-run the hub link process.
     *
     * @param int $post_id
     */
    public function verify_single_post( $post_id ) {
        $config = DBA_Startup_Hub_Registry::get_config();
        $hub_id = get_option( $config['hub_page_option'], 0 );

        if ( ! $hub_id ) return;

        $hub_content = get_post_field( 'post_content', $hub_id );
        $permalink   = get_permalink( $post_id );

        if ( $permalink && strpos( $hub_content, $permalink ) === false ) {
            $category_short = get_post_meta( $post_id, '_dba_theme', true ) ?: 'Startup';
            $city           = get_post_meta( $post_id, '_dba_startup_hub_city', true ) ?: '';

            $this->link_from_hub_page( $post_id, $category_short, $city );
            error_log( 'DBA StartupHub Anti-Orphan: Verification fixed orphan #' . $post_id );
        }
    }

    /* =================================================================
     *  WEEKLY AUDIT
     * ================================================================= */

    /**
     * Scan all Startup Hub posts and fix any orphans.
     *
     * @return array { 'total' => int, 'orphaned' => int, 'fixed' => int }
     */
    public function weekly_audit() {
        $config = DBA_Startup_Hub_Registry::get_config();
        $hub_id = get_option( $config['hub_page_option'], 0 );

        $result = array( 'total' => 0, 'orphaned' => 0, 'fixed' => 0 );

        if ( ! $hub_id || ! get_post_status( $hub_id ) || get_post_status( $hub_id ) === 'trash' ) {
            error_log( 'DBA StartupHub Anti-Orphan Audit: No hub page — aborting.' );
            return $result;
        }

        $hub_content = get_post_field( 'post_content', $hub_id );

        $all_posts = get_posts( array(
            'post_type'      => 'post',
            'post_status'    => 'publish',
            'meta_key'       => $config['meta_auto_created'],
            'meta_compare'   => 'EXISTS',
            'posts_per_page' => -1,
            'fields'         => 'ids',
        ) );

        $result['total'] = count( $all_posts );

        foreach ( $all_posts as $pid ) {
            if ( $pid == $hub_id ) continue;

            $permalink = get_permalink( $pid );
            if ( $permalink && strpos( $hub_content, $permalink ) === false ) {
                $result['orphaned']++;

                $category_short = get_post_meta( $pid, '_dba_theme', true ) ?: 'Startup';
                $city           = get_post_meta( $pid, '_dba_startup_hub_city', true ) ?: '';

                if ( $this->link_from_hub_page( $pid, $category_short, $city ) ) {
                    $result['fixed']++;
                    // Refresh hub content for next iteration
                    $hub_content = get_post_field( 'post_content', $hub_id );
                }
            }
        }

        error_log( 'DBA StartupHub Anti-Orphan Audit: total=' . $result['total']
            . ', orphaned=' . $result['orphaned'] . ', fixed=' . $result['fixed'] );

        return $result;
    }
}
