<?php
/**
 * DBA_TIS_Scheduler — Weekly Automated Scanning
 *
 * Runs via WP-Cron every 7 days (synced with bot publishing cycles):
 *   1. Crawls entire site (local DB mode)
 *   2. Classifies all content by topic
 *   3. Generates recommendations and bot directives
 *   4. Stores results in scan history
 *   5. Optionally sends email digest to admin
 *
 * Weekly cadence ensures directives stay fresh — bots never waste
 * a generation cycle on a topic that's already been covered.
 *
 * Can also be triggered manually from the admin dashboard.
 *
 * @since 2.17.0
 */
if ( ! defined( 'ABSPATH' ) ) exit;

class DBA_TIS_Scheduler {

    const CRON_HOOK    = 'dba_tis_weekly_scan';
    const LOCK_KEY     = 'dba_tis_scan_lock';
    const LOCK_TTL     = 1800; // 30 minutes max scan time
    const SETTINGS_KEY = 'dba_tis_schedule_settings';

    private static $instance = null;

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

    private function __construct() {
        add_action( self::CRON_HOOK, array( $this, 'run_weekly_scan' ) );
    }

    /* ══════════════════════════════════════════════════════════════
     *  CRON SCHEDULING
     * ══════════════════════════════════════════════════════════════ */

    /**
     * Register the weekly cron schedule and event.
     * Runs every 7 days — synced with bot publishing cadence.
     */
    public static function schedule() {
        if ( ! wp_next_scheduled( self::CRON_HOOK ) ) {
            // Schedule first run for next Monday at 03:00 UTC (before bots fire)
            $next = strtotime( 'next monday 03:00:00 UTC' );
            wp_schedule_event( $next, 'weekly', self::CRON_HOOK );
            error_log( 'DBA TIS Scheduler: Scheduled weekly scan — next run ' . date( 'Y-m-d H:i', $next ) . ' UTC' );
        }

        // ── Cleanup: remove legacy monthly schedule if it exists ──
        $legacy = wp_next_scheduled( 'dba_tis_monthly_scan' );
        if ( $legacy ) {
            wp_clear_scheduled_hook( 'dba_tis_monthly_scan' );
            error_log( 'DBA TIS Scheduler: Removed legacy monthly schedule.' );
        }
    }

    /**
     * Unschedule the weekly cron.
     */
    public static function unschedule() {
        wp_clear_scheduled_hook( self::CRON_HOOK );
    }

    /**
     * Get next scheduled scan time.
     */
    public static function get_next_scan() {
        $next = wp_next_scheduled( self::CRON_HOOK );
        return $next ? date( 'Y-m-d H:i:s', $next ) : 'Not scheduled';
    }

    /**
     * Get schedule settings.
     */
    public static function get_settings() {
        return wp_parse_args( get_option( self::SETTINGS_KEY, array() ), array(
            'enabled'         => true,
            'use_ai'          => false,  // AI classification costs tokens
            'email_digest'    => true,
            'email_address'   => get_option( 'admin_email' ),
            'auto_directives' => true,   // Auto-generate bot directives after scan
        ) );
    }

    /**
     * Save schedule settings.
     */
    public static function save_settings( $settings ) {
        update_option( self::SETTINGS_KEY, $settings, false );

        if ( ! empty( $settings['enabled'] ) ) {
            self::schedule();
        } else {
            self::unschedule();
        }
    }

    /* ══════════════════════════════════════════════════════════════
     *  WEEKLY CRON RUN
     * ══════════════════════════════════════════════════════════════ */

    /**
     * Execute the weekly scan (called by WP-Cron every 7 days).
     */
    public function run_weekly_scan() {
        $settings = self::get_settings();

        if ( empty( $settings['enabled'] ) ) {
            error_log( 'DBA TIS: Weekly scan disabled — skipping.' );
            return;
        }

        // Prevent concurrent runs
        if ( get_transient( self::LOCK_KEY ) ) {
            error_log( 'DBA TIS: Scan already running (lock exists) — skipping.' );
            return;
        }
        set_transient( self::LOCK_KEY, true, self::LOCK_TTL );

        // Check Conflict Center if available
        if ( class_exists( 'DBA_Conflict_Center' ) ) {
            if ( ! DBA_Conflict_Center::acquire( 'tis', self::CRON_HOOK ) ) {
                delete_transient( self::LOCK_KEY );
                error_log( 'DBA TIS: Conflict Center denied — another bot is running.' );
                return;
            }
        }

        error_log( 'DBA TIS: ═══ Weekly scan starting ═══' );
        @set_time_limit( 600 );
        @ini_set( 'memory_limit', '512M' );

        try {
            // Run the scan
            $scan_results = DBA_TIS_Analyzer::run_scan( array(
                'use_ai' => ! empty( $settings['use_ai'] ),
            ) );

            if ( is_wp_error( $scan_results ) ) {
                error_log( 'DBA TIS: Scan failed — ' . $scan_results->get_error_message() );
                delete_transient( self::LOCK_KEY );
                return;
            }

            // Generate recommendations
            $recs = DBA_TIS_Recommender::generate_recommendations( $scan_results );
            error_log( 'DBA TIS: Generated ' . count( $recs ) . ' recommendations.' );

            // Auto-generate bot directives
            if ( ! empty( $settings['auto_directives'] ) ) {
                $directives = DBA_TIS_Recommender::generate_bot_directives( $recs );
                error_log( 'DBA TIS: Generated bot directives for ' . count( $directives ) . ' bots.' );
            }

            // Send email digest
            if ( ! empty( $settings['email_digest'] ) && ! empty( $settings['email_address'] ) ) {
                self::send_digest_email( $scan_results, $recs, $settings['email_address'] );
            }

            error_log( 'DBA TIS: ═══ Weekly scan complete — ' . $scan_results['total_pages'] . ' pages analyzed ═══' );

        } catch ( \Throwable $e ) {
            error_log( 'DBA TIS FATAL: ' . $e->getMessage() );
        }

        // Release locks
        delete_transient( self::LOCK_KEY );
        if ( class_exists( 'DBA_Conflict_Center' ) ) {
            DBA_Conflict_Center::release( 'tis' );
        }

        DBA_TIS_Analyzer::clear_progress();

        // ── Trigger Pipeline: harvest + validate in 60/120 min ──
        if ( class_exists( 'DBA_TIS_Pipeline' ) ) {
            DBA_TIS_Pipeline::schedule_after_scan();
            error_log( 'DBA TIS: Pipeline stages scheduled (harvest + validate).' );
        }
    }

