<?php

require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';

if (!function_exists('fleekdash_log_debug')) {
    require_once FLEEKDASH_PLUGIN_DIR . 'includes/Core/debug-helpers.php';
}

class FleekDashCoreUpgraderSkin extends WP_Upgrader_Skin
{
    /** @var array<int, array<string, mixed>> */
    private array $messages = array();
    /** @var array<int, array<string, mixed>> */
    private array $errors = array();
    private bool $hadErrors = false;
    private string $currentAction = '';

    /**
     * @param array<string, mixed> $args
     */
    public function __construct($args = array())
    {
        parent::__construct($args);
        fleekdash_log_debug('FleekDash: Initializing core upgrader skin');
    }

    public function header()
    {
        fleekdash_log_debug('FleekDash: Header called');
        $this->feedback('Starting WordPress core process...');
    }

    public function footer()
    {
        fleekdash_log_debug('FleekDash: Footer called');
        if ($this->hadErrors) {
            $this->feedback('Core process finished with errors');
        } else {
            $this->feedback('Core process finished successfully');
        }
    }

    /**
     * @param string $title
     */
    public function before($title = '')
    {
        fleekdash_log_debug('FleekDash: Before called with title: ' . $title);
        $this->currentAction = $title;
        $this->feedback('Starting %s...', $title);
    }

    /**
     * @param string $title
     */
    public function after($title = '')
    {
        fleekdash_log_debug('FleekDash: After called with title: ' . $title);
        if ($this->hadErrors) {
            $this->feedback('Failed to complete %s', $title);
        } else {
            $this->feedback('Successfully completed %s', $title);
        }
    }

    public function feedback($string, ...$args)
    {
        fleekdash_log_debug('FleekDash: Feedback called with: ' . print_r(array($string, $args), true));

        if (empty($string)) {
            return;
        }

        $resolvedString = $this->resolveFeedbackString($string);
        if ($resolvedString === '' || strpos($resolvedString, 'maintenance_') === 0) {
            if (strpos($resolvedString, 'maintenance_') === 0) {
                fleekdash_log_debug('FleekDash: Ignoring maintenance message');
            }
            return;
        }

        $message = $this->buildStructuredMessage($resolvedString, $args);
        $this->messages[] = $message;
        fleekdash_log_debug('FleekDash Core Progress: ' . print_r($message, true));
    }

    public function error($errors)
    {
        fleekdash_log_debug('FleekDash: Error called with: ' . print_r($errors, true));
        $this->hadErrors = true;

        if (is_string($errors)) {
            $message = array(
                'message' => $errors,
                'timestamp' => time(),
                'action' => $this->currentAction,
                'type' => 'error'
            );
            $this->errors[] = $message;
            fleekdash_log_debug('FleekDash Core Error: ' . $errors);
        } elseif (is_wp_error($errors)) {
            foreach ($errors->get_error_messages() as $error) {
                $message = array(
                    'message' => $error,
                    'timestamp' => time(),
                    'action' => $this->currentAction,
                    'type' => 'error'
                );
                $this->errors[] = $message;
                fleekdash_log_debug('FleekDash Core Error: ' . $error);
            }
        }
    }

    public function get_upgrade_messages()
    {
        fleekdash_log_debug('FleekDash: Getting upgrade messages');
        fleekdash_log_debug('FleekDash: Progress messages: ' . print_r($this->messages, true));
        fleekdash_log_debug('FleekDash: Error messages: ' . print_r($this->errors, true));

        $all_messages = array();

        // Merge progress entries
        foreach ($this->messages as $message) {
            $all_messages[] = array(
                'type' => isset($message['type']) ? $message['type'] : $this->getMessageType($message['message']),
                'message' => $message['message'],
                'timestamp' => $message['timestamp'],
                'action' => isset($message['action']) ? $message['action'] : '',
                'step' => isset($message['step']) ? $message['step'] : ''
            );
        }

        // Append structured errors
        foreach ($this->errors as $error) {
            $all_messages[] = array(
                'type' => 'error',
                'message' => 'Error: ' . $error['message'],
                'timestamp' => $error['timestamp'],
                'action' => isset($error['action']) ? $error['action'] : ''
            );
        }

        // Chronological ordering
        usort($all_messages, function ($a, $b) {
            return $a['timestamp'] - $b['timestamp'];
        });

        // Terminal summary when failures occurred
        if ($this->hadErrors) {
            $all_messages[] = array(
                'type' => 'error',
                'message' => 'Core process completed with errors',
                'timestamp' => time()
            );
        }

        return $all_messages;
    }

