<?php

namespace AIPT\Api\BulkGenerator\Title;

use AIPT\Api\OpenAI\OpenAIClient;
use AIPT\Api\Gemini\GeminiClient;
use AIPT\Core\ErrorHandler;
use AIPT\Utils\PromptFormatter;
use AIPT\Utils\VariableConverter;
use AIPT\Utils\ProductFilter\ProductFilterBuilder;
use AIPT\Utils\ProductFilter\ProductFilterMapper;
use AIPT\Api\BulkGenerator\Common\DatabaseManager;
use AIPT\Api\BulkGenerator\Common\AIClientFactory;
use AIPT\Api\BulkGenerator\Common\ProductDataFormatter;
use AIPT\Api\BulkGenerator\Title\Core\TitlePromptFactory;

class TitleGeneratorService {
    private $db_manager;
    private $prompt_factory;

    public function __construct() {
        $this->db_manager = new DatabaseManager();
        $this->prompt_factory = new TitlePromptFactory();
    }

    public function get_products($params) {
        try {
            $filterParams = ProductFilterMapper::fromRequest($params);
            $builder = new ProductFilterBuilder();
            ProductFilterMapper::applyToBuilder($builder, $filterParams);
            return $builder->getProducts();
        } catch (\Exception $e) {
            return [
                'products' => [],
                'total' => 0,
                'total_pages' => 0,
                'error' => 'An error occurred while searching products: ' . $e->getMessage()
            ];
        }
    }

    public function get_categories() {
        return ProductFilterMapper::getCategories();
    }

    public function bulk_generate($product_ids, $options) {
        $results = [];
        $language = $options['language'] ?? get_option('aipt_language', 'English');
        $writing_style = isset($options['writing_style']) ? sanitize_text_field($options['writing_style']) : (isset($options['writingStyle']) ? sanitize_text_field($options['writingStyle']) : get_option('aipt_writing_style', 'Professional'));
        $variant_count = intval($options['variantCount'] ?? 1);
        $variant_count = max(1, min(5, $variant_count)); 

        foreach ($product_ids as $product_id) {
            $product = wc_get_product($product_id);
            if (!$product) continue;

            try {
                $api_provider = $options['provider'] ?? get_option('aipt_api_provider', 'openai');
                $product_data = ProductDataFormatter::getFormattedProductData($product);
                
                if (empty($product_data['categories'])) {
                    $product_data['categories'] = '';
                }

                $client = AIClientFactory::create($api_provider, [
                    'category' => $product_data['categories'],
                    'generation_type' => 'title',
                    'model' => $options['model'] ?? null
                ]);

                $title_prompts = $this->prompt_factory->getTitlePrompts($options, $product_data, $language, $writing_style);
                $system_prompt = $title_prompts['system_prompt'];
                $user_prompt = $title_prompts['user_prompt'];

                $variable_map = [
                    '{SKU}' => $product_data['sku'],
                    '{ATTRIBUTES}' => $product_data['formatted_attributes'],
                    '{CATEGORIES}' => $product_data['categories'],
                    '{TAGS}' => $product_data['tags'],
                    '{PRICE}' => $product_data['price'],
                    '{REGULAR_PRICE}' => $product_data['regular_price'],
                    '{SALE_PRICE}' => $product_data['sale_price'],
                    '{language}' => $language,
                    '{style}' => $writing_style,
                    '{title}' => $product_data['name'],
                    '{short_description}' => $product->get_short_description(),
                    '{long_description}' => $product->get_description(),
                    '{max_length}' => $options['maxLength'] ?? '60',
                    '{keywords}' => $options['keywords'] ?? '',
                    '{tone}' => $options['tone'] ?? 'SEO-Focused'
                ];

                $titles = $this->generateUniqueVariants(
                    $client,
                    $system_prompt,
                    $user_prompt,
                    $variant_count,
                    $variable_map,
                    $options['model'] ?? null,
                    $product_id
                );

                $results[] = [
                    'product_id' => $product_id,
                    'type' => 'title',
                    'variants' => $titles,
                    'text' => $titles[0] 
                ];

            } catch (\Exception $e) {
                $provider = $options['provider'] ?? get_option('aipt_api_provider', 'openai');

                $results[] = [
                    'product_id' => $product_id,
                    'type' => 'title',
                    'text' => '',
                    'api_error' => ErrorHandler::format_api_error_message(ucfirst($provider), $e->getMessage()),
                    'provider' => ucfirst($provider)
                ];
            }
        }

        return $results;
    }

