<?php

namespace Mainto\RpcServer\RpcUtil\Tool\LogDriver;


use Mainto\RpcServer\Protocol\Request\Request;
use Throwable;

class Local extends LogDriveAbstract {
    /**
     * send message to aliyun log service
     *
     * @param $source
     * @param $logStore
     * @param $contents
     */
    private function send (string $source, string $logStore, $contents) {
        $content = sprintf("[%s] %s: %s\n", date('Y-m-d H:i:s'), $source, $this->transObject($contents));
        @file_put_contents(storage_path("logs/rpc_log_{$logStore}.log"), $content, FILE_APPEND);
    }

    public function logThrowable ($request, Throwable $e, string $source = "") {
        if ($source == "") {
            $traceInfo = $this->getTraceInfo(-1);
            $source = $traceInfo['source'];
        }

        $traceStr = "\n";
        foreach (explode("\n", $e->getTraceAsString()) as $key => $value) {
            $traceStr .= $value."\n";
            if (strpos($value, 'php-rpc-framework/src/RpcServer/RpcInvoke.php') !== false
                && strpos($value, 'ReflectionMethod->invokeArgs()') !== false) {
                $traceStr .= "[framework trace]";
                break;
            }
        }

        $this->send($source, "error", [
            "request"       => $this->transObject($request),
            "error_name"    => class_basename($e),
            "error_code"    => $e->getCode(),
            "error_content" => $e->getMessage(),
            "error_file"    => $e->getFile(),
            "error_line"    => $e->getLine(),
            "error_trace"   => $traceStr,
        ]);
    }

    /**
     * log throwable error log
     *
     * @param $request
     * @param $source
     * @param Throwable $e
     */
    public function logRequestThrowable (Request $request, Throwable $e, string $source = "") {
        if ($source == "") {
            $traceInfo = $this->getTraceInfo(-1);
            $source = $traceInfo['source'];
        }

        $traceStr = "\n";
        foreach (explode("\n", $e->getTraceAsString()) as $key => $value) {
            $traceStr .= $value."\n";
            if (strpos($value, 'php-rpc-framework/src/RpcServer/RpcInvoke.php') !== false
                && strpos($value, 'ReflectionMethod->invokeArgs()') !== false) {
                $traceStr .= "[framework trace]";
                break;
            }
        }

        $this->send($source, "error", [
            "header"        => $request->getAllHeaders(),
            "request"       => $request->getAllParams(),
            "error_name"    => class_basename($e),
            "error_code"    => $e->getCode(),
            "error_content" => $e->getMessage(),
            "error_file"    => $e->getFile(),
            "error_line"    => $e->getLine(),
            "error_trace"   => $traceStr,
        ]);
    }

    /**
     * log info message
     *
     * @param $title
     * @param $message
     */
    public function info (string $title, $message) {
        $this->log("INFO", $title, $message);
    }

    /**
     * log some messgae
     *
     * @param string $level
     * @param string $title
     * @param $message
     */
    protected function log (string $level, string $title, $message) {
        $traceInfo = $this->getTraceInfo();
        $this->send($traceInfo['source'], "log", [
            "offset"  => $traceInfo['file'],
            "level"   => $level,
            "title"   => $title,
            "content" => $message,
        ]);
    }

    /**
     * log debug message
     *
     * @param $title
     * @param $message
     */
    public function debug (string $title, $message) {
        $this->log("DEBU", $title, $message);
    }

    /**
     * log notice message
     *
     * @param $title
     * @param $message
     */
    public function notice (string $title, $message) {
        $this->log("NOTI", $title, $message);
    }

    /**
     * log warning message
     *
     * @param $title
     * @param $message
     */
    public function warning (string $title, $message) {
        $this->log("WARN", $title, $message);
    }

    /**
     * log error message
     *
     * @param $source
     * @param $title
     * @param $message
     */
    public function error (string $title, $message) {
        $this->log("ERRO", $title, $message);
    }

    /**
     * log critical message
     *
     * @param $title
     * @param $message
     */
    public function critical (string $title, $message) {
        $this->log("CRIT", $title, $message);
    }
}