<?php

/**
 * Content Generator
 *
 * @package AIContentGenerator
 */
namespace AICG;

// Prevent direct access
if ( !defined( 'ABSPATH' ) ) {
    exit;
}
/**
 * Orchestrates content creation from keyword to published post
 */
class Content_Generator {
    /**
     * AI Client instance
     */
    private $ai_client;

    /**
     * Pexels API instance
     */
    private $pexels;

    /**
     * Quality Checker instance
     */
    private $quality_checker;

    /**
     * Constructor
     */
    public function __construct( Ai_Client $ai_client, Pexels_Api $pexels, Quality_Checker $quality_checker ) {
        $this->ai_client = $ai_client;
        $this->pexels = $pexels;
        $this->quality_checker = $quality_checker;
    }

    /**
     * Generate content from a keyword ID
     */
    public function generate_from_keyword( $keyword_id, $options = array() ) {
        global $wpdb;
        // Get keyword data
        $keyword_manager = new Keyword_Manager();
        $keyword_data = $keyword_manager->get_keyword( $keyword_id );
        if ( !$keyword_data ) {
            return new \WP_Error('keyword_not_found', __( 'Keyword not found.', 'roidnet-ai-content-generator' ));
        }
        // Set keyword language in options
        $options = wp_parse_args( $options, array() );
        if ( !empty( $keyword_data->language ) ) {
            $options['language'] = $keyword_data->language;
        }
        // Check if already processed
        if ( $keyword_data->status === 'completed' ) {
            return new \WP_Error('already_processed', __( 'This keyword has already been processed.', 'roidnet-ai-content-generator' ));
        }
        // Mark as processing
        $keyword_manager->mark_processing( $keyword_id );
        try {
            // Generate content
            $result = $this->generate( $keyword_data->keyword, array_merge( $options, array(
                'category_id' => $keyword_data->category_id,
            ) ) );
            if ( is_wp_error( $result ) ) {
                $error_msg = $result->get_error_message();
                // Log to System Log
                Action_Logger::log(
                    'content_generation',
                    sprintf( __( 'Generation failed for keyword "%s": %s', 'roidnet-ai-content-generator' ), $keyword_data->keyword, $error_msg ),
                    'error',
                    $options['schedule_id'] ?? null
                );
                // Handle retry logic
                $max_retries = get_option( 'roidaico_max_retries', 3 );
                $current_retries = ( isset( $keyword_data->retries ) ? $keyword_data->retries : 0 );
                if ( $current_retries < $max_retries ) {
                    $keyword_manager->increment_retries( $keyword_id );
                    $keyword_manager->revert_to_pending( $keyword_id );
                } else {
                    $keyword_manager->mark_failed( $keyword_id, $error_msg );
                }
                return $result;
            }
            // Mark as completed
            $keyword_manager->mark_completed( $keyword_id, $result );
            // Handle translation linking
            $this->handle_multilingual_linking( $keyword_id, $result, $options['post_type'] ?? 'post' );
            // Generate other keywords in the same translation group together
            $this->generate_group_translations( $keyword_id, $options );
            // Log the generation
            $this->log_generation( $result, $keyword_id, $options['schedule_id'] ?? null );
            return $result;
        } catch ( \Throwable $e ) {
            $error_msg = $e->getMessage();
            // Log to System Log
            Action_Logger::log(
                'content_generation',
                sprintf( __( 'Fatal error generating content for keyword "%s": %s', 'roidnet-ai-content-generator' ), $keyword_data->keyword, $error_msg ),
                'error',
                $options['schedule_id'] ?? null
            );
            // Handle fatal errors or any throwable as retriable if under limit
            $max_retries = get_option( 'roidaico_max_retries', 3 );
            $current_retries = ( isset( $keyword_data->retries ) ? $keyword_data->retries : 0 );
            if ( $current_retries < $max_retries ) {
                $keyword_manager->increment_retries( $keyword_id );
                $keyword_manager->revert_to_pending( $keyword_id );
            } else {
                $keyword_manager->mark_failed( $keyword_id, $error_msg );
            }
            return new \WP_Error('generation_error', $error_msg);
        }
    }

