<?php

namespace App\Http\Middleware;

use App\Models\OperationLog as OperationLogModel;
use Closure;
use Illuminate\Http\Request;

class RecordOperationLog
{
    protected array $ignorePaths = [
        'api/admin/auth/login',
        'api/admin/auth/refresh',
        'api/admin/operation-logs/destroy',
        'api/admin/operation-logs/clear',
    ];

    public function handle(Request $request, Closure $next)
    {
        $response = $next($request);

        if (! $this->shouldLog($request)) {
            return $response;
        }

        try {
            OperationLogModel::create([
                'user_id' => $request->user()?->id,
                'module' => $this->getModule($request),
                'action' => $this->getAction($request),
                'method' => $request->method(),
                'path' => $request->path(),
                'params' => $this->filterParams($request),
                'ip' => $request->ip(),
                'user_agent' => $request->userAgent(),
                'status' => $response->getStatusCode() < 400 ? 1 : 0,
                'error_message' => $response->getStatusCode() >= 400 ? $this->getErrorMessage($response) : null,
            ]);
        } catch (\Throwable) {
        }

        return $response;
    }

    protected function shouldLog(Request $request): bool
    {
        if (! in_array($request->method(), ['POST', 'PUT', 'PATCH', 'DELETE'])) {
            return false;
        }

        return ! in_array($request->path(), $this->ignorePaths);
    }

    protected function getModule(Request $request): string
    {
        $path = $request->path();
        $parts = explode('/', $path);

        return $parts[2] ?? 'unknown';
    }

    protected function getAction(Request $request): string
    {
        $route = $request->route();

        return $route?->getActionMethod() ?? 'unknown';
    }

    protected function filterParams(Request $request): array
    {
        $params = $request->except(['password', 'old_password', 'new_password', 'confirm_password']);

        return array_slice($params, 0, 50);
    }

    protected function getErrorMessage($response): ?string
    {
        try {
            $content = json_decode($response->getContent(), true);

            return $content['message'] ?? null;
        } catch (\Throwable) {
            return null;
        }
    }
}