    public function apply_titles($results, $options) {
        $applied_count = 0;

        foreach ($results as $result) {
            $product_id = $result['product_id'] ?? null;
            $title = $result['title'] ?? null;
            $status = $result['status'] ?? 'pending';

            if (!$product_id || !$title) {
                continue;
            }

            if ($status === 'rejected') {
                continue;
            }

			$product = wc_get_product($product_id);
			if (!$product) {
				continue;
			}

			$sanitized_title = sanitize_text_field( $title );
			call_user_func( [ $product, 'set_name' ], $sanitized_title );
			call_user_func( [ $product, 'save' ] );

            $this->db_manager->delete_history_items([
                'product_id' => $product_id,
                'description_type' => 'title',
                'status' => 'pending'
            ]);

            $applied_count++;
        }

        return [
            'message' => 'Titles applied successfully',
            'applied_count' => $applied_count
        ];
    }

    /**
     * Generate unique title variants with retry logic to prevent duplicates
     */
    private function generateUniqueVariants($client, $system_prompt, $user_prompt, $variant_count, $variable_map, $model, $product_id) {
        $max_retries = 3;
        $attempt = 0;
        $all_generated_titles = [];

        $safe_variables = VariableConverter::convertVariables($variable_map);

        if ($variant_count <= 1) {
            $processed_system_prompt = str_replace(array_keys($safe_variables), array_values($safe_variables), $system_prompt);
            $processed_user_prompt = str_replace(array_keys($safe_variables), array_values($safe_variables), $user_prompt);
            
            $processed_system_prompt = PromptFormatter::cleanContent($processed_system_prompt);
            $processed_user_prompt = PromptFormatter::cleanContent($processed_user_prompt);
            
            $generated_text = $client->generate_description($processed_system_prompt, $processed_user_prompt, $model);
            $generated_text = PromptFormatter::cleanContent($generated_text);
            $generated_text = trim($generated_text, '"\'`');
            $generated_text = wp_strip_all_tags($generated_text);

            if (empty(trim($generated_text))) {
                throw new \Exception('No valid title was generated');
            }
            
            return [$generated_text];
        }

        while ($attempt < $max_retries && count($all_generated_titles) < $variant_count) {
            $attempt++;
            

            $enhanced_user_prompt = $user_prompt;
            
            if ($attempt == 1) {

                $enhanced_user_prompt .= "\n\nIMPORTANT: Generate {$variant_count} COMPLETELY DIFFERENT title variations for this product. Each variant must be unique in wording, style, and approach. Return them separated by '|||'. DO NOT repeat the same title or use very similar words.";
            } elseif ($attempt == 2) {

                $enhanced_user_prompt .= "\n\nGenerate {$variant_count} DIVERSE title variations using DIFFERENT approaches:";
                $enhanced_user_prompt .= "\n1. Focus on main features";
                $enhanced_user_prompt .= "\n2. Emphasize benefits";
                $enhanced_user_prompt .= "\n3. Highlight unique selling points";
                $enhanced_user_prompt .= "\n4. Use emotional appeal";
                $enhanced_user_prompt .= "\n5. SEO-focused approach";
                $enhanced_user_prompt .= "\nEach title MUST be completely different. Return them separated by '|||'.";
                

                if (!empty($all_generated_titles)) {
                    $enhanced_user_prompt .= "\n\nDO NOT generate these titles again: " . implode(', ', array_map(function($title) { return '"' . $title . '"'; }, $all_generated_titles));
                }
            } else {

                $enhanced_user_prompt .= "\n\nCREATE {$variant_count} COMPLETELY UNIQUE titles with these requirements:";
                $enhanced_user_prompt .= "\n- Use different word choices and sentence structures";
                $enhanced_user_prompt .= "\n- Vary the focus (features vs benefits vs emotional appeal)";
                $enhanced_user_prompt .= "\n- Different lengths within the character limit";
                $enhanced_user_prompt .= "\n- Avoid repeating key phrases from previous attempts";
                $enhanced_user_prompt .= "\nReturn them separated by '|||'.";
                
                if (!empty($all_generated_titles)) {
                    $enhanced_user_prompt .= "\n\nAVOID these previously generated titles: " . implode(', ', array_map(function($title) { return '"' . $title . '"'; }, $all_generated_titles));
                }
            }

            $processed_system_prompt = str_replace(array_keys($safe_variables), array_values($safe_variables), $system_prompt);
            $processed_user_prompt = str_replace(array_keys($safe_variables), array_values($safe_variables), $enhanced_user_prompt);
            
            $processed_system_prompt = PromptFormatter::cleanContent($processed_system_prompt);
            $processed_user_prompt = PromptFormatter::cleanContent($processed_user_prompt);
            
            if (defined('WP_DEBUG') && WP_DEBUG) {
                $log_message = "[AIPT Debug - Title Generator] Attempt {$attempt} for Product ID: {$product_id}\n";
                $log_message .= "--- SYSTEM PROMPT ---\n";
                $log_message .= $processed_system_prompt . "\n";
                $log_message .= "--- USER PROMPT ---\n";
                $log_message .= $processed_user_prompt . "\n";
                $log_message .= "-----------------------\n";
            }
            
            $generated_text = $client->generate_description($processed_system_prompt, $processed_user_prompt, $model);
            $generated_text = PromptFormatter::cleanContent($generated_text);
            $generated_text = trim($generated_text, '"\'`');
            $generated_text = wp_strip_all_tags($generated_text);

            if (empty(trim($generated_text))) {
                continue; 
            }
            

            $new_titles = [];
            if (strpos($generated_text, '|||') !== false) {
                $raw_titles = explode('|||', $generated_text);
                foreach ($raw_titles as $title) {
                    $title = trim($title);
                    if (!empty($title)) {
                        $new_titles[] = $title;
                    }
                }
            } else {
                $new_titles[] = $generated_text;
            }
            

            foreach ($new_titles as $title) {
                if (!$this->isDuplicateTitle($title, $all_generated_titles)) {
                    $all_generated_titles[] = $title;
                    

                    if (count($all_generated_titles) >= $variant_count) {
                        break 2; 
                    }
                }
            }
        }
        

        while (count($all_generated_titles) < $variant_count) {
            if (count($all_generated_titles) > 0) {

                $base_title = $all_generated_titles[0];
                $variation = $this->createTitleVariation($base_title, count($all_generated_titles));
                
                if (!$this->isDuplicateTitle($variation, $all_generated_titles)) {
                    $all_generated_titles[] = $variation;
                } else {

                    break;
                }
            } else {

                throw new \Exception('Unable to generate any valid titles');
            }
        }
        

        return array_slice($all_generated_titles, 0, $variant_count);
    }
    
    /**
     * Check if a title is duplicate (similar) to existing titles
     */
    private function isDuplicateTitle($new_title, $existing_titles) {
        $new_title_clean = strtolower(trim($new_title));
        
        foreach ($existing_titles as $existing_title) {
            $existing_title_clean = strtolower(trim($existing_title));
            

            if ($new_title_clean === $existing_title_clean) {
                return true;
            }
            

            $new_words = array_filter(explode(' ', $new_title_clean));
            $existing_words = array_filter(explode(' ', $existing_title_clean));
            
            if (count($new_words) > 0 && count($existing_words) > 0) {
                $intersection = array_intersect($new_words, $existing_words);
                $similarity = count($intersection) / max(count($new_words), count($existing_words));
                
                if ($similarity >= 0.85) {
                    return true;
                }
            }
        }
        
        return false;
    }
    
    /**
     * Create a slight variation of a base title
     */
    private function createTitleVariation($base_title, $variation_number) {

        $variations = [
            'Premium ' . $base_title,
            $base_title . ' - Professional Quality',
            'High-Quality ' . $base_title,
            $base_title . ' Collection',
            'Best ' . $base_title
        ];
        
        $variation_index = ($variation_number - 1) % count($variations);
        return $variations[$variation_index];
    }
}
