<?php

namespace App\Http\Middleware;

use App\Models\Members\User;
use Closure;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Laravel\Sanctum\PersonalAccessToken;

class ApiKeyMiddleware
{
    public function handle(Request $request, Closure $next)
    {
        // 화이트리스트(인증 예외 라우트) - API Key 검증 제외
        $publicRoutes = [
            '/',                 // Root (Swagger redirect)
            'api/v1/signup',
            'api/v1/register',
            'api/v1/refresh',
            'api/v1/debug-apikey',
            'api/v1/internal/*', // 내부 서버간 통신 (HMAC 인증 사용)
            'api-docs',          // Swagger UI
            'api-docs/*',        // Swagger 하위 경로
            'docs',              // L5-Swagger UI
            'docs/*',            // L5-Swagger 하위 경로 (에셋 등)
            'docs/api-docs.json', // Swagger JSON
            'up',                // Health check
        ];

        $currentRoute = $request->route()?->uri() ?? $request->path();

        // 화이트리스트 패턴 매칭 (와일드카드 지원)
        $isPublicRoute = false;
        foreach ($publicRoutes as $pattern) {
            if ($pattern === $currentRoute || fnmatch($pattern, $currentRoute)) {
                $isPublicRoute = true;
                break;
            }
        }

        // 공개 라우트가 아닌 경우에만 요청 정보 로깅
        if (! $isPublicRoute) {
            Log::info('API Request', [
                'ip' => $request->ip(),
                'user_id' => optional($request->user())->id,
                'method' => $request->method(),
                'uri' => $request->getRequestUri(),
                'input' => $request->except(['password', 'password_confirmation']), // 민감 정보 제외
                'user_agent' => $request->userAgent(),
                'headers' => [
                    'X-API-KEY' => $request->header('X-API-KEY') ? '***' : null,
                    'Authorization' => $request->bearerToken() ? 'Bearer ***' : null,
                    'Accept' => $request->header('Accept'),
                    'Content-Type' => $request->header('Content-Type'),
                ],
            ]);
        }

        // 공개 라우트는 API Key 검증 스킵
        if ($isPublicRoute) {
            return $next($request);
        }

        // API Key 검증
        $apiKey = $request->header('X-API-KEY');
        $validApiKey = false;

        if ($apiKey) {
            $validApiKey = DB::table('api_keys')
                ->where('key', $apiKey)
                ->where('is_active', true)
                ->exists();
        }

        if (! $validApiKey) {
            // 보안 로그 기록 (API Key 없이 접근 시도)
            Log::warning('Unauthorized API access attempt', [
                'ip' => $request->ip(),
                'uri' => $request->getRequestUri(),
                'method' => $request->method(),
                'user_agent' => $request->userAgent(),
            ]);

            return response()->json(['message' => 'Unauthorized. Invalid or missing API key'], 401);
        }

        // Bearer 인증 (Sanctum)
        $user = [];
        if ($token = $request->bearerToken()) {
            $accessToken = PersonalAccessToken::findToken($token);
            if ($accessToken && $accessToken->tokenable instanceof User) {
                $user = $accessToken->tokenable;

                if ($user) {
                    // 기본 테넌트(여러개 소속시 활성화 테넌트)
                    $tenantId = $user->userTenants
                        ->where('is_default', 1)
                        ->first()?->tenant_id
                        ?? $user->userTenants->first()?->tenant_id;

                    $tenantId = $tenantId ?? 0;

                    // tenant_id 설정
                    $request->attributes->set('tenant_id', $tenantId);
                    app()->instance('tenant_id', $tenantId);

                    // user_id 설정
                    $request->attributes->set('api_user', $user->id);
                    app()->instance('api_user', $user->id);
                }
            }
        }

        // 화이트리스트(인증 예외 라우트) - Bearer 토큰 없이 접근 가능
        $allowWithoutAuth = [
            'api/v1/login',
            'api/v1/signup',
            'api/v1/register',
            'api/v1/refresh',
            'api/v1/debug-apikey',
            'api/v1/internal/exchange-token', // 내부 서버간 토큰 교환 (HMAC 인증 사용)
            'api/v1/admin/fcm/*',             // Admin FCM API (MNG에서 API Key만으로 접근)
            'api/v1/app/*',                   // 앱 버전 확인/다운로드 (API Key만 필요)
        ];

        // 현재 라우트 확인 (경로 또는 이름)
        $currentRoute = $request->route()?->uri() ?? $request->path();

        // 화이트리스트 패턴 매칭 (와일드카드 지원)
        $isAllowedWithoutAuth = false;
        foreach ($allowWithoutAuth as $pattern) {
            if ($pattern === $currentRoute || fnmatch($pattern, $currentRoute)) {
                $isAllowedWithoutAuth = true;
                break;
            }
        }

        if (! $isAllowedWithoutAuth) {
            // 인증정보(api_user, tenant_id) 없으면 튕김
            if (! app()->bound('api_user')) {
                throw new AuthenticationException('회원정보 정보 없음');
            }
        }

        $response = $next($request);

        // 응답 정보 저장
        Log::info('API Response', [
            'uri' => $request->getRequestUri(),
            'status' => $response->getStatusCode(),
            'content' => $response->getContent(), // 응답 body도 원하면!
        ]);

        return $response;
    }
}
