<?php

namespace App\Http\Controllers;

use App\Models\ApiRequestLog;
use App\Models\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;
use Illuminate\View\View;

class ApiLogController extends Controller
{
    /**
     * API 로그 목록 화면
     */
    public function index(Request $request): View
    {
        $query = ApiRequestLog::query()
            ->with(['tenant', 'user'])
            ->orderByDesc('created_at');  // 항상 최신순

        // 필터: HTTP 메서드 (다중 선택 가능)
        if ($request->filled('method')) {
            $methods = $request->input('method');
            if (is_array($methods)) {
                $query->whereIn('method', $methods);
            } else {
                $query->where('method', $methods);
            }
        }

        // 필터: 상태 코드
        if ($request->filled('status')) {
            $status = $request->status;
            if ($status === '2xx') {
                $query->whereBetween('response_status', [200, 299]);
            } elseif ($status === 'error') {
                $query->where('response_status', '>=', 400);
            } elseif ($status === '4xx') {
                $query->whereBetween('response_status', [400, 499]);
            } elseif ($status === '5xx') {
                $query->whereBetween('response_status', [500, 599]);
            }
        }

        // 필터: URL 검색
        if ($request->filled('search')) {
            $query->where('url', 'like', '%'.$request->search.'%');
        }

        // 필터: 그룹 ID
        if ($request->filled('group_id')) {
            $query->where('group_id', $request->group_id);
        }

        // 필터: 테넌트
        if ($request->filled('tenant_id')) {
            $query->where('tenant_id', $request->tenant_id);
        }

        // 통계
        $stats = [
            'total' => ApiRequestLog::count(),
            'success' => ApiRequestLog::whereBetween('response_status', [200, 299])->count(),
            'client_error' => ApiRequestLog::whereBetween('response_status', [400, 499])->count(),
            'server_error' => ApiRequestLog::whereBetween('response_status', [500, 599])->count(),
            'avg_duration' => (int) ApiRequestLog::avg('duration_ms'),
        ];

        $logs = $query->paginate(50)->withQueryString();

        // 현재 페이지 로그들의 그룹별 개수 조회
        $groupIds = $logs->pluck('group_id')->filter()->unique()->values()->toArray();
        $groupCounts = [];
        if (! empty($groupIds)) {
            $groupCounts = ApiRequestLog::whereIn('group_id', $groupIds)
                ->selectRaw('group_id, COUNT(*) as count')
                ->groupBy('group_id')
                ->pluck('count', 'group_id')
                ->toArray();
        }

        // 세션에 저장된 토큰 정보 (API Explorer와 공유)
        $savedToken = session('api_explorer_token');
        $savedUserId = session('api_explorer_user_id');

        return view('api-logs.index', compact('logs', 'stats', 'groupCounts', 'savedToken', 'savedUserId'));
    }

    /**
     * API 로그 상세 화면
     */
    public function show(int $id): View
    {
        $log = ApiRequestLog::with(['tenant', 'user'])->findOrFail($id);

        // 같은 그룹의 다른 요청들 (오래된 순)
        $groupLogs = collect();
        $groupMethodCounts = [];
        if ($log->group_id) {
            $groupLogs = ApiRequestLog::where('group_id', $log->group_id)
                ->where('id', '!=', $log->id)
                ->orderBy('created_at')  // 오래된 순
                ->get();

            // 메서드별 개수 집계
            $groupMethodCounts = $groupLogs->groupBy('method')
                ->map(fn ($items) => $items->count())
                ->sortKeys()
                ->toArray();
        }

        // 세션에 저장된 토큰 정보 (API Explorer와 공유)
        $savedToken = session('api_explorer_token');
        $savedUserId = session('api_explorer_user_id');

        return view('api-logs.show', compact('log', 'groupLogs', 'groupMethodCounts', 'savedToken', 'savedUserId'));
    }

    /**
     * 오래된 로그 삭제 (수동)
     */
    public function prune()
    {
        $deleted = ApiRequestLog::pruneOldLogs();

        return redirect()->route('dev-tools.api-logs.index')
            ->with('success', "{$deleted}개의 로그가 삭제되었습니다.");
    }

