<?php

namespace App\Http\Middleware;

use App\Models\AdminActivityLog;
use App\Support\AdminActivityLogSupport;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Str;
use Symfony\Component\HttpFoundation\Response;

class LogAdminActivity
{
    public function handle(Request $request, Closure $next): Response
    {
        $response = $next($request);

        $admin = $request->user('admin');
        if (!$admin || !$this->tableAvailable()) {
            return $response;
        }

        $route = $request->route();
        if (!$route) {
            return $response;
        }

        if (!AdminActivityLog::shouldLogRequest($request->method(), $route->getName(), $request->path())) {
            return $response;
        }

        try {
            $requestPayload = AdminActivityLogSupport::buildRequestPayload($request);

            $queryPayload = AdminActivityLogSupport::sanitizePayload($request->query());

            AdminActivityLog::query()->create([
                'admin_id' => $admin->id,
                'admin_name' => (string) ($admin->name ?? ''),
                'admin_email' => (string) ($admin->email ?? ''),
                'method' => strtoupper((string) $request->method()),
                'route_name' => $route->getName(),
                'path' => '/' . ltrim((string) $request->path(), '/'),
                'full_url' => Str::limit((string) $request->fullUrl(), 5000, ''),
                'activity_summary' => $this->activitySummary($request, $route->getName()),
                'response_status' => (int) $response->getStatusCode(),
                'ip_address' => (string) ($request->ip() ?? ''),
                'user_agent' => Str::limit((string) ($request->userAgent() ?? ''), 2000, ''),
                'query_payload' => $queryPayload !== [] ? $queryPayload : null,
                'request_payload' => $requestPayload !== [] ? $requestPayload : null,
            ]);
        } catch (\Throwable) {
            // Activity logging should never block admin work.
        }

        return $response;
    }

    private function tableAvailable(): bool
    {
        static $exists = null;

        if ($exists !== null) {
            return $exists;
        }

        try {
            $exists = Schema::hasTable('admin_activity_logs');
        } catch (\Throwable) {
            $exists = false;
        }

        return $exists;
    }

    private function activitySummary(Request $request, ?string $routeName): string
    {
        $method = strtoupper((string) $request->method());
        $normalizedRouteName = strtolower((string) ($routeName ?? ''));
        $verb = match (true) {
            $method === 'GET' && str_contains($normalizedRouteName, '.export') => 'Exported',
            $method === 'GET' && str_contains($normalizedRouteName, '.toggle') => 'Toggled',
            $method === 'GET' && str_contains($normalizedRouteName, '.change-status') => 'Changed',
            $method === 'GET' && str_contains($normalizedRouteName, '.login') => 'Logged In',
            $method === 'POST' => 'Submitted',
            in_array($method, ['PUT', 'PATCH'], true) => 'Updated',
            $method === 'DELETE' => 'Deleted',
            default => 'Performed',
        };

        $label = $routeName ?: (string) $request->path();
        $label = str_replace(['admin.', '.', '_', '-'], [' ', ' ', ' ', ' '], $label);
        $label = preg_replace('/\s+/', ' ', $label) ?: '';
        $label = trim($label);

        if ($label === '') {
            $label = 'Admin Page';
        }

        return $verb . ' ' . Str::title($label);
    }
}
