<?php

namespace platyFramework;

require_once __DIR__ . '/ptyCliColor.php';

class ptyCliLog
{
    // 하위 호환성을 위한 색상 상수 (ptyCliColor 사용 권장)
    const COLOR_WHITE = ptyCliColor::LIGHT_WHITE;
    const COLOR_RED = ptyCliColor::RED;
    const COLOR_GREEN = ptyCliColor::GREEN;
    const COLOR_YELLOW = ptyCliColor::YELLOW;
    const COLOR_BLUE = ptyCliColor::BLUE;
    const COLOR_MAGENTA = ptyCliColor::MAGENTA;
    const COLOR_CYAN = ptyCliColor::CYAN;
    const COLOR_RESET = ptyCliColor::RESET;

    private $prefix;
    private $color;
    private $debug;
    private $colors;

    public function __construct($prefix = "APP", $color = ptyCliColor::LIGHT_WHITE, $debug = true)
    {
        $this->prefix = $prefix;
        $this->color = $color;
        $this->debug = $debug;
        $this->colors = [
            'info' => ptyCliColor::CYAN,
            'success' => ptyCliColor::GREEN,
            'warning' => ptyCliColor::YELLOW,
            'error' => ptyCliColor::RED,
            'url' => ptyCliColor::MAGENTA,
            'verbose' => ptyCliColor::DARK_WHITE,
            'data' => ptyCliColor::LIGHT_WHITE,
            'response' => ptyCliColor::CYAN,
            'reset' => ptyCliColor::RESET
        ];

        date_default_timezone_set('Asia/Seoul');

        if ($prefix != "URL" && $prefix != "ELASTIC") {
            $this->url = new ptyCliLog("URL", ptyCliColor::DARK_MAGENTA, $debug);
            $this->elastic = new ptyCliLog("URL", ptyCliColor::DARK_WHITE, $debug);
        }
    }

    public function log($message, $type = 'info', $data = null)
    {
        if (!$this->debug) return;

        if ($message == "") {
            echo "\n";
            return;
        }

        // 타임스탬프 생성 (밀리초 포함)
        $now = microtime(true);
        // $milliseconds = sprintf("%03d", ($now - floor($now)) * 1000);
        // $timestamp = date('Y-m-d H:i:s', (int)$now) . '.' . $milliseconds;
        $timestamp = date('H:i:s', (int)$now);

        $typeColor = $this->colors[$type] ?? $this->colors['info'];
        $reset = $this->colors['reset'];

        // verbose 타입일 때 호출한 함수명 추가
        $functionName = "";
        // if ($type === 'verbose') {
        if (true) {
            $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3);
            if (isset($backtrace[2])) {
                $caller = $backtrace[2];
                if (isset($caller['class'])) {
                    $functionName = $caller['class'] . $caller['type'] . $caller['function'];
                } else if (isset($caller['function'])) {
                    $functionName = $caller['function'];
                }

                if ($functionName) {
                    // closure인 경우 파일명:라인번호 형식으로 변환
                    if (preg_match('/\{closure:(.+):(\d+)\}/', $functionName, $matches)) {
                        $filePath = $matches[1];
                        $lineNumber = $matches[2];
                        $fileName = basename($filePath);
                        $functionName = $fileName . ':' . $lineNumber;
                    }
                    else {
                        $functionName.= "()";

                    }

                    $functionName = ptyCliColor::DARK_WHITE . $functionName . " ". $reset;
                }
            }
        }

        // 타임스탬프 + prefix에 지정된 색상 사용, type은 타입 색상 사용
        echo ptyCliColor::DARK_WHITE . $timestamp . " " . $reset;
        echo sprintf("%-45s", $functionName);
        echo $this->color . sprintf("[%-8s] ", strtoupper($this->prefix)) . $reset;
        echo $typeColor . $message . $reset . "\n";

        if ($data !== null) {
            echo $this->colors['data'] . json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) . $reset . "\n";
        }
    }

    public function verbose($message, $data = null)
    {
        $this->log($message, 'verbose', $data);
    }

    public function info($message, $data = null)
    {
        $this->log($message, 'info', $data);
    }

    public function success($message, $data = null)
    {
        $this->log($message, 'success', $data);
    }

    public function warning($message, $data = null)
    {
        $this->log($message, 'warning', $data);
    }

    public function error($message, $data = null)
    {
        $this->log($message, 'error', $data);
    }

    public function url($message, $data = null)
    {
        $this->log($message, 'url', $data);
    }

    public function mysql($message, $data = null)
    {
        $this->log($message, 'mysql', $data);
    }

    public function elastic($message, $data = null)
    {
        $this->log($message, 'elastic', $data);
    }

    public function data($message, $data = null)
    {
        $this->log($message, 'data', $data);
    }

    public function response($message, $data = null)
    {
        $this->log($message, 'response', $data);
    }

    public function setDebug($debug)
    {
        $this->debug = $debug;
        $this->log("디버그 모드 " . ($debug ? "활성화" : "비활성화"), 'info');
    }

    public function isDebugEnabled()
    {
        return $this->debug;
    }

    public function separator($length = 50)
    {
        $this->log("\n".str_repeat("=", $length), 'info');
    }
}

/**
 * ptyCliLog 헬퍼 함수
 *
 * @param string $prefix 로그 prefix (기본값: "APP")
 * @param string $color 로그 색상 (기본값: ptyCliLog::COLOR_WHITE)
 * @param bool $debug 디버그 모드 (기본값: true)
 * @return ptyCliLog
 */
function ptyCliLog($prefix = "APP", $color = ptyCliLog::COLOR_WHITE, $debug = true)
{
    return new ptyCliLog($prefix, $color, $debug);
}