<?php

namespace BitApps\SocialPro\HTTP\Services\Ai\OpenaiService;

use BitApps\Social\Model\Account;
use BitApps\Social\Utils\Hash;
use BitApps\SocialPro\Deps\BitApps\WPKit\Helpers\JSON;
use BitApps\SocialPro\Deps\BitApps\WPKit\Http\Client\HttpClient;
use Exception;

class OpenaiService
{
    private const CHAT_COMPLETION_URL = 'https://api.openai.com/v1/chat/completions';

    private const IMAGE_GENERATION_URL = 'https://api.openai.com/v1/images/generations';

    private $httpClient;

    private $apiKey;

    public function __construct()
    {
        $this->httpClient = new HttpClient();
        $this->loadApiKey();
    }

    /**
     * Check if the service is properly configured.
     *
     * @return bool
     */
    public function isConfigured(): bool
    {
        return !empty($this->apiKey);
    }

    /**
     * Generate text content using OpenAI chat completion.
     *
     * @param string $prompt The prompt/content to process
     * @param string $model  The AI model to use (from AiPromptConfig)
     * @param array  $config Additional configuration options
     *
     * @return array{success: bool, content: string|null, error: string|null}
     */
    public function generateText(string $prompt, string $model, array $config = []): array
    {
        if (!$this->isConfigured()) {
            return $this->errorResponse('OpenAI API key is not configured');
        }

        if (empty($prompt)) {
            return $this->errorResponse('Prompt cannot be empty');
        }

        $temperature = $config['temperature'] ?? 1.0;

        $requestBody = [
            'model'    => $model,
            'messages' => [
                [
                    'role'    => 'user',
                    'content' => $prompt,
                ],
            ],
            'temperature' => (float) $temperature,
        ];

        $headers = [
            'Authorization' => 'Bearer ' . $this->apiKey,
            'Content-Type'  => 'application/json',
        ];

        try {
            $response = $this->httpClient->request(
                self::CHAT_COMPLETION_URL,
                'POST',
                JSON::encode($requestBody),
                $headers
            );

            if (is_wp_error($response)) {
                return $this->errorResponse($response->get_error_message());
            }

            if (isset($response->error)) {
                return $this->errorResponse($response->error->message ?? 'Unknown OpenAI API error');
            }

            if (isset($response->choices[0]->message->content)) {
                $generatedContent = trim($response->choices[0]->message->content);

                return $this->successResponse($generatedContent);
            }

            return $this->errorResponse('Invalid response from OpenAI API');
        } catch (Exception $e) {
            return $this->errorResponse('OpenAI API request failed: ' . $e->getMessage());
        }
    }

    /**
     * Generate image content using OpenAI image generation API.
     *
     * @param string $prompt The prompt/content to generate image from
     * @param string $model  The AI model to use
     * @param array  $config Additional configuration options (imageSize, quality, outputFormat, background)
     *
     * @return array{success: bool, content: string|null, error: string|null}
     */
    public function generateImage(string $prompt, string $model, array $config = []): array
    {
        if (!$this->isConfigured()) {
            return $this->errorResponse('OpenAI API key is not configured');
        }

        if (empty($prompt)) {
            return $this->errorResponse('Prompt cannot be empty');
        }

        // dall-e-2 and dall-e-3 were removed from OpenAI API — migrate to gpt-image-1
        if ($model === 'dall-e-3' || $model === 'dall-e-2') {
            $model = 'gpt-image-1';
        }

        $size = $config['imageSize'] ?? '1024x1024';
        $quality = $config['quality'] ?? 'auto';
        $outputFormat = $config['outputFormat'] ?? 'png';
        $background = $config['background'] ?? 'auto';

        $validSizes = ['1024x1024', '1536x1024', '1024x1536', 'auto'];
        if (!\in_array($size, $validSizes, true)) {
            $size = '1024x1024';
        }

        $validQualities = ['auto', 'low', 'medium', 'high'];
        if (!\in_array($quality, $validQualities, true)) {
            $quality = 'auto';
        }

        $validOutputFormats = ['png', 'webp', 'jpeg'];
        if (!\in_array($outputFormat, $validOutputFormats, true)) {
            $outputFormat = 'png';
        }

        $validBackgrounds = ['transparent', 'opaque', 'auto'];
        if (!\in_array($background, $validBackgrounds, true)) {
            $background = 'auto';
        }

        // transparent background is only supported with png or webp
        if ($background === 'transparent' && $outputFormat === 'jpeg') {
            $outputFormat = 'png';
        }

        $requestBody = [
            'model'         => $model,
            'prompt'        => $prompt,
            'size'          => $size,
            'quality'       => $quality,
            'output_format' => $outputFormat,
            'background'    => $background,
            'n'             => 1,
        ];

        $headers = [
            'Authorization' => 'Bearer ' . $this->apiKey,
            'Content-Type'  => 'application/json',
        ];

        try {
            $response = $this->httpClient->request(
                self::IMAGE_GENERATION_URL,
                'POST',
                JSON::encode($requestBody),
                $headers,
                ['timeout' => 120]
            );

            if (is_wp_error($response)) {
                return $this->errorResponse($response->get_error_message());
            }

            if (isset($response->error)) {
                return $this->errorResponse($response->error->message ?? 'Unknown OpenAI API error');
            }

            // URL response (legacy — kept as a fallback)
            if (isset($response->data[0]->url)) {
                return $this->successResponse($response->data[0]->url);
            }

            // gpt-image-1 returns base64 — save to WP media library and return the URL
            if (isset($response->data[0]->b64_json)) {
                $imageResult = $this->saveBase64ImageToWP($response->data[0]->b64_json, $outputFormat);
                if ($imageResult) {
                    $keepImage = ($config['keepImage'] ?? 'true') !== 'false';
                    if (!$keepImage) {
                        wp_schedule_single_event(time() + 300, 'bit_social_delete_ai_image', [$imageResult['id']]);
                    }

                    return $this->successResponse($imageResult['url']);
                }

                return $this->errorResponse('Failed to save generated image to media library');
            }

            return $this->errorResponse('Invalid response from OpenAI API');
        } catch (Exception $e) {
            return $this->errorResponse('OpenAI API request failed: ' . $e->getMessage());
        }
    }

