<?php

namespace App\Services;

use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;

class FormulaApiService
{
    /**
     * API 서버의 FormulaEvaluatorService를 HTTP로 호출하여 BOM 산출
     *
     * Docker 내부 통신 패턴:
     * - URL: https://nginx/api/v1/quotes/calculate/bom (Docker nginx 컨테이너)
     * - Host 헤더: api.sam.kr (nginx가 올바른 서버 블록으로 라우팅)
     * - SSL 우회: withoutVerifying() (내부 자체 서명 인증서)
     * - 인증: X-API-KEY + Bearer token (ApiTokenService 토큰 교환)
     *
     * @param  string  $finishedGoodsCode  완제품 코드 (예: FG-KQTS01)
     * @param  array  $variables  입력 변수 ['W0' => 3000, 'H0' => 3000, 'QTY' => 1]
     * @param  int  $tenantId  테넌트 ID
     * @return array 성공 시 API 응답, 실패 시 ['success' => false, 'error' => '...']
     */
    public function calculateBom(string $finishedGoodsCode, array $variables, int $tenantId): array
    {
        try {
            $apiKey = config('api-explorer.default_environments.0.api_key')
                   ?: env('FLOW_TESTER_API_KEY', '');

            // Bearer token: ApiTokenService로 세션 토큰 확인, 만료 시 재발급
            $bearerToken = $this->resolveApiToken($tenantId);

            $headers = [
                'Host' => 'api.sam.kr',
                'Accept' => 'application/json',
                'Content-Type' => 'application/json',
                'X-API-KEY' => $apiKey,
                'X-TENANT-ID' => (string) $tenantId,
            ];

            $http = Http::timeout(30)->withoutVerifying()->withHeaders($headers);

            if ($bearerToken) {
                $http = $http->withToken($bearerToken);
            }

            // API의 QuoteBomCalculateRequest는 W0, H0, QTY 등을 최상위 레벨에서 기대
            $payload = array_merge(
                ['finished_goods_code' => $finishedGoodsCode],
                $variables  // W0, H0, QTY 등을 풀어서 전송
            );

            $response = $http->post('https://nginx/api/v1/quotes/calculate/bom', $payload);

            if ($response->successful()) {
                $json = $response->json();

                // ApiResponse::handle()는 {success, message, data} 구조로 래핑
                return $json['data'] ?? $json;
            }

            Log::warning('FormulaApiService: API 호출 실패', [
                'status' => $response->status(),
                'body' => $response->body(),
                'code' => $finishedGoodsCode,
            ]);

            return [
                'success' => false,
                'error' => 'API 응답 오류: HTTP '.$response->status(),
            ];
        } catch (\Exception $e) {
            Log::error('FormulaApiService: 예외 발생', [
                'message' => $e->getMessage(),
                'code' => $finishedGoodsCode,
            ]);

            return [
                'success' => false,
                'error' => '수식 계산 서버 연결 실패: '.$e->getMessage(),
            ];
        }
    }

    /**
     * API Bearer token 확보 (세션 토큰 → 만료/미존재 시 재발급)
     */
    private function resolveApiToken(int $tenantId): ?string
    {
        $tokenService = new ApiTokenService;

        // 세션에 유효한 토큰이 있으면 사용
        if (! $tokenService->isTokenExpired()) {
            return $tokenService->getSessionToken();
        }

        // 토큰 만료 또는 미존재 → 교환 시도
        $userId = auth()->id();
        if (! $userId) {
            Log::warning('[FormulaApiService] 인증된 사용자 없음 - API 토큰 교환 불가');

            return null;
        }

        $result = $tokenService->exchangeToken($userId, $tenantId);
        if ($result['success']) {
            $tokenService->storeTokenInSession(
                $result['data']['access_token'],
                $result['data']['expires_in']
            );

            return $result['data']['access_token'];
        }

        Log::warning('[FormulaApiService] API 토큰 교환 실패', [
            'error' => $result['error'] ?? '',
        ]);

        return null;
    }
}