    /**
     * Generate content for a keyword
     */
    public function generate( $keyword, $options = array() ) {
        $defaults = array(
            'category_id' => 0,
            'post_type'   => get_option( 'roidaico_default_post_type', 'post' ),
            'author_id'   => get_current_user_id(),
            'post_status' => 'draft',
            'tone'        => get_option( 'roidaico_default_tone', 'professional' ),
            'length'      => get_option( 'roidaico_default_length', 'medium' ),
            'language'    => get_option( 'roidaico_default_language', 'en' ),
            'add_image'   => true,
            'schedule_id' => null,
        );
        $options = wp_parse_args( $options, $defaults );
        // Get internal links if enabled
        $internal_links = array();
        if ( get_option( 'roidaico_enable_internal_links', true ) ) {
            $internal_links = $this->get_related_posts( $keyword, $options['category_id'] );
        }
        // Generate article content via AI
        $article = $this->ai_client->generate_content( $keyword, array(
            'tone'           => $options['tone'],
            'length'         => $options['length'],
            'language'       => $options['language'],
            'internal_links' => $internal_links,
        ) );
        if ( is_wp_error( $article ) ) {
            return $article;
        }
        // Run quality checks
        $quality_result = $this->quality_checker->check_content( $article );
        if ( is_wp_error( $quality_result ) ) {
            return $quality_result;
        }
        // Create the post
        $post_data = array(
            'post_title'   => sanitize_text_field( $article['title'] ),
            'post_content' => '',
            'post_excerpt' => ( isset( $article['excerpt'] ) ? sanitize_text_field( $article['excerpt'] ) : '' ),
            'post_status'  => $options['post_status'],
            'post_type'    => $options['post_type'],
            'post_author'  => $options['author_id'],
        );
        // Set category if post type supports it
        if ( $options['post_type'] === 'post' && $options['category_id'] > 0 ) {
            $post_data['post_category'] = array($options['category_id']);
        }
        $post_id = wp_insert_post( $post_data );
        if ( is_wp_error( $post_id ) ) {
            return $post_id;
        }
        // Set language for Polylang or WPML if active
        $post_lang = ( !empty( $options['language'] ) ? $options['language'] : get_option( 'roidaico_default_language', 'en' ) );
        if ( function_exists( 'pll_set_post_language' ) ) {
            pll_set_post_language( $post_id, $post_lang );
        }
        if ( has_action( 'wpml_set_element_language_details' ) ) {
            $element_type = 'post_' . $options['post_type'];
            do_action( 'wpml_set_element_language_details', array(
                'element_id'           => $post_id,
                'element_type'         => $element_type,
                'trid'                 => null,
                'language_code'        => $post_lang,
                'source_language_code' => null,
            ) );
        }
        // Set tags
        if ( !empty( $article['tags'] ) && is_array( $article['tags'] ) ) {
            wp_set_post_tags( $post_id, $article['tags'] );
            // Set tags language if Polylang or WPML is active
            if ( function_exists( 'pll_set_term_language' ) || has_action( 'wpml_set_element_language_details' ) ) {
                $post_tags = wp_get_post_tags( $post_id );
                if ( !empty( $post_tags ) && is_array( $post_tags ) ) {
                    foreach ( $post_tags as $tag ) {
                        if ( function_exists( 'pll_set_term_language' ) ) {
                            pll_set_term_language( $tag->term_id, $post_lang );
                        }
                        if ( has_action( 'wpml_set_element_language_details' ) ) {
                            do_action( 'wpml_set_element_language_details', array(
                                'element_id'           => $tag->term_taxonomy_id,
                                'element_type'         => 'tax_post_tag',
                                'trid'                 => null,
                                'language_code'        => $post_lang,
                                'source_language_code' => null,
                            ) );
                        }
                    }
                }
            }
        }
        // Add featured image
        if ( $options['add_image'] ) {
            $image_query = ( !empty( $article['featured_image_prompt'] ) ? $article['featured_image_prompt'] : $keyword );
            $this->add_featured_image( $post_id, $image_query, $options );
        }
        // Final content update (with images attached to post)
        $processed_content = $this->process_internal_images( $article['content'], $post_id );
        // Strip duplicate H1 if AI included it despite instructions
        $processed_content = preg_replace( '/<h1[^>]*>.*?<\\/h1>/si', '', $processed_content );
        wp_update_post( array(
            'ID'           => $post_id,
            'post_content' => $processed_content,
        ) );
        // Set SEO meta data
        $this->set_seo_meta( $post_id, $article );
        // Store generation meta
        update_post_meta( $post_id, '_roidaico_generated', true );
        update_post_meta( $post_id, '_roidaico_keyword', $keyword );
        update_post_meta( $post_id, '_roidaico_generated_at', current_time( 'mysql' ) );
        return $post_id;
    }