    /* ══════════════════════════════════════════════════════════════
     *  MANUAL TRIGGER — Called from admin AJAX
     * ══════════════════════════════════════════════════════════════ */

    /**
     * Run a scan immediately (non-cron, called from admin).
     */
    public static function run_manual_scan( $use_ai = false, $language = 'en' ) {
        if ( get_transient( self::LOCK_KEY ) ) {
            return new WP_Error( 'locked', 'A scan is already running. Please wait.' );
        }
        set_transient( self::LOCK_KEY, true, self::LOCK_TTL );

        try {
            $scan_results = DBA_TIS_Analyzer::run_scan( array(
                'use_ai'   => $use_ai,
                'language' => $language,
            ) );

            if ( is_wp_error( $scan_results ) ) {
                delete_transient( self::LOCK_KEY );
                return $scan_results;
            }

            $recs = DBA_TIS_Recommender::generate_recommendations( $scan_results );
            $directives = DBA_TIS_Recommender::generate_bot_directives( $recs );

            delete_transient( self::LOCK_KEY );
            DBA_TIS_Analyzer::clear_progress();

            // Return minimal response — full data already stored via store_scan().
            // This prevents AJAX parse errors from oversized JSON responses.
            return array(
                'status'          => 'complete',
                'total_pages'     => $scan_results['total_pages'] ?? 0,
                'scan_language'   => $scan_results['scan_language'] ?? 'en',
                'recommendations' => count( $recs ),
                'directives'      => count( $directives ),
            );

        } catch ( \Throwable $e ) {
            delete_transient( self::LOCK_KEY );
            return new WP_Error( 'scan_error', $e->getMessage() );
        }
    }

    /**
     * Check if a scan is currently running.
     */
    public static function is_running() {
        return (bool) get_transient( self::LOCK_KEY );
    }

    /* ══════════════════════════════════════════════════════════════
     *  EMAIL DIGEST
     * ══════════════════════════════════════════════════════════════ */

    /**
     * Send a weekly scan digest email.
     */
    private static function send_digest_email( $scan, $recs, $to ) {
        $site_name = get_bloginfo( 'name' );
        $subject   = "[{$site_name}] TIS Weekly Scan Report — " . date( 'M j, Y' );

        $summary = array();
        $critical_count = 0;
        foreach ( $recs as $r ) {
            if ( $r['priority'] === 'critical' ) $critical_count++;
        }

        $body  = "<h2>🔬 Topic Intelligence Scanner — Weekly Report</h2>\n";
        $body .= "<p>Scan completed on " . $scan['scan_date'] . " — " . $scan['total_pages'] . " pages analyzed.</p>\n";

        // Top 5 topics
        $body .= "<h3>📊 Top Topics by Distribution</h3>\n<table border='1' cellpadding='8' cellspacing='0'>\n";
        $body .= "<tr><th>Topic</th><th>%</th><th>Pages</th></tr>\n";
        $i = 0;
        foreach ( $scan['distribution'] as $slug => $d ) {
            if ( $i >= 8 ) break;
            $body .= "<tr><td>{$d['label']}</td><td>{$d['percentage']}%</td><td>{$d['page_count']}</td></tr>\n";
            $i++;
        }
        $body .= "</table>\n";

        // Critical gaps
        if ( $critical_count > 0 ) {
            $body .= "<h3>🔴 Critical Content Gaps ({$critical_count})</h3>\n<ul>\n";
            foreach ( $recs as $r ) {
                if ( $r['priority'] === 'critical' ) {
                    $body .= "<li><strong>{$r['title']}</strong><br>{$r['message']}</li>\n";
                }
            }
            $body .= "</ul>\n";
        }

        $body .= "<p><a href='" . admin_url( 'admin.php?page=dba-tis' ) . "'>View full report in dashboard →</a></p>\n";

        $headers = array( 'Content-Type: text/html; charset=UTF-8' );
        wp_mail( $to, $subject, $body, $headers );
        error_log( "DBA TIS: Digest email sent to {$to}" );
    }
}
