<?php

namespace App\Services;

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

class ApiService
{
    protected $baseUrl;
    protected $timeout;
    protected $token = null;

    public function __construct()
    {
        $this->baseUrl = config('app.siscon_api_url', env('SISCON_API_URL', 'http://localhost:8000/api'));
        $this->timeout = config('app.siscon_api_timeout', env('SISCON_API_TIMEOUT', 0));
        
        // Cargar token desde la sesión si existe
        if (session()->has('backoffice_token')) {
            $this->token = session('backoffice_token');
        }
    }

    /**
     * Función estructural para hacer peticiones HTTP con headers correctos y logging
     * 
     * @param string $method Método HTTP (GET, POST, PUT, DELETE, PATCH)
     * @param string $url URL completa o endpoint
     * @param array $data Datos para enviar (body)
     * @param array $params Parámetros de query string
     * @param string $logContext Contexto para logs (ej: 'regenerate_token', 'get_companies')
     * @return array
     */
    public function makeApiRequest(string $method, string $url, array $data = [], array $params = [], string $logContext = 'api_request'): array
    {
        try {
            // Preparar timeout
            $timeout = is_numeric($this->timeout) && $this->timeout > 0 ? (int) $this->timeout : 30;
            
            // Preparar URL completa si es necesario
            $fullUrl = str_starts_with($url, 'http') ? $url : $this->baseUrl . '/' . ltrim($url, '/');
            
            // Preparar headers base
            $headers = [
                'Content-Type' => 'application/json',
                'Accept' => 'application/json',
                'User-Agent' => 'SISCON-Backoffice/1.0',
            ];
            
            // Determinar qué token usar según el contexto
            if ($logContext === 'user_authenticate') {
                // Para login: usar token de API
                $apiToken = env('SISCON_API_TOKEN');
                if ($apiToken) {
                    $headers['Authorization'] = 'Bearer ' . $apiToken;
                }
            } else {
                // Para todas las demás requests: usar JWT token del usuario
                if ($this->token) {
                    $headers['Authorization'] = 'Bearer ' . $this->token;
                }
            }
            
            // Log de inicio de petición con información del token
            Log::channel('api')->info("API Request iniciada: {$method} {$fullUrl}", [
                'context' => $logContext,
                'data' => $data,
                'params' => $params,
                'url' => $fullUrl,
                'has_token' => !empty($this->token),
                'token_length' => $this->token ? strlen($this->token) : 0,
                'authorization_header' => isset($headers['Authorization']) ? 'Bearer [***]' : 'Not set'
            ]);
            
            // Preparar petición HTTP
            $http = Http::timeout($timeout)->withHeaders($headers);
            
            // Agregar parámetros de query si es GET o si se especifican
            if (!empty($params)) {
                $http = $http->withOptions(['query' => $params]);
            }

            // Realizar petición según el método
            $response = match(strtoupper($method)) {
                'GET' => $http->get($fullUrl),
                'POST' => $http->post($fullUrl, $data),
                'PUT' => $http->put($fullUrl, $data),
                'DELETE' => $http->delete($fullUrl),
                'PATCH' => $http->patch($fullUrl, $data),
                default => throw new \InvalidArgumentException("Método HTTP no soportado: {$method}")
            };

            // Log de respuesta exitosa
            if ($response->successful()) {
                Log::channel('api')->info("API Request exitosa: {$method} {$fullUrl}", [
                    'context' => $logContext,
                    'status' => $response->status(),
                    'response_body' => $response->body(),
                    'response_size' => strlen($response->body()),
                ]);

                return [
                    'success' => true,
                    'data' => $response->json(),
                    'status_code' => $response->status(),
                    'message' => 'Petición exitosa'
                ];
            } else {
                // Log de error HTTP
                Log::channel('api')->warning("API Request falló: {$method} {$fullUrl}", [
                    'context' => $logContext,
                    'status' => $response->status(),
                    'response_body' => $response->body()
                ]);

                return [
                    'success' => false,
                    'error' => 'Error en la API',
                    'status_code' => $response->status(),
                    'message' => 'La petición no fue exitosa',
                    'response_body' => $response->body()
                ];
            }

        } catch (\Exception $e) {
            // Log de excepción
            Log::channel('api')->error("API Request excepción: {$method} {$url}", [
                'context' => $logContext,
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
                'data' => $data,
                'params' => $params
            ]);

            return [
                'success' => false,
                'error' => $e->getMessage(),
                'message' => 'Error interno en la petición'
            ];
        }
    }

    /**
     * Regenerar token de primera vez para una empresa
     *
     * @param array $data
     * @return array
     */
    public function regenerateFirstToken(array $data = []): array
    {
        return $this->makeApiRequest('POST', api_url('access_requests.regenerate_first_token'), $data, [], 'regenerate_first_token');
    }

    /**
     * Obtener lista de empresas
     *
     * @param array $params
     * @return array
     */
    public function getCompaniesList(array $params = []): array
    {
        return $this->makeApiRequest('GET', '/backoffice/companies-list', [], $params, 'get_companies_list');
    }

    /**
     * Establecer token para autenticación
     *
     * @param string $token
     * @return void
     */
    public function setToken(string $token): void
    {
        $this->token = $token;
        // También guardarlo en la sesión para futuras peticiones
        session(['backoffice_token' => $token]);
    }

    /**
     * Validar token con la API
     *
     * @return bool
     */
    public function validateToken(): bool
    {
        if (!$this->token) {
            return false;
        }

        try {
            $response = $this->makeApiRequest('POST', api_url('auth.verify'), [
                'token' => $this->token
            ], [], 'validate_token');

            return $response['success'] && isset($response['data']['valid']) && $response['data']['valid'];
        } catch (\Exception $e) {
            Log::channel('api')->warning('Token validation error', ['error' => $e->getMessage()]);
            return false;
        }
    }

    /**
     * Obtener datos del usuario actual
     *
     * @return array|null
     */
    public function getCurrentUser(): ?array
    {
        if (!$this->token) {
            return null;
        }

        try {
            $response = $this->makeApiRequest('GET', api_url('auth.user'), [], [], 'get_current_user');
            
            if ($response['success']) {
                return $response['data']['user'] ?? null;
            }

            return null;
        } catch (\Exception $e) {
            Log::channel('api')->warning('Get current user error', ['error' => $e->getMessage()]);
            return null;
        }
    }
}