    /**
     * Process internal image placeholders and replace with Pexels images
     */
    private function process_internal_images( $content, $post_id ) {
        // Find [IMAGE: description] patterns
        preg_match_all( '/\\[IMAGE:\\s*(.*?)\\]/i', $content, $matches );
        if ( empty( $matches[0] ) ) {
            return $content;
        }
        foreach ( $matches[1] as $index => $description ) {
            $placeholder = $matches[0][$index];
            $attachment_id = null;
            if ( empty( $attachment_id ) || is_wp_error( $attachment_id ) ) {
                // Search for image
                $image = $this->pexels->get_unique_image( $description );
                if ( is_wp_error( $image ) ) {
                    // Remove placeholder if search fails
                    $content = str_replace( $placeholder, '', $content );
                    continue;
                }
                // Download and attach image
                $attachment_id = $this->pexels->download_image( $image, $post_id );
                if ( is_wp_error( $attachment_id ) ) {
                    $content = str_replace( $placeholder, '', $content );
                    continue;
                }
            }
            // Generate image tag
            $img_url = wp_get_attachment_url( $attachment_id );
            $img_alt = get_post_meta( $attachment_id, '_wp_attachment_image_alt', true );
            $img_tag = sprintf(
                '<figure class="wp-block-image size-large"><img src="%s" alt="%s" class="wp-image-%d"/><figcaption>%s</figcaption></figure>',
                esc_url( $img_url ),
                esc_attr( $img_alt ),
                $attachment_id,
                esc_html( $img_alt )
            );
            $content = str_replace( $placeholder, $img_tag, $content );
        }
        return $content;
    }

    /**
     * Add featured image from Pexels
     */
    private function add_featured_image( $post_id, $keyword, $options = array() ) {
        // Get unique image
        $image = $this->pexels->get_unique_image( $keyword );
        if ( is_wp_error( $image ) ) {
            // Log the initial failure
            Action_Logger::log( 'images', sprintf( __( 'Initial image search failed for: "%s". Error: %s. Trying fallbacks...', 'roidnet-ai-content-generator' ), $keyword, $image->get_error_message() ), 'info' );
            // Fallback 1: Try a simplified version of the keyword (English only)
            $clean_keyword = $this->pexels->clean_query( $keyword );
            if ( $clean_keyword !== $keyword ) {
                $image = $this->pexels->get_unique_image( $clean_keyword );
            }
            // Fallback 2: Try the category name
            if ( is_wp_error( $image ) && !empty( $options['category_id'] ) && $options['category_id'] > 0 ) {
                $category = get_term( $options['category_id'], 'category' );
                if ( $category && !is_wp_error( $category ) ) {
                    $image = $this->pexels->get_unique_image( $category->name );
                }
            }
            // Final check
            if ( is_wp_error( $image ) ) {
                // Log but don't fail
                Action_Logger::log( 'images', sprintf( __( 'All image search fallbacks failed for: "%s". Final Error: %s', 'roidnet-ai-content-generator' ), $keyword, $image->get_error_message() ), 'warning' );
                return false;
            }
        }
        // Download and attach image
        $attachment_id = $this->pexels->download_image( $image, $post_id );
        if ( is_wp_error( $attachment_id ) ) {
            Action_Logger::log( 'images', sprintf( __( 'Could not download image for keyword: "%s". Error: %s', 'roidnet-ai-content-generator' ), $keyword, $attachment_id->get_error_message() ), 'error' );
            return false;
        }
        // Set as featured image
        set_post_thumbnail( $post_id, $attachment_id );
        Action_Logger::log( 'images', sprintf( __( 'Successfully added featured image for keyword: "%s". Attachment ID: %d', 'roidnet-ai-content-generator' ), $keyword, $attachment_id ), 'success' );
        return $attachment_id;
    }