    private function getMessageType(string $message): string
    {
        $lowerMessage = strtolower($message);
        $messageType = 'info';
        if (
            strpos($lowerMessage, 'error') !== false ||
            strpos($lowerMessage, 'failed') !== false ||
            strpos($lowerMessage, 'could not') !== false ||
            strpos($lowerMessage, 'unable to') !== false
        ) {
            $messageType = 'error';
        } elseif (
            strpos($lowerMessage, 'success') !== false ||
            strpos($lowerMessage, 'finished') !== false ||
            strpos($lowerMessage, 'completed') !== false
        ) {
            $messageType = 'success';
        } elseif (strpos($lowerMessage, 'downloading') !== false) {
            $messageType = 'downloading';
        } elseif (strpos($lowerMessage, 'unpack') !== false) {
            $messageType = 'unpacking';
        } elseif (strpos($lowerMessage, 'install') !== false) {
            $messageType = 'installing';
        } elseif (strpos($lowerMessage, 'updating') !== false) {
            $messageType = 'updating';
        } elseif (strpos($lowerMessage, 'verifying') !== false) {
            $messageType = 'verifying';
        }
        return $messageType;
    }

    public function decrement_update_count($type)
    {
        fleekdash_log_debug('FleekDash: Decrement update count called for type: ' . $type);
    }

    /**
     * @param mixed $string
     */
    private function resolveFeedbackString($string): string
    {
        $resolved = '';
        if (is_object($string) && method_exists($string, 'strings') && isset($string->strings[0])) {
            $resolved = (string) $string->strings[0];
        } elseif (is_scalar($string)) {
            $resolved = (string) $string;
        }
        return $resolved;
    }

    /**
     * @param array<int, mixed> $args
     * @return array<string, mixed>
     */
    private function buildStructuredMessage(string $format, array $args): array
    {
        $text = vsprintf($format, $args);
        $message = array(
            'message' => $text,
            'timestamp' => time(),
        );
        if (!empty($this->currentAction)) {
            $message['action'] = $this->currentAction;
        }

        $lowerMessage = strtolower($text);
        $step = $this->detectStep($lowerMessage);
        if ($step !== '') {
            $message['step'] = $step;
        }
        if ($this->isErrorMessage($lowerMessage)) {
            $message['type'] = 'error';
            $this->hadErrors = true;
        }
        return $message;
    }

    private function detectStep(string $lowerMessage): string
    {
        $step = '';
        if (strpos($lowerMessage, 'downloading') !== false) {
            $step = 'downloading';
        } elseif (strpos($lowerMessage, 'unpack') !== false) {
            $step = 'unpacking';
        } elseif (strpos($lowerMessage, 'install') !== false) {
            $step = 'installing';
        } elseif (strpos($lowerMessage, 'updating') !== false) {
            $step = 'updating';
        } elseif (strpos($lowerMessage, 'verifying') !== false) {
            $step = 'verifying';
        }
        return $step;
    }

    private function isErrorMessage(string $lowerMessage): bool
    {
        return strpos($lowerMessage, 'error') !== false
            || strpos($lowerMessage, 'failed') !== false
            || strpos($lowerMessage, 'could not') !== false
            || strpos($lowerMessage, 'unable to') !== false;
    }
}

if (!class_exists('FleekDash_Core_Upgrader_Skin', false)) {
    class_alias(FleekDashCoreUpgraderSkin::class, 'FleekDash_Core_Upgrader_Skin');
}
