<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
use Illuminate\Http\Request;
use App\Helpers\AuditSanitizer;
use App\Jobs\ProcessAuditLog;
use Illuminate\Support\Facades\Session;
use App\Helpers\TinyRedis; 

class LogAuditActivity
{
    public function handle($request, Closure $next)
    {
        // Capture start time for latency calculation
        $request->attributes->set('audit_start_time', microtime(true));

        return $next($request);
    }

    public function terminate($request, $response)
    {

        if (_env('CENTRALIZED_AUDIT_LOG_ENABLED', true) == false) {
                return;
            }

        // 1. Filter: Only log POST requests
        if ($request->method() === 'GET') {
            return;
        }

        try {
            // 2. Determine Stream Segregation
            $streamName = $this->determineStreamName($request);

            // 3. Calculate Latency
            $startTime = $request->attributes->get('audit_start_time', microtime(true));
            $latencyMs = (microtime(true) - $startTime) * 1000;

            $responseBody = null;

            // 1. Check if response is a file download (Binary) to avoid memory crashes
            if ($response instanceof \Symfony\Component\HttpFoundation\BinaryFileResponse) {
                $responseBody = '[Binary File Download]';
            } 
            // 2. Otherwise, get content
            else {
                $content = $response->getContent();
                
                // Try to decode JSON so CloudWatch indexes the fields
                $decoded = json_decode($content, true);
                
                if (json_last_error() === JSON_ERROR_NONE && is_array($decoded)) {
                    $responseBody = AuditSanitizer::clean($decoded); 
                } else {
                    $responseBody = substr($content, 0, 1000) . (strlen($content) > 1000 ? '...' : '');
                }
            }

            // 4. Capture Context & Payload
            $payload = [
                'request_id'  => uniqid('req_', true),
                'source'      => $this->determineSource($request),
                'user_id'     => Auth::check() ? Auth::id() : null,
                'status_code' => $response->getStatusCode(),
                'latency_ms'  => round($latencyMs, 2),
                'ip'          => $request->ip(),
                'url'         => $request->fullUrl(),
                'method'      => $request->method(),
                'user_agent'  => $request->header('User-Agent'),
                'stream'      => $streamName,
                'permissions' => Session::get('permissions'),
                'request_body'  => AuditSanitizer::clean($request->input()), 
                'response_body' => $responseBody, 
            ];

            $redis = new TinyRedis(
                _env('REDIS_HOST', '127.0.0.1'),
                _env('REDIS_PORT', 6379)
            );

            //dispatch(new ProcessAuditLog('HTTP Audit', $payload));
            $redis->lpush('audit_queue', json_encode($payload));

        } catch (\Exception $e) {
            Log::error('Audit Middleware Failure: ' . $e->getMessage(), [
                'trace' => $e->getTraceAsString()
            ]);
        }
    }

    protected function determineStreamName(Request $request)
    {
        // $action = $request->route() ? $request->route()->getActionName() : '';
        // $path = $request->path();

        // // 1. Vendor APIs (vendor_apis.php)
        // // Matches namespace "Vendors\VendorController"
        // if (strpos($action, 'Vendors\\') !== false) {
        //     return 'vendor-audit-logs';
        // }

        // // 2. Consumer App (consumer.php)
        // // Matches namespace "ConsumerAPI\..."
        // if (strpos($action, 'ConsumerAPI\\') !== false) {
        //     return 'consumer-audit-logs';
        // }

        // // 3. Merchant PWA (pwa.php)
        // // Matches "MerchantApiController"
        // if (strpos($action, 'MerchantApiController') !== false) {
        //     return 'merchant-pwa-audit-logs';
        // }

        // // 4. Admin Panel
        // // Matches path "admin/*" or namespace "Admin\..."
        // if ($request->is('admin/*') || strpos($action, 'Admin\\') !== false) {
        //     return 'admin-audit-logs';
        // }

        // // 5. General API (api.php)
        // // Matches "ApiController" or paths starting with "api/"
        // // We put this after Consumer/Merchant to avoid overlap if those inherit from ApiController
        // if (strpos($action, 'ApiController') !== false || $request->is('api/*')) {
        //     return 'general-api-audit-logs';
        // }

        // // 6. Web / Frontend (web.php)
        // // Matches "FrontController", "ConsentController" or anything else
        // return 'web-audit-logs';
        return _env('CLOUDWATCH_CENTRAL_STREAM', 'centralized-admin-audit-logs');
    }

    protected function determineSource(Request $request)
    {
        // 1. Check strict Origin header (Standard for CORS)
        $origin = $request->header('Origin');
        if (!empty($origin)) {
            return $origin;
        }

        // 2. Check Referer
        $referer = $request->header('Referer');
        if (!empty($referer)) {
            // Strip scheme (http://) to keep it clean
            return parse_url($referer, PHP_URL_HOST) ?: $referer;
        }

        // 4. Fallback to parsing User Agent simply
        $ua = $request->header('User-Agent');
        if (stripos($ua, 'Postman') !== false) {
            return 'Postman';
        }
        if (stripos($ua, 'Android') !== false) {
            return 'Android App';
        }
        if (stripos($ua, 'iOS') !== false || stripos($ua, 'iPhone') !== false) {
            return 'iOS App';
        }

        return 'unknown-client';
    }
}