    /**
     * Get related posts for internal linking
     */
    private function get_related_posts( $keyword, $category_id = 0, $limit = 3 ) {
        $max_links = get_option( 'roidaico_max_internal_links', 3 );
        $limit = min( $limit, $max_links );
        $args = array(
            'post_type'      => 'post',
            'post_status'    => 'publish',
            'posts_per_page' => $limit,
            's'              => $keyword,
            'orderby'        => 'relevance',
        );
        if ( $category_id > 0 ) {
            $args['cat'] = $category_id;
        }
        $query = new \WP_Query($args);
        $links = array();
        if ( $query->have_posts() ) {
            while ( $query->have_posts() ) {
                $query->the_post();
                $links[] = array(
                    'title' => get_the_title(),
                    'url'   => get_permalink(),
                );
            }
            wp_reset_postdata();
        }
        return $links;
    }

    /**
     * Set SEO meta data based on detected plugin
     */
    private function set_seo_meta( $post_id, $article ) {
        $seo_plugin = $this->detect_seo_plugin();
        $meta_description = ( isset( $article['meta_description'] ) ? sanitize_text_field( $article['meta_description'] ) : '' );
        $focus_keyword = ( isset( $article['focus_keyword'] ) ? sanitize_text_field( $article['focus_keyword'] ) : '' );
        switch ( $seo_plugin ) {
            case 'yoast':
                update_post_meta( $post_id, '_yoast_wpseo_metadesc', $meta_description );
                update_post_meta( $post_id, '_yoast_wpseo_focuskw', $focus_keyword );
                break;
            case 'rankmath':
                update_post_meta( $post_id, 'rank_math_description', $meta_description );
                update_post_meta( $post_id, 'rank_math_focus_keyword', $focus_keyword );
                break;
            default:
                // Store as generic meta
                update_post_meta( $post_id, '_roidaico_meta_description', $meta_description );
                update_post_meta( $post_id, '_roidaico_focus_keyword', $focus_keyword );
                break;
        }
    }

    /**
     * Detect active SEO plugin
     */
    private function detect_seo_plugin() {
        $setting = get_option( 'roidaico_seo_plugin', 'auto' );
        if ( $setting !== 'auto' ) {
            return $setting;
        }
        // Auto-detect
        if ( defined( 'WPSEO_VERSION' ) || class_exists( 'WPSEO_Meta' ) ) {
            return 'yoast';
        }
        if ( class_exists( 'RankMath' ) || defined( 'RANK_MATH_VERSION' ) ) {
            return 'rankmath';
        }
        return 'none';
    }

    /**
     * Log generation for tracking
     */
    private function log_generation( $post_id, $keyword_id, $schedule_id = null ) {
        global $wpdb;
        $table = $wpdb->prefix . 'roidaico_posts_log';
        $wpdb->insert( $table, array(
            'post_id'      => $post_id,
            'keyword_id'   => $keyword_id,
            'schedule_id'  => $schedule_id,
            'generated_at' => current_time( 'mysql' ),
        ), array(
            '%d',
            '%d',
            '%d',
            '%s'
        ) );
    }

    /**
     * Get generation statistics
     */
    public function get_stats( $days = 30 ) {
        global $wpdb;
        $table = $wpdb->prefix . 'roidaico_posts_log';
        $date_from = date( 'Y-m-d H:i:s', strtotime( "-{$days} days" ) );
        return $wpdb->get_results( $wpdb->prepare( "SELECT DATE(generated_at) as date, COUNT(*) as count \r\n            FROM {$table} \r\n            WHERE generated_at >= %s \r\n            GROUP BY DATE(generated_at) \r\n            ORDER BY date DESC", $date_from ) );
    }

