<?php
/**
 * File State Renderer - Main Orchestration
 *
 * Renders the unified File State Scanner UI.
 * One scan, one fix, one report.
 *
 * This main class handles:
 * - State management (get_unified_state, get_last_scan, etc.)
 * - Main render() orchestration
 *
 * UI components are in: class-sqmedia-file-state-renderer-components.php
 * CSS/JS assets are in: class-sqmedia-file-state-renderer-assets.php
 *
 * @package StaticQ
 */

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

// Load component files
require_once __DIR__ . '/class-sqmedia-file-state-renderer-components.php';
require_once __DIR__ . '/class-sqmedia-file-state-renderer-assets.php';

class SQMedia_File_State_Renderer {

    /**
     * Statuses
     */
    const STATUS_NOT_SCANNED = 'not_scanned';
    const STATUS_SCANNING = 'scanning';
    const STATUS_BUILDING_INDEX = 'building_index';
    const STATUS_PAUSED = 'paused';
    const STATUS_CLEAN = 'clean';
    const STATUS_ISSUES = 'issues';
    const STATUS_CRITICAL = 'critical';
    const STATUS_FIXING = 'fixing';

    /**
     * Database instance
     */
    private SQMedia_Database $db;

    /**
     * Components renderer
     */
    private SQMedia_File_State_Renderer_Components $components;

    /**
     * Assets renderer
     */
    private SQMedia_File_State_Renderer_Assets $assets;

    /**
     * Constructor
     */
    public function __construct() {
        $this->db = sqmedia()->get_database();
        $this->components = new SQMedia_File_State_Renderer_Components($this, $this->db);
        $this->assets = new SQMedia_File_State_Renderer_Assets();
    }

    /**
     * Render the complete health check section
     */
    public function render(): void {
        $state = $this->get_unified_state();

        ?>
        <div class="sqmedia-section sqmedia-file-state-scanner">
            <h2>📊 <?php esc_html_e('Media Library Scanner', 'staticq-media'); ?></h2>

            <?php $this->components->render_unified_card($state); ?>
        </div>

        <?php $this->assets->render_styles(); ?>
        <?php $this->assets->render_scripts($state); ?>
        <?php
    }

    // =========================================================================
    // STATE MANAGEMENT
    // =========================================================================

