<?php

namespace GriffinForms\Includes\Ai;

use GriffinForms\Traits\Singleton;
use GriffinForms\Includes\Ai\Transports\AiTransportResolver;
use GriffinForms\Includes\Ai\Exceptions\AiBrokerError;
use GriffinForms\Includes\Ai\Exceptions\ButlerTimeoutException;

class AiBroker
{
    use Singleton;

    protected $resolver;
    protected $log;

    protected function __construct()
    {
        $this->resolver = new AiTransportResolver();
        $this->log      = \GriffinForms\Log::getInstance();
    }

    /**
     * Orchestrates an AI prompt request safely through the specified provider wrapper.
     * Guaranteed to return a standardized safe array without throwing fatal exceptions downstream.
     */
    public function request(string $provider, string $prompt, array $context = [], array $config = []): array
    {
        try {
            return $this->requestStrict($provider, $prompt, $context, $config);
        } catch (ButlerTimeoutException $e) {
            $this->logError('Broker Timeout: ' . $e->getMessage(), $e->getCode());
            return $this->formatErrorResponse('AI request timed out before Griffin Assist could finish.', $e->getCode() ?: 408);
        } catch (AiBrokerError $e) {
            $this->logError('Broker Error: ' . $e->getMessage(), $e->getCode());
            return $this->formatErrorResponse($e->getMessage(), $e->getCode());
        } catch (\Exception $e) {
            $this->logError('Fatal Transport Exception: ' . $e->getMessage(), 500);
            return $this->formatErrorResponse('An unexpected AI service execution error occurred.', 500);
        } catch (\Throwable $t) {
            $this->logError('System Throwable inside AI Transport: ' . $t->getMessage(), 500);
            return $this->formatErrorResponse('A critical subsystem failure completely aborted the AI request.', 500);
        }
    }

    public function requestStrict(string $provider, string $prompt, array $context = [], array $config = []): array
    {
        if ($provider === '') {
            throw new AiBrokerError('AI is not configured for this workflow yet.', 412);
        }

        $client = $this->resolver->resolve($provider, $config);
        $response = $client->request($prompt, $context);
        ButlerTokenManager::getInstance()->record($response);

        return $response;
    }

    protected function logError(string $message, $code)
    {
        if (is_object($this->log)) {
            // Logs structure defaults -> type, category, item_id, user_id, message, trace/action string
            $this->log->add(
                'error', 
                'ai_broker', 
                0, 
                (int) get_current_user_id(), 
                $message . ' (Code: ' . sanitize_text_field($code) . ')', 
                'ai_request_failed'
            );
        }
    }

    protected function formatErrorResponse(string $message, $code): array
    {
        return array(
            'success' => false,
            'error'   => $message,
            'code'    => $code
        );
    }
}