    /**
     * Convert and compress raw image binary to webp format using GD
     */
    private function convert_to_webp( $image_data, $quality = 80 ) {
        if ( !function_exists( 'imagecreatefromstring' ) || !function_exists( 'imagewebp' ) ) {
            return $image_data;
            // Fallback: return original if GD is missing
        }
        $image = @imagecreatefromstring( $image_data );
        if ( !$image ) {
            return $image_data;
        }
        // Enable alpha blending and save alpha for transparent images
        imagealphablending( $image, false );
        imagesavealpha( $image, true );
        ob_start();
        $success = imagewebp( $image, null, $quality );
        $webp_data = ob_get_clean();
        imagedestroy( $image );
        if ( $success && !empty( $webp_data ) ) {
            return $webp_data;
        }
        return $image_data;
    }

    /**
     * Save binary image data as a WordPress attachment
     */
    private function save_binary_as_image( $image_binary, $alt_text, $post_id = 0 ) {
        require_once ABSPATH . 'wp-admin/includes/file.php';
        require_once ABSPATH . 'wp-admin/includes/media.php';
        require_once ABSPATH . 'wp-admin/includes/image.php';
        // Detect MIME type from binary headers
        $finfo = new \finfo(FILEINFO_MIME_TYPE);
        $mime_type = $finfo->buffer( $image_binary );
        $extension = 'jpg';
        if ( $mime_type === 'image/webp' ) {
            $extension = 'webp';
        } elseif ( $mime_type === 'image/png' ) {
            $extension = 'png';
        } elseif ( $mime_type === 'image/gif' ) {
            $extension = 'gif';
        }
        $slug = sanitize_title( $alt_text );
        if ( empty( $slug ) ) {
            $slug = 'ai-image';
        }
        $filename = sanitize_file_name( $slug . '-' . time() . '-' . rand( 100, 999 ) . '.' . $extension );
        // Save binary to a temporary file
        $upload_dir = wp_upload_dir();
        if ( $upload_dir['error'] ) {
            return new \WP_Error('upload_dir_error', $upload_dir['error']);
        }
        $temp_filepath = $upload_dir['path'] . '/' . $filename;
        $saved = file_put_contents( $temp_filepath, $image_binary );
        if ( $saved === false ) {
            return new \WP_Error('write_file_error', __( 'Could not write temporary image file.', 'roidnet-ai-content-generator' ));
        }
        // Prepare file array
        $file_array = array(
            'name'     => $filename,
            'tmp_name' => $temp_filepath,
        );
        // Upload to media library
        $attachment_id = media_handle_sideload( $file_array, $post_id, $alt_text );
        // Clean up temp file if still exists
        if ( file_exists( $temp_filepath ) ) {
            @unlink( $temp_filepath );
        }
        if ( is_wp_error( $attachment_id ) ) {
            return $attachment_id;
        }
        // Update alt text
        update_post_meta( $attachment_id, '_wp_attachment_image_alt', $alt_text );
        return $attachment_id;
    }

