<?php

namespace AIPT\Utils;

/**
 * PromptBuilder - Builds AI prompts with product context isolation
 * 
 * This class ensures each product has an isolated context in AI prompts,
 * preventing cross-product contamination during batch generation.
 * 
 * @since 2.4.0
 */
class PromptBuilder {
    /**
     * Product context data
     *
     * @var array
     */
    private $context = [];

    /**
     * Isolation marker for debugging
     *
     * @var string
     */
    private $isolation_marker;

    /**
     * Create a new PromptBuilder instance with isolated product context.
     *
     * @param array $product_data Product data from ProductDataFormatter
     * @param int   $product_id   Product ID
     */
    public function __construct(array $product_data, int $product_id) {
        $this->isolation_marker = 'ctx_' . uniqid();
        $this->context = $this->createIsolatedContext($product_data, $product_id);
    }

    /**
     * Create an isolated product context.
     * This ensures no data from previous products can contaminate the current context.
     *
     * @param array $product_data Product data
     * @param int   $product_id   Product ID
     * @return array Isolated context
     */
    private function createIsolatedContext(array $product_data, int $product_id): array {
        return [
            'id' => $product_id,
            'name' => $product_data['name'] ?? '',
            'sku' => $product_data['sku'] ?? '',
            'price' => $product_data['price'] ?? '',
            'regular_price' => $product_data['regular_price'] ?? '',
            'sale_price' => $product_data['sale_price'] ?? '',
            'categories' => $product_data['categories'] ?? '',
            'tags' => $product_data['tags'] ?? '',
            'attributes' => $product_data['formatted_attributes'] ?? '',
            'custom_variables' => $product_data['custom_variables'] ?? [],
            '_isolation_marker' => $this->isolation_marker,
        ];
    }

    /**
     * Get the product identity prefix for prompts.
     * This is prepended to system prompts to enforce product-specific generation.
     *
     * @return string Product identity string
     */
    public function getProductIdentity(): string {
        $sku_display = !empty($this->context['sku']) ? $this->context['sku'] : 'N/A';
        
        return sprintf(
            "IMPORTANT: You are writing content ONLY for this specific product:\n" .
            "- Product Name: %s\n" .
            "- Product ID: %d\n" .
            "- SKU: %s\n" .
            "DO NOT reference, mention, or include information about any other products.\n" .
            "All content must be specifically about the product listed above.\n\n",
            $this->context['name'],
            $this->context['id'],
            $sku_display
        );
    }

    /**
     * Get the product context line for user prompts.
     * Provides product details in a structured format.
     *
     * @return string Product context lines
     */
    public function getProductContext(): string {
        $lines = [
            'Product Details:',
            '- Name: ' . ($this->context['name'] ?: 'N/A'),
            '- SKU: ' . ($this->context['sku'] ?: 'N/A'),
            '- Categories: ' . ($this->context['categories'] ?: 'N/A'),
            '- Tags: ' . ($this->context['tags'] ?: 'N/A'),
            '- Price: ' . ($this->context['price'] ?: 'N/A'),
        ];

        if (!empty($this->context['regular_price'])) {
            $lines[] = '- Regular Price: ' . $this->context['regular_price'];
        }
        if (!empty($this->context['sale_price'])) {
            $lines[] = '- Sale Price: ' . $this->context['sale_price'];
        }
        if (!empty($this->context['attributes'])) {
            $lines[] = '- Attributes: ' . $this->context['attributes'];
        }

        return implode("\n", $lines);
    }

    /**
     * Build a complete system prompt with product identity.
     *
     * @param string $base_prompt     The base system prompt template
     * @param array  $variables       Variables to replace in the prompt
     * @return string Complete system prompt
     */
    public function buildSystemPrompt(string $base_prompt, array $variables = []): string {
        $prompt = $this->getProductIdentity() . $base_prompt;
        
        if (!empty($variables)) {
            $safe_variables = VariableConverter::convertVariables($variables);
            $prompt = str_replace(
                array_keys($safe_variables),
                array_values($safe_variables),
                $prompt
            );
        }

        return PromptFormatter::cleanContent($prompt);
    }

    /**
     * Build a complete user prompt with product context.
     *
     * @param string $base_prompt     The base user prompt template
     * @param array  $variables       Variables to replace in the prompt
     * @param string $existing_content Optional existing content to append
     * @return string Complete user prompt
     */
    public function buildUserPrompt(string $base_prompt, array $variables = [], string $existing_content = ''): string {
        $prompt = $base_prompt;
        if (!empty($variables)) {
            $safe_variables = VariableConverter::convertVariables($variables);
            $prompt = str_replace(
                array_keys($safe_variables),
                array_values($safe_variables),
                $prompt
            );
        }

        if (!empty($existing_content)) {
            $prompt .= "\n\n" . $existing_content;
        }

        return PromptFormatter::cleanContent($prompt);
    }

    /**
     * Build variable map for prompt replacement.
     *
     * @param string $type           Description type ('short' or 'full')
     * @param int    $max_length     Maximum length for the description
     * @param string $language       Target language
     * @param string $writing_style  Writing style/tone
     * @param array  $custom_vars    Custom variable definitions
     * @return array Variable map for replacement
     */
    public function buildVariableMap(
        string $type,
        int $max_length,
        string $language,
        string $writing_style,
        array $custom_vars = []
    ): array {
        $length_key = $type === 'short' ? '{max_short_length}' : '{max_length}';
        
        $map = [
            $length_key => $max_length,
            '{SKU}' => $this->context['sku'],
            '{ATTRIBUTES}' => $this->context['attributes'],
            '{CATEGORIES}' => $this->context['categories'],
            '{TAGS}' => $this->context['tags'],
            '{PRICE}' => $this->context['price'],
            '{REGULAR_PRICE}' => $this->context['regular_price'],
            '{SALE_PRICE}' => $this->context['sale_price'],
            '{language}' => $language,
            '{style}' => $writing_style,
            '{title}' => $this->context['name'],
        ];

        if (!empty($custom_vars) && !empty($this->context['custom_variables'])) {
            foreach ($custom_vars as $variable) {
                $var_name = $variable['name'] ?? '';
                if (!empty($var_name) && isset($this->context['custom_variables'][$var_name])) {
                    $map['{' . $var_name . '}'] = $this->context['custom_variables'][$var_name];
                }
            }
        }

        return $map;
    }

    /**
     * Get the isolation marker for debugging purposes.
     *
     * @return string Isolation marker
     */
    public function getIsolationMarker(): string {
        return $this->isolation_marker;
    }

    /**
     * Get the raw context array.
     *
     * @return array Product context
     */
    public function getContext(): array {
        return $this->context;
    }

    /**
     * Get the product ID from context.
     *
     * @return int Product ID
     */
    public function getProductId(): int {
        return (int) $this->context['id'];
    }

    /**
     * Get the product name from context.
     *
     * @return string Product name
     */
    public function getProductName(): string {
        return $this->context['name'];
    }

    /**
     * Get the product SKU from context.
     *
     * @return string Product SKU
     */
    public function getProductSku(): string {
        return $this->context['sku'];
    }

    /**
     * Static factory method to create PromptBuilder from WC_Product.
     *
     * @param \WC_Product $product      WooCommerce product object
     * @param array       $product_data Formatted product data
     * @return self New PromptBuilder instance
     */
    public static function fromProduct(\WC_Product $product, array $product_data): self {
        return new self($product_data, $product->get_id());
    }
}