    /**
     * Delete an AI-generated attachment from the media library (WP cron callback).
     *
     * @param int $attachmentId Attachment ID to delete
     */
    public static function deleteAiImage(int $attachmentId): void
    {
        wp_delete_attachment($attachmentId, true);
    }

    /**
     * Decode a base64 image and save it to the WordPress media library.
     *
     * @param string $b64Json Base64-encoded image data
     * @param string $format  Image format: png, webp, or jpeg
     *
     * @return array{url: string, id: int}|null Attachment URL + ID on success, null on failure
     */
    private function saveBase64ImageToWP(string $b64Json, string $format = 'png'): ?array
    {
        $imageData = base64_decode($b64Json);
        if (!$imageData) {
            return null;
        }

        $uploadDir = wp_upload_dir();
        if (!empty($uploadDir['error'])) {
            return null;
        }

        $mimeMap = ['png' => 'image/png', 'webp' => 'image/webp', 'jpeg' => 'image/jpeg'];
        $mime = $mimeMap[$format] ?? 'image/png';
        $ext = $format === 'jpeg' ? 'jpg' : $format;

        $filename = 'ai-image-' . time() . '.' . $ext;
        $filepath = $uploadDir['path'] . '/' . $filename;

        if (file_put_contents($filepath, $imageData) === false) {
            return null;
        }

        $attachmentId = wp_insert_attachment([
            'post_mime_type' => $mime,
            'post_title'     => sanitize_file_name($filename),
            'post_status'    => 'inherit',
        ], $filepath);

        if (is_wp_error($attachmentId)) {
            unlink($filepath);

            return null;
        }

        require_once ABSPATH . 'wp-admin/includes/image.php';
        wp_update_attachment_metadata(
            $attachmentId,
            wp_generate_attachment_metadata($attachmentId, $filepath)
        );

        $url = wp_get_attachment_url($attachmentId);

        if (!$url) {
            wp_delete_attachment($attachmentId, true);

            return null;
        }

        return ['url' => $url, 'id' => $attachmentId];
    }

    /**
     * Load API key from account.
     *
     * @return void
     */
    private function loadApiKey(): void
    {
        $account = Account::where('platform', 'openai')
            ->where('account_type', Account::accountType['AI_PLATFORM'])
            ->where('status', Account::ACCOUNT_STATUS['active'])
            ->first();

        if ($account && isset($account->details->key)) {
            try {
                $this->apiKey = Hash::decrypt($account->details->key);
            } catch (Exception $e) {
                $this->apiKey = null;
            }
        }
    }

    /**
     * Create error response.
     *
     * @param string $message Error message
     *
     * @return array
     */
    private function errorResponse(string $message): array
    {
        return [
            'success' => false,
            'content' => null,
            'error'   => $message,
        ];
    }

    /**
     * Create success response.
     *
     * @param string $content Generated content
     *
     * @return array
     */
    private function successResponse(string $content): array
    {
        return [
            'success' => true,
            'content' => $content,
            'error'   => null,
        ];
    }
}