    /**
     * Handle Polylang / WPML translation linking
     */
    private function handle_multilingual_linking( $keyword_id, $new_post_id, $post_type = 'post' ) {
        global $wpdb;
        $keyword_manager = new Keyword_Manager();
        $current_keyword = $keyword_manager->get_keyword( $keyword_id );
        if ( !$current_keyword ) {
            return;
        }
        $current_lang = ( !empty( $current_keyword->language ) ? $current_keyword->language : 'en' );
        // 1. If this keyword is a translation of a parent keyword
        if ( !empty( $current_keyword->translation_of ) ) {
            $parent_keyword = $keyword_manager->get_keyword( $current_keyword->translation_of );
            if ( $parent_keyword && !empty( $parent_keyword->post_id ) ) {
                $this->link_wp_posts(
                    $parent_keyword->post_id,
                    $new_post_id,
                    ( !empty( $parent_keyword->language ) ? $parent_keyword->language : 'en' ),
                    $current_lang,
                    $post_type
                );
            }
        }
        // 2. If other keywords are translations of this keyword
        $table = $wpdb->prefix . 'roidaico_keywords';
        $translations = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$table} WHERE translation_of = %d AND post_id IS NOT NULL AND post_id > 0", $keyword_id ) );
        if ( !empty( $translations ) ) {
            foreach ( $translations as $trans_kw ) {
                $this->link_wp_posts(
                    $new_post_id,
                    $trans_kw->post_id,
                    $current_lang,
                    ( !empty( $trans_kw->language ) ? $trans_kw->language : 'en' ),
                    $post_type
                );
            }
        }
    }

    /**
     * Link two posts as translations in Polylang or WPML
     */
    private function link_wp_posts(
        $post_id_1,
        $post_id_2,
        $lang_1,
        $lang_2,
        $post_type = 'post'
    ) {
        // Polylang
        if ( function_exists( 'pll_get_post_translations' ) && function_exists( 'pll_save_post_translations' ) ) {
            $translations = ( pll_get_post_translations( $post_id_1 ) ?: array() );
            $translations_2 = ( pll_get_post_translations( $post_id_2 ) ?: array() );
            $merged_translations = array_merge( $translations, $translations_2 );
            $merged_translations[$lang_1] = $post_id_1;
            $merged_translations[$lang_2] = $post_id_2;
            pll_save_post_translations( $merged_translations );
            Action_Logger::log( 'multilingual', sprintf(
                __( 'Polylang: Linked post %d (%s) and post %d (%s)', 'roidnet-ai-content-generator' ),
                $post_id_1,
                $lang_1,
                $post_id_2,
                $lang_2
            ), 'success' );
        }
        // WPML
        if ( has_action( 'wpml_set_element_language_details' ) ) {
            $element_type = 'post_' . $post_type;
            $trid = apply_filters(
                'wpml_element_trid',
                null,
                $post_id_1,
                $element_type
            );
            if ( !$trid ) {
                $trid = apply_filters(
                    'wpml_element_trid',
                    null,
                    $post_id_2,
                    $element_type
                );
            }
            if ( !$trid ) {
                do_action( 'wpml_set_element_language_details', array(
                    'element_id'           => $post_id_1,
                    'element_type'         => $element_type,
                    'trid'                 => null,
                    'language_code'        => $lang_1,
                    'source_language_code' => null,
                ) );
                $trid = apply_filters(
                    'wpml_element_trid',
                    null,
                    $post_id_1,
                    $element_type
                );
            }
            if ( $trid ) {
                do_action( 'wpml_set_element_language_details', array(
                    'element_id'           => $post_id_2,
                    'element_type'         => $element_type,
                    'trid'                 => $trid,
                    'language_code'        => $lang_2,
                    'source_language_code' => $lang_1,
                ) );
                Action_Logger::log( 'multilingual', sprintf(
                    __( 'WPML: Linked post %d (%s) and post %d (%s) via TRID %d', 'roidnet-ai-content-generator' ),
                    $post_id_1,
                    $lang_1,
                    $post_id_2,
                    $lang_2,
                    $trid
                ), 'success' );
            }
        }
    }

    /**
     * Find and generate pending translations in the same group to process them together
     */
    private function generate_group_translations( $keyword_id, $options = array() ) {
        // Prevent recursion
        if ( !empty( $options['is_translation_group_run'] ) ) {
            return;
        }
        global $wpdb;
        $keyword_manager = new Keyword_Manager();
        $current_keyword = $keyword_manager->get_keyword( $keyword_id );
        if ( !$current_keyword ) {
            return;
        }
        // Determine parent keyword ID
        $parent_id = ( !empty( $current_keyword->translation_of ) ? $current_keyword->translation_of : $current_keyword->id );
        // Find all other pending keywords in this group (parent + children)
        $table = $wpdb->prefix . 'roidaico_keywords';
        $group_keywords = $wpdb->get_results( $wpdb->prepare(
            "SELECT id FROM {$table} WHERE (id = %d OR translation_of = %d) AND id != %d AND status = 'pending'",
            $parent_id,
            $parent_id,
            $keyword_id
        ) );
        if ( !empty( $group_keywords ) ) {
            $options['is_translation_group_run'] = true;
            foreach ( $group_keywords as $kw ) {
                // Generate content for the sibling translation keyword
                $this->generate_from_keyword( $kw->id, $options );
            }
        }
    }

}
