<?php

declare(strict_types=1);

namespace Meibuyu\Micro\Amqp\Producer;

use Exception;
use Hyperf\Amqp\Annotation\Producer;
use Hyperf\Amqp\Message\ProducerMessage;
use Meibuyu\Micro\Exceptions\HttpResponseException;
use Meibuyu\Micro\Model\Auth;

/**
 * @Producer(exchange="micro", routingKey="exception-log")
 */
class ExceptionLogProducer extends ProducerMessage
{

    public function __construct($data)
    {
        try {
            $data['operator'] = Auth::user()['name'];
        } catch (HttpResponseException $e) {
            put_log('获取操作人失败; ' . $e->getMessage(), 'ExceptionLogProducer.log');
        }
        // 获取trace中真实文件和行数
        if (!empty($data['trace'])) {
            preg_match('/(\/var\/www\/app\/.+?\.php)(?=\()/', $data['trace'], $matchFiles);
            if (!empty($matchFiles[0])) {
                $data['file'] = $matchFiles[0];
                $file = str_replace('/', '\/', $matchFiles[0]);
                $file = str_replace('.', '\.', $file);
                $pattern = '/(?<=' . $file . '\()[0-9]+(?=\))/';
                preg_match($pattern, $data['trace'], $matchLines);
                if (!empty($matchLines[0])) {
                    $data['line'] = $matchLines[0];
                }
            }
        }
        if (!empty($data['file'])) {
            // 只对项目app文件夹下的错误获取编码人
            preg_match('/(\/var\/www\/app\/)/', $data['file'], $matchPaths);
            if (!empty($matchPaths[0])) {
                try {
                    exec("cd {$matchPaths[0]} && git blame -L {$data['line']},{$data['line']} {$data['file']}", $output);
                    if (!empty($output[0]) && is_string($output[0])) {
                        preg_match('/(?<=\()[^ ]+/', $output[0], $matchCoders);
                        if (!empty($matchCoders[0])) {
                            $data['coder'] = $matchCoders[0];
                        }
                    }
                } catch (Exception $e) {
                    put_log('获取编码人失败; ' . $e->getMessage(), 'ExceptionLogProducer.log');
                }
            }
        }
        $this->payload = $data;
    }

}