    /**
     * 모든 로그 삭제
     */
    public function truncate()
    {
        $deleted = ApiRequestLog::truncate();

        return redirect()->route('dev-tools.api-logs.index')
            ->with('success', '모든 로그가 삭제되었습니다.');
    }

    /**
     * API 로그 재전송
     */
    public function resend(Request $request, int $id): JsonResponse
    {
        $log = ApiRequestLog::findOrFail($id);

        // URL 변환: api.sam.kr → API_BASE_URL (환경별 설정)
        $url = $this->convertApiUrl($log->url);

        // 인증 토큰 결정 (API Explorer와 공유)
        $token = null;
        if ($request->filled('token')) {
            // 직접 입력한 토큰 사용
            $token = $request->input('token');
            // 세션에 저장 (다음 재전송 시 재사용)
            session(['api_explorer_token' => $token]);
        } elseif ($request->filled('user_id')) {
            // 사용자 선택 시 Sanctum 토큰 발급
            $user = User::findOrFail($request->input('user_id'));
            $token = $user->createToken('api-log-resend', ['*'])->plainTextToken;
            // 세션에 저장 (다음 재전송 시 재사용)
            session(['api_explorer_token' => $token]);
            session(['api_explorer_user_id' => $user->id]);
        } elseif (session('api_explorer_token')) {
            // 세션에 저장된 토큰 사용
            $token = session('api_explorer_token');
        }

        // HTTP 요청 빌더 생성
        $httpClient = Http::timeout(30);

        // Authorization 헤더 설정
        if ($token) {
            $httpClient = $httpClient->withToken($token);
        }

        // Content-Type 설정 (원본 헤더에서 추출)
        $contentType = 'application/json';
        if (isset($log->request_headers['content-type'])) {
            $contentType = is_array($log->request_headers['content-type'])
                ? $log->request_headers['content-type'][0]
                : $log->request_headers['content-type'];
        }
        $httpClient = $httpClient->contentType($contentType);

        // Accept 헤더 설정
        $httpClient = $httpClient->accept('application/json');

        // X-API-KEY 헤더 설정 (.env에서 가져옴)
        $apiKey = config('services.api.key');
        if ($apiKey) {
            $httpClient = $httpClient->withHeaders(['X-API-KEY' => $apiKey]);
        }

        // 요청 실행 및 시간 측정
        $startTime = microtime(true);

        try {
            $response = match (strtoupper($log->method)) {
                'GET' => $httpClient->get($url, $log->request_query ?? []),
                'POST' => $httpClient->post($url, $log->request_body ?? []),
                'PUT' => $httpClient->put($url, $log->request_body ?? []),
                'PATCH' => $httpClient->patch($url, $log->request_body ?? []),
                'DELETE' => $httpClient->delete($url, $log->request_body ?? []),
                default => throw new \InvalidArgumentException("Unsupported HTTP method: {$log->method}"),
            };

            $durationMs = (int) ((microtime(true) - $startTime) * 1000);

            // 응답 파싱
            $responseBody = $response->json() ?? $response->body();

            return response()->json([
                'success' => $response->successful(),
                'status' => $response->status(),
                'duration_ms' => $durationMs,
                'response' => $responseBody,
            ]);
        } catch (\Exception $e) {
            $durationMs = (int) ((microtime(true) - $startTime) * 1000);

            return response()->json([
                'success' => false,
                'status' => 0,
                'duration_ms' => $durationMs,
                'response' => [
                    'error' => $e->getMessage(),
                    'type' => get_class($e),
                ],
            ], 500);
        }
    }

    /**
     * API URL 변환 (환경별 설정 적용)
     * 로그에 저장된 외부 URL을 현재 환경에서 접근 가능한 URL로 변환
     */
    private function convertApiUrl(string $originalUrl): string
    {
        $apiBaseUrl = config('services.api.base_url');

        if (empty($apiBaseUrl)) {
            return $originalUrl;
        }

        // 기존 API 도메인 패턴 (api.sam.kr, api.codebridge-x.com 등)
        $patterns = [
            '#^https?://api\.sam\.kr#',
            '#^https?://api\.codebridge-x\.com#',
        ];

        foreach ($patterns as $pattern) {
            if (preg_match($pattern, $originalUrl)) {
                return preg_replace($pattern, rtrim($apiBaseUrl, '/'), $originalUrl);
            }
        }

        return $originalUrl;
    }
}
