<?php
namespace Lcmigrator\LcMigrator\Logger;

class Logger {
    private string $logFile;
    private bool $fileLoggingEnabled;
    private bool $wpDebugEnabled;
    private bool $logInfoLogs;
    private static ?Logger $instance = null;

    // Define log levels
    public const ERROR = 'ERROR';
    public const WARNING = 'WARNING';
    public const INFO = 'INFO';
    public const DEBUG = 'DEBUG';

    private const LOG_LEVELS = [
        self::ERROR,
        self::WARNING,
        self::INFO,
        self::DEBUG
    ];

    private function __construct() {
        $this->initializeLogger();
    }

    private function initializeLogger(): void {
        // Check constants for configuration
        $this->fileLoggingEnabled = defined('LC_MIGRATOR_ENABLE_LOGGING') 
            ? LC_MIGRATOR_ENABLE_LOGGING 
            : false;

        $this->wpDebugEnabled = defined('LC_MIGRATOR_ENABLE_WP_DEBUG') 
            ? LC_MIGRATOR_ENABLE_WP_DEBUG 
            : true;

        $this->logInfoLogs = defined('LOGGER_LOG_INFO_LOGS') 
        ? LOGGER_LOG_INFO_LOGS
        : true;
        // Set log file path from constant or default
        $this->logFile = defined('LC_MIGRATOR_LOG_PATH')
            ? LC_MIGRATOR_LOG_PATH
            : dirname(__DIR__) . '/logs/plugin.log';
        
        

        if ($this->fileLoggingEnabled) {
            $this->initializeLogFile();
        }
    }

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

    private function initializeLogFile(): void {
        $logDir = dirname($this->logFile);
        
        if (!file_exists($logDir)) {
            wp_mkdir_p($logDir);
        }

        if (!file_exists($this->logFile)) {
            touch($this->logFile);
            chmod($this->logFile, 0644);
        }
    }

    private function writeToWPDebug(string $message, string $level): void {
        if (!$this->wpDebugEnabled || !WP_DEBUG) {
            return;
        }

        $debugMessage = "[" . $level . "] " . $message;

        if (defined('WP_DEBUG_LOG') && WP_DEBUG_LOG) {
            error_log($debugMessage);
        }

        if (defined('WP_DEBUG_DISPLAY') && WP_DEBUG_DISPLAY) {
            // Only display non-debug messages in admin
            if ($level !== self::DEBUG || is_admin()) {
                echo '<div style="color: ' . esc_attr($this->getColorForLevel($level)) . ';">' 
                    . esc_html($debugMessage) . '</div>';
            }
        }
    }

    private function getColorForLevel(string $level): string {
        switch ($level) {
            case self::ERROR:
                return '#dc3545';
            case self::WARNING:
                return '#ffc107';
            case self::INFO:
                return '#17a2b8';
            case self::DEBUG:
                return '#6c757d';
            default:
                return '#000000';
        }
    }

    public function log(string $message, string $level = self::INFO): void {
        if (!in_array($level, self::LOG_LEVELS)) {
            return;
        }

        // Write to file if enabled
        if ($this->fileLoggingEnabled) {
            $timestamp = date('Y-m-d H:i:s');
            $formattedMessage = sprintf(
                "[%s] [%s] %s%s",
                $timestamp,
                str_pad($level, 7, ' ', STR_PAD_RIGHT),
                $message,
                PHP_EOL
            );

            file_put_contents(
                $this->logFile,
                $formattedMessage,
                FILE_APPEND | LOCK_EX
            );
        }

        // Write to WP Debug if enabled
        $this->writeToWPDebug($message, $level);
    }

    public function error(string $message): void {
        $this->log($message, self::ERROR);
    }

    public function warning(string $message): void {
        $this->log($message, self::WARNING);
    }

    public function info(string $message): void {
        if(LC_MIGRATOR_ENABLE_LOGGING){
            $this->log($message, self::INFO);
        }
    }

    public function debug(string $message): void {
        $this->log($message, self::DEBUG);
    }

    public function logException(\Throwable $exception): void {
        $message = sprintf(
            "Exception: %s\nFile: %s\nLine: %d\nTrace:\n%s",
            $exception->getMessage(),
            $exception->getFile(),
            $exception->getLine(),
            $exception->getTraceAsString()
        );
        
        $this->error($message);
    }

    public function getLastLines(int $lines = 10): array {
        if (!$this->fileLoggingEnabled || !file_exists($this->logFile)) {
            return [];
        }

        $file = new \SplFileObject($this->logFile, 'r');
        $file->seek(PHP_INT_MAX);
        $totalLines = $file->key();

        $result = [];
        $start = max(0, $totalLines - $lines);

        $file->seek($start);
        while (!$file->eof()) {
            $line = $file->current();
            if (trim($line) !== '') {
                $result[] = $line;
            }
            $file->next();
        }

        return $result;
    }

    public function clear(): bool {
        if (!$this->fileLoggingEnabled) {
            return false;
        }
        return (bool) file_put_contents($this->logFile, '');
    }
}
