<?php

namespace BitApps\SocialPro\Utils;

use BitApps\Social\Model\Log;
use BitApps\Social\Utils\Common;
use BitApps\Social\Utils\SmartTag;
use BitApps\SocialPro\Model\AiPromptConfig;

class ProSmartTagHandler
{
    use Common;

    /**
     * Supported AI platforms and their service classes.
     */
    private const AI_PLATFORMS = [
        'openai' => 'BitApps\SocialPro\HTTP\Services\Ai\OpenaiService\OpenaiService',
    ];

    public static function getProSmartTagValue($key, $postId)
    {
        // Handle custom_field_[key]
        if (preg_match('/^custom_field_\[([^\]]+)\]$/', $key, $matches)) {
            return self::getCustomFieldValue($postId, $matches[1]);
        }

        // Handle hashtags_[key]
        if (preg_match('/^hashtags_\[([^\]]+)\]$/', $key, $matches)) {
            return self::getHashtagsValue($postId, $matches[1]);
        }

        // Handle prompt_13_[post_content_full] or prompt_13

        if (preg_match('/^prompt_(\d+)(?:_\[(.*)\])?$/s', $key, $matches)) {
            $promptId = $matches[1];
            $content = !empty($matches[2]) ? trim($matches[2]) : '';

            return self::getPromptValue($promptId, $postId, $content);
        }

        // Fallback: WooCommerce product info
        return (new WooCommerceProductInfo())->getWooCommerceInfo($key, $postId);
    }

    private static function getCustomFieldValue($postId, $customFieldKey)
    {
        $value = \get_post_meta($postId, $customFieldKey, true);

        // Normalize arrays/objects to string
        if (\is_array($value) || \is_object($value)) {
            $value = implode(',', (array) $value);
        }

        return (string) $value;
    }

    private static function getHashtagsValue($postId, $tagKey)
    {
        static $smartTag;

        // Create SmartTag instance once
        if (!$smartTag) {
            $smartTag = new SmartTag();
        }

        $post = \get_post($postId);
        if (!$post) {
            return '';
        }

        // Get raw tag value
        switch ($tagKey) {
            case 'post_categories':
                $rawValue = $smartTag->getPostTerms($postId, 'category', true);
                break;
            case 'post_tags':
                $rawValue = $smartTag->getPostTerms($postId, 'tag', true);
                break;
            default:
                $rawValue = $smartTag->getSmartTagValue($tagKey, $post);
                break;
        }

        if (empty($rawValue)) {
            return '';
        }

        $words = preg_split('/\s+/', trim($rawValue));

        $hashtags = array_map(function ($word) {
            return '#' . ltrim($word, '#');
        }, $words);

        return implode(' ', $hashtags);
    }

    private static function getPromptValue($promptId, $postId, $promptContent)
    {
        $aiPromptConfig = AiPromptConfig::findOne(['id' => $promptId]);

        if (!$aiPromptConfig) {
            return '';
        }

        $post = \get_post($postId);
        if (!$post) {
            return $aiPromptConfig->fallback_content ?? '';
        }

        $platform = $aiPromptConfig->platform;
        $model = $aiPromptConfig->model;

        // Parse config if it's a string
        $config = $aiPromptConfig->config;

        if (\is_string($config)) {
            $config = json_decode($config, true) ?? [];
        } elseif (\is_object($config)) {
            $config = (array) $config;
        } else {
            $config = [];
        }

        // Generate AI content using dynamic platform
        $aiService = self::createAiService($platform);

        if (!$aiService) {
            return self::getFallbackContent($aiPromptConfig, $post);
        }

        if (!$aiService->isConfigured()) {
            return self::getFallbackContent($aiPromptConfig, $post);
        }

        // Check if this is an image type prompt
        $promptType = $aiPromptConfig->type ?? 'text';

        if ($promptType === 'image') {
            $promptText = $aiPromptConfig->prompt ? (new self())->replaceTagValue($aiPromptConfig->prompt, $post) : '';

            $result = $aiService->generateImage($promptText, $model, $config);

            // If AI generation successful, return the image URL
            if ($result['success'] && !empty($result['content'])) {
                return $result['content'];
            }

            self::logAiError($platform, $promptId, $postId, $result['error'] ?? 'AI image generation failed');

            return false;
        }

        // Replace smart tags in the prompt content
        $content = (new self())->replaceTagValue($promptContent, $post);

        // Generate text for text type prompts
        $result = $aiService->generateText($content, $model, $config);

        // If AI generation successful, return the content
        if ($result['success'] && !empty($result['content'])) {
            return $result['content'];
        }

        self::logAiError($platform, $promptId, $postId, $result['error'] ?? 'AI text generation failed');

        return self::getFallbackContent($aiPromptConfig, $post);
    }

    /**
     * Create AI service instance based on platform.
     *
     * @param string $platform The AI platform name
     *
     * @return object|null
     */
    private static function createAiService(string $platform)
    {
        $platform = strtolower($platform);

        if (!isset(self::AI_PLATFORMS[$platform])) {
            return;
        }

        $serviceClass = self::AI_PLATFORMS[$platform];

        if (!class_exists($serviceClass)) {
            return;
        }

        return new $serviceClass();
    }

    /**
     * Get fallback content when AI fails.
     *
     * @param object $aiPromptConfig The AI prompt configuration
     * @param object $post           The WordPress post object
     *
     * @return string
     */
    private static function getFallbackContent($aiPromptConfig, $post): string
    {
        $fallbackContent = $aiPromptConfig->fallback_content ?? '';

        if (!empty($fallbackContent)) {
            // Replace smart tags in fallback content too
            return (new self())->replaceTagValue($fallbackContent, $post);
        }

        return '';
    }

    private static function logAiError(string $platform, $promptId, $postId, string $errorMessage): void
    {
        Log::insert([
            'schedule_id' => null,
            'platform'    => $platform,
            'status'      => Log::status['FAIL'],
            'details'     => json_encode([
                'prompt_id' => $promptId,
                'post_id'   => $postId,
                'response'  => $errorMessage,
            ]),
        ]);
    }
}