    /**
     * Get unified scanner state
     *
     * Checks for running/paused/completed scans and returns combined status.
     */
    public function get_unified_state(): array {
        // Check for running scan (any phase, including unified)
        $running_scan = $this->db->get_running_scan('file_state');

        if ($running_scan) {
            $status = $running_scan->status;
            if ($status === 'building_index') {
                $mapped_status = self::STATUS_BUILDING_INDEX;
            } elseif ($status === 'fixing') {
                $mapped_status = self::STATUS_FIXING;
            } else {
                $mapped_status = self::STATUS_SCANNING;
            }

            return [
                'status' => $mapped_status,
                'scan_id' => $running_scan->scan_id,
                'processed' => (int) $running_scan->processed_items,
                'total' => (int) $running_scan->total_items,
                'results' => $running_scan->results,
                'started_at' => $running_scan->scan_started,
            ];
        }

        // Check for paused scan
        $paused_scan = $this->get_paused_scan();

        if ($paused_scan) {
            return [
                'status' => self::STATUS_PAUSED,
                'scan_id' => $paused_scan->scan_id,
                'processed' => (int) $paused_scan->processed_items,
                'total' => (int) $paused_scan->total_items,
                'results' => $paused_scan->results,
            ];
        }

        // Check for last completed scan
        $last_scan = $this->get_last_scan();

        if (!$last_scan) {
            return [
                'status' => self::STATUS_NOT_SCANNED,
                'scan_id' => null,
                'results' => null,
            ];
        }

        // Analyze results
        $results = $last_scan->results;
        $issue_counts = $this->db->get_scan_item_counts($last_scan->scan_id);
        $file_counts = $this->db->get_scan_file_counts($last_scan->scan_id);
        $total_issues = array_sum($issue_counts);
        $total_issue_files = array_sum($file_counts);

        // Unfixable categories: no automated fix exists
        $unfixable_categories = ['critical_missing', 'original_missing'];
        $fixable_issues = $total_issues;
        foreach ($unfixable_categories as $cat) {
            $fixable_issues -= ($issue_counts[$cat] ?? 0);
        }

        $attachments_with_issues = $this->db->get_scan_attachments_with_issues($last_scan->scan_id);

        $total_files_checked = $results['summary']['files_checked'] ?? 0;
        $files_ok = max(0, $total_files_checked - $total_issue_files);

        $has_critical = isset($issue_counts['critical_missing']) && $issue_counts['critical_missing'] > 0;

        if ($total_issues === 0) {
            $status = self::STATUS_CLEAN;
        } elseif ($has_critical) {
            $status = self::STATUS_CRITICAL;
        } else {
            $status = self::STATUS_ISSUES;
        }

        // Check if this is an old phase-specific scan
        $current_phase = $results['current_phase'] ?? 'unified';
        $is_legacy = ($current_phase !== 'unified');

        return [
            'status' => $status,
            'scan_id' => $last_scan->scan_id,
            'scanned_at' => $last_scan->scan_completed ?? $last_scan->scan_started,
            'total_scanned' => (int) $last_scan->total_items,
            'duration' => $this->calculate_duration($last_scan->scan_started, $last_scan->scan_completed),
            'results' => $results,
            'issue_counts' => $issue_counts,
            'file_counts' => $file_counts,
            'total_issues' => $total_issues,
            'fixable_issues' => $fixable_issues,
            'total_issue_files' => $total_issue_files,
            'attachments_with_issues' => $attachments_with_issues,
            'files_ok' => $files_ok,
            'is_legacy' => $is_legacy,
        ];
    }

    /**
     * Get the last completed scan (any phase)
     */
    public function get_last_scan(): ?object {
        global $wpdb;

        $table = SQMedia_Database::get_table(SQMedia_Database::TABLE_SCANS);

        // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
        $row = $wpdb->get_row(
            "SELECT * FROM {$table}
             WHERE scan_type = 'file_state'
             AND status = 'completed'
             ORDER BY scan_completed DESC
             LIMIT 1"
        );
        // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter

        if ($row) {
            $row->results = json_decode($row->results, true) ?: [];
        }

        return $row;
    }

    /**
     * Get a paused scan (any phase)
     */
    public function get_paused_scan(): ?object {
        global $wpdb;

        $table = SQMedia_Database::get_table(SQMedia_Database::TABLE_SCANS);

        // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
        $row = $wpdb->get_row(
            "SELECT * FROM {$table}
             WHERE scan_type = 'file_state'
             AND status = 'paused'
             ORDER BY scan_started DESC
             LIMIT 1"
        );
        // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter

        if ($row) {
            $row->results = json_decode($row->results, true) ?: [];
        }

        return $row;
    }

    /**
     * Calculate duration between two times
     */
    public function calculate_duration(?string $start, ?string $end): string {
        if (!$start || !$end) {
            return '';
        }

        $start_time = strtotime($start);
        $end_time = strtotime($end);
        $diff = $end_time - $start_time;

        if ($diff < 60) {
            /* translators: %d: number of seconds */
            return sprintf(__('%ds', 'staticq-media'), $diff);
        } elseif ($diff < 3600) {
            $minutes = floor($diff / 60);
            $seconds = $diff % 60;
            /* translators: %1$d: number of minutes, %2$d: number of seconds */
            return sprintf(__('%1$dm %2$ds', 'staticq-media'), $minutes, $seconds);
        } else {
            $hours = floor($diff / 3600);
            $minutes = floor(($diff % 3600) / 60);
            /* translators: %1$d: number of hours, %2$d: number of minutes */
            return sprintf(__('%1$dh %2$dm', 'staticq-media'), $hours, $minutes);
        }
    }
}
