<?php
/**
 * Publishes content approved by email replies.
 *
 * @package Aysa
 */

if (!defined('ABSPATH')) {
    exit;
}

class Aysa_Content_Email_Publisher {
    const CRON_HOOK = 'aysa_content_email_approval_publish_cron';
    const LOCK_KEY = 'aysa_content_email_approval_publish_lock';

    public static function init() {
        $instance = new self();
        add_filter('cron_schedules', array($instance, 'register_cron_schedules'));
        add_action(self::CRON_HOOK, array($instance, 'process_pending_publications'));
        add_action('init', array($instance, 'ensure_cron_scheduled'));
        add_action('init', array($instance, 'maybe_backfill_published_email_posts'), 20);
    }

    public function register_cron_schedules($schedules) {
        if (!isset($schedules['aysa_content_email_5min'])) {
            $schedules['aysa_content_email_5min'] = array(
                'interval' => 5 * 60,
                'display' => __('Every 5 Minutes (AYSA Content Email)', 'aysaaiseo'),
            );
        }
        return $schedules;
    }

    public function ensure_cron_scheduled() {
        if (!wp_next_scheduled(self::CRON_HOOK)) {
            wp_schedule_event(time() + 60, 'aysa_content_email_5min', self::CRON_HOOK);
        }
    }

    public static function deactivate() {
        wp_clear_scheduled_hook(self::CRON_HOOK);
    }

    public function maybe_backfill_published_email_posts() {
        if (get_transient('aysa_content_email_backfill_lock_v2')) {
            return false;
        }
        set_transient('aysa_content_email_backfill_lock_v2', 1, MINUTE_IN_SECONDS);
        return $this->backfill_published_email_posts();
    }

    public function process_pending_publications() {
        $project_id = intval(get_option('aysa_project_id', 0));
        if ($project_id <= 0 || get_transient(self::LOCK_KEY)) {
            return false;
        }

        set_transient(self::LOCK_KEY, 1, 4 * MINUTE_IN_SECONDS);
        try {
            $response = $this->api_request('v1/content/email-approval/pending-publications', array(
                'project_id' => $project_id,
            ));
            if (empty($response['ok']) || empty($response['items']) || !is_array($response['items'])) {
                return $this->backfill_published_email_posts();
            }

            $processed = false;
            foreach ($response['items'] as $item) {
                if (!is_array($item)) {
                    continue;
                }
                $post_id = $this->publish_item($item);
                if ($post_id > 0) {
                    $this->mark_published($item, $post_id);
                    $processed = true;
                }
            }
            return $this->backfill_published_email_posts() || $processed;
        } finally {
            delete_transient(self::LOCK_KEY);
        }
    }

    private function publish_item(array $item) {
        $approval_id = intval($item['approval_id'] ?? 0);
        $project_id = intval($item['project_id'] ?? 0);
        $article = isset($item['article']) && is_array($item['article']) ? $item['article'] : array();
        if ($approval_id <= 0 || $project_id <= 0 || empty($article)) {
            return 0;
        }

        $existing_post_id = intval(get_option($this->published_option_key($approval_id), 0));
        if ($existing_post_id > 0 && get_post($existing_post_id)) {
            return $existing_post_id;
        }

        $existing = get_posts(array(
            'post_type' => 'post',
            'post_status' => array('publish', 'future', 'draft', 'pending', 'private'),
            // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- Reviewed WordPress query: the metadata selector is required by the feature and is constrained by the surrounding post type, status, limit, or administrative scope.
            'meta_key' => '_aysa_content_email_approval_id',
            // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value -- Reviewed WordPress query: the metadata selector is required by the feature and is constrained by the surrounding post type, status, limit, or administrative scope.
            'meta_value' => (string) $approval_id,
            'fields' => 'ids',
            'posts_per_page' => 1,
            'no_found_rows' => true,
        ));
        if (!empty($existing[0])) {
            update_option($this->published_option_key($approval_id), intval($existing[0]), false);
            return intval($existing[0]);
        }

        $title = sanitize_text_field((string) ($article['title'] ?? ''));
        $body_html = (string) ($article['body_html'] ?? '');
        if ($title === '' || trim(wp_strip_all_tags($body_html)) === '') {
            return 0;
        }

        $publish_time = $this->next_content_email_publish_time();
        $post_id = wp_insert_post(array(
            'post_title' => $title,
            'post_name' => $this->build_article_url_slug($article, $title),
            'post_content' => wp_kses_post($body_html),
            'post_excerpt' => sanitize_textarea_field((string) ($article['excerpt'] ?? '')),
            'post_status' => 'future',
            'post_date' => get_date_from_gmt(gmdate('Y-m-d H:i:s', $publish_time)),
            'post_date_gmt' => gmdate('Y-m-d H:i:s', $publish_time),
            'post_type' => 'post',
            'post_author' => $this->publisher_user_id(),
        ), true);
        if (is_wp_error($post_id)) {
            $this->log_error('content_email_publish_failed', $post_id->get_error_message(), $approval_id);
            return 0;
        }

        $post_id = intval($post_id);
        update_post_meta($post_id, '_aysa_content_email_approval_id', $approval_id);
        update_post_meta($post_id, '_aysa_content_email_project_id', $project_id);
        update_post_meta($post_id, '_aysa_generation_source', 'content-email-approval');
        update_post_meta($post_id, '_aysa_competitor_title', sanitize_text_field((string) ($item['competitor_title'] ?? '')));
        update_post_meta($post_id, '_aysa_competitor_url', esc_url_raw((string) ($item['competitor_url'] ?? '')));
        update_post_meta($post_id, '_aysa_content_email_scheduled_for', gmdate('c', $publish_time));
        $this->persist_seo_meta($post_id, $article);
        $this->persist_tags($post_id, $article);
        $this->persist_category($post_id, $article);
        $this->persist_article_images($post_id, $article);
        update_option($this->published_option_key($approval_id), $post_id, false);

        return $post_id;
    }

    private function next_content_email_publish_time() {
        $base = time();
        $latest = get_posts(array(
            'post_type' => 'post',
            'post_status' => 'future',
            // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- Reviewed WordPress query: the metadata selector is required by the feature and is constrained by the surrounding post type, status, limit, or administrative scope.
            'meta_key' => '_aysa_generation_source',
            // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value -- Reviewed WordPress query: the metadata selector is required by the feature and is constrained by the surrounding post type, status, limit, or administrative scope.
            'meta_value' => 'content-email-approval',
            'orderby' => 'date',
            'order' => 'DESC',
            'fields' => 'ids',
            'posts_per_page' => 1,
            'no_found_rows' => true,
        ));
        if (!empty($latest[0])) {
            $future_ts = get_post_time('U', true, intval($latest[0]));
            if ($future_ts && $future_ts > $base) {
                $base = $future_ts;
            }
        }

        return $base + wp_rand(DAY_IN_SECONDS, 2 * DAY_IN_SECONDS);
    }

    private function build_article_url_slug(array $article, $title) {
        $source_parts = array();
        foreach (array('slug', 'url_recomandat', 'primary_keyword') as $key) {
            $value = trim((string) ($article[$key] ?? ''));
            if ($value !== '') {
                $path = (string) wp_parse_url($value, PHP_URL_PATH);
                $source_parts[] = $path !== '' ? basename(trim($path, '/')) : $value;
            }
        }
        foreach (array_slice((array) ($article['secondary_keywords'] ?? $article['keywords'] ?? array()), 0, 4) as $keyword) {
            $source_parts[] = (string) $keyword;
        }
        $source_parts[] = (string) $title;

        $stopwords = array(
            'a','ai','ale','al','asta','acest','aceasta','aceste','acesti','acestia','acolo','asa',
            'ca','care','cat','cât','cand','când','ce','cea','cele','cel','cei','cum','cu',
            'de','din','dupa','după','este','fara','fără','fi','fie','in','în','intre','între',
            'la','mai','mult','nu','o','pe','pentru','prin','sau','sa','să','si','și','spre',
            'the','and','or','for','with','from','into','how','what','when','where','why','your'
        );
        $stop = array_fill_keys(array_map('remove_accents', $stopwords), true);
        $tokens = array();
        $seen = array();
        foreach ($source_parts as $part) {
            foreach (explode('-', sanitize_title((string) $part)) as $token) {
                $token = trim((string) $token);
                $token_key = remove_accents($token);
                if ($token === '' || ((strlen($token_key) < 3 && !preg_match('/^\d+$/', $token_key)) || isset($stop[$token_key]) || isset($seen[$token_key]))) {
                    continue;
                }
                $seen[$token_key] = true;
                $tokens[] = $token;
            }
        }
        if (empty($tokens)) {
            return sanitize_title((string) $title);
        }

        $base_url_length = mb_strlen(home_url('/'));
        $ideal_slug_chars = max(42, 80 - $base_url_length);
        $max_slug_chars = max($ideal_slug_chars, 120 - $base_url_length);
        $slug = '';
        foreach ($tokens as $token) {
            $candidate = $slug === '' ? $token : $slug . '-' . $token;
            if (mb_strlen($candidate) > $max_slug_chars) {
                break;
            }
            $slug = $candidate;
            if (mb_strlen(home_url('/' . $slug . '/')) >= 50 && mb_strlen($slug) >= $ideal_slug_chars) {
                break;
            }
        }
        return $slug !== '' ? $slug : sanitize_title((string) $title);
    }

    private function mark_published(array $item, $post_id) {
        $approval_id = intval($item['approval_id'] ?? 0);
        $project_id = intval($item['project_id'] ?? 0);
        if ($approval_id <= 0 || $project_id <= 0 || intval($post_id) <= 0) {
            return false;
        }

        $response = $this->api_request('v1/content/email-approval/mark-published', array(
            'approval_id' => $approval_id,
            'project_id' => $project_id,
            'post_id' => intval($post_id),
            'published_url' => get_permalink($post_id),
        ));
        return !empty($response['ok']);
    }

    private function api_request($endpoint, array $payload) {
        $token = $this->bearer_token();
        if ($token === '') {
            return false;
        }

        $base_url = class_exists('Aysa_API_Config') ? Aysa_API_Config::get_api_base_url() : (defined('AYSA_API_BASE_URL') ? AYSA_API_BASE_URL : 'https://api.aysa.ai/');
        $response = wp_remote_post(rtrim((string) $base_url, '/') . '/' . ltrim($endpoint, '/'), array(
            'timeout' => 30,
            'headers' => array(
                'Accept' => 'application/json',
                'Content-Type' => 'application/json',
                'Authorization' => 'Bearer ' . $token,
            ),
            'body' => wp_json_encode($payload),
        ));
        if (is_wp_error($response)) {
            $this->log_error('content_email_api_http_failed', $response->get_error_message(), intval($payload['approval_id'] ?? 0));
            return false;
        }

        $code = intval(wp_remote_retrieve_response_code($response));
        $body = json_decode((string) wp_remote_retrieve_body($response), true);
        if ($code < 200 || $code >= 300 || !is_array($body)) {
            $this->log_error('content_email_api_invalid_response', 'API returned an invalid response.', intval($payload['approval_id'] ?? 0));
            return false;
        }
        return $body;
    }

    private function bearer_token() {
        $token = trim((string) get_option('aysa_user_secret_key', ''));
        if ($token !== '') {
            return $token;
        }

        $auth_data = get_option('aysa_activator_auth_data', array());
        if (is_array($auth_data)) {
            $token = trim((string) ($auth_data['secret_key'] ?? ''));
            if ($token !== '') {
                return $token;
            }
        }
        return '';
    }

    private function persist_seo_meta($post_id, array $article) {
        $meta_title = sanitize_text_field((string) ($article['meta_title'] ?? ''));
        $meta_description = sanitize_textarea_field((string) ($article['meta_description'] ?? ''));
        if ($meta_title !== '') {
            update_post_meta($post_id, '_aysa_seo_title', $meta_title);
            update_post_meta($post_id, '_aysa_meta_title', $meta_title);
            update_post_meta($post_id, '_yoast_wpseo_title', $meta_title);
            update_post_meta($post_id, 'rank_math_title', $meta_title);
        }
        if ($meta_description !== '') {
            update_post_meta($post_id, '_aysa_seo_description', $meta_description);
            update_post_meta($post_id, '_aysa_meta_description', $meta_description);
            update_post_meta($post_id, '_yoast_wpseo_metadesc', $meta_description);
            update_post_meta($post_id, 'rank_math_description', $meta_description);
        }
    }

    private function persist_tags($post_id, array $article) {
        $tags = isset($article['tags']) && is_array($article['tags']) ? $article['tags'] : array();
        if (empty($tags)) {
            $tags = $this->fallback_tags($article);
        }
        $tags = array_values(array_filter(array_map(static function($tag) {
            return sanitize_text_field((string) $tag);
        }, $tags)));
        if (!empty($tags)) {
            wp_set_post_terms($post_id, $tags, 'post_tag', false);
        }
    }

    private function persist_category($post_id, array $article) {
        $category_name = sanitize_text_field((string) ($article['category'] ?? ''));
        if ($category_name === '') {
            $category_name = 'Blog';
        }

        $term = term_exists($category_name, 'category');
        if (!$term) {
            $term = wp_insert_term($category_name, 'category');
        }
        if (is_wp_error($term)) {
            return;
        }

        $term_id = is_array($term) ? intval($term['term_id'] ?? 0) : intval($term);
        if ($term_id > 0) {
            wp_set_post_terms($post_id, array($term_id), 'category', false);
        }
    }

    private function persist_article_images($post_id, array $article) {
        $slots = isset($article['image_slots']) && is_array($article['image_slots']) ? array_values($article['image_slots']) : array();
        if (empty($slots)) {
            $primary_keyword = sanitize_text_field((string) ($article['primary_keyword'] ?? ''));
            if ($primary_keyword === '') {
                $primary_keyword = sanitize_text_field((string) get_the_title($post_id));
            }
            update_post_meta($post_id, '_aysa_article_image_retry_pending', '1');
            update_post_meta($post_id, '_aysa_article_image_retry_roles', array('featured', 'inline_primary'));
            update_post_meta($post_id, '_aysa_article_image_retry_context', array(
                'article_topic' => get_the_title($post_id),
                'primary_keyword' => $primary_keyword,
                'secondary_keywords' => array(),
                'language' => (string) get_option('aysa_language', 'ro'),
                'brand_name' => (string) get_option('aysa_brand_name', get_bloginfo('name')),
                'queued_at' => current_time('mysql'),
                'attempts' => 0,
            ));
            if (!wp_next_scheduled('aysa_process_article_images_now', array($post_id))) {
                wp_schedule_single_event(time() + 60, 'aysa_process_article_images_now', array($post_id));
            }
            return;
        }

        foreach ($slots as $slot) {
            if (!is_array($slot)) {
                continue;
            }
            $role = sanitize_key((string) ($slot['slot'] ?? $slot['role'] ?? ''));
            $url = esc_url_raw((string) ($slot['image_url'] ?? $slot['url'] ?? ''));
            if ($url === '') {
                continue;
            }
            $meta = array(
                'alt_text' => (string) ($slot['alt_text'] ?? ''),
                'title' => (string) ($slot['title'] ?? ''),
                'caption' => (string) ($slot['caption'] ?? ''),
                'description' => (string) ($slot['description'] ?? ''),
            );
            if ($role === 'featured' && !has_post_thumbnail($post_id)) {
                $this->download_and_set_featured_image($post_id, $url, $meta);
            } elseif (in_array($role, array('inline', 'inline_primary', 'middle', 'pre_final'), true)) {
                $inline = $this->download_inline_image($post_id, $url, $meta);
                if (is_array($inline)) {
                    $content = (string) get_post_field('post_content', $post_id);
                    wp_update_post(array(
                        'ID' => intval($post_id),
                        'post_content' => $this->insert_inline_image_figure($content, $inline),
                    ));
                }
                break;
            }
        }
    }

    private function download_and_set_featured_image($post_id, $image_url, array $image_meta = array()) {
        $attachment_id = $this->sideload_image($post_id, $image_url, $image_meta, 'AYSA Generated Featured Image');
        if ($attachment_id <= 0) {
            return false;
        }
        set_post_thumbnail($post_id, $attachment_id);
        return true;
    }

    private function download_inline_image($post_id, $image_url, array $image_meta = array()) {
        $attachment_id = $this->sideload_image($post_id, $image_url, $image_meta, 'AYSA Generated Inline Article Image');
        if ($attachment_id <= 0) {
            return false;
        }
        return array(
            'attachment_id' => $attachment_id,
            'url' => wp_get_attachment_url($attachment_id),
            'alt_text' => get_post_meta($attachment_id, '_wp_attachment_image_alt', true),
            'caption' => get_post_field('post_excerpt', $attachment_id),
        );
    }

    private function sideload_image($post_id, $image_url, array $image_meta, $description) {
        if (!function_exists('media_handle_sideload')) {
            require_once ABSPATH . 'wp-admin/includes/media.php';
            require_once ABSPATH . 'wp-admin/includes/file.php';
            require_once ABSPATH . 'wp-admin/includes/image.php';
        }

        $tmp = download_url($image_url, 45);
        if (is_wp_error($tmp)) {
            return 0;
        }

        $path = wp_parse_url($image_url, PHP_URL_PATH);
        $name = basename((string) $path);
        if ($name === '' || strpos($name, '.') === false) {
            $name = 'aysa-article-' . intval($post_id) . '.png';
        }

        $attachment_id = media_handle_sideload(array(
            'name' => sanitize_file_name($name),
            'tmp_name' => $tmp,
        ), $post_id, $description);
        if (is_wp_error($attachment_id)) {
            wp_delete_file($tmp);
            return 0;
        }

        $alt_text = sanitize_text_field((string) ($image_meta['alt_text'] ?? ''));
        if ($alt_text !== '') {
            update_post_meta($attachment_id, '_wp_attachment_image_alt', $alt_text);
        }
        wp_update_post(array(
            'ID' => intval($attachment_id),
            'post_title' => sanitize_text_field((string) ($image_meta['title'] ?? get_the_title($post_id))),
            'post_excerpt' => sanitize_text_field((string) ($image_meta['caption'] ?? '')),
            'post_content' => wp_kses_post((string) ($image_meta['description'] ?? '')),
        ));

        return intval($attachment_id);
    }

    private function insert_inline_image_figure($content, array $image) {
        $url = esc_url((string) ($image['url'] ?? ''));
        if ($url === '') {
            return $content;
        }
        $alt = esc_attr((string) ($image['alt_text'] ?? ''));
        $caption = sanitize_text_field((string) ($image['caption'] ?? ''));
        $figure = '<figure class="aysa-article-inline-image"><img src="' . $url . '" alt="' . $alt . '" loading="lazy">';
        if ($caption !== '') {
            $figure .= '<figcaption>' . esc_html($caption) . '</figcaption>';
        }
        $figure .= '</figure>';

        $parts = preg_split('/(<\/p>)/i', (string) $content, -1, PREG_SPLIT_DELIM_CAPTURE);
        if (!is_array($parts) || count($parts) < 4) {
            return $content . "\n\n" . $figure;
        }
        $insert_at = max(2, (int) floor(count($parts) / 2));
        array_splice($parts, $insert_at, 0, $figure);
        return implode('', $parts);
    }

    private function fallback_tags(array $article) {
        $text = wp_strip_all_tags((string) (($article['title'] ?? '') . ' ' . ($article['body_html'] ?? '')));
        $candidates = array_filter(array_map('trim', preg_split('/[,;\\n]+/', (string) ($article['primary_keyword'] ?? '')) ?: array()));
        foreach (preg_split('/\\s+/', mb_strtolower($text)) ?: array() as $word) {
            $word = trim((string) preg_replace('/[^[:alnum:]ăâîșțĂÂÎȘȚ-]+/u', '', $word));
            if (mb_strlen($word) < 5 || in_array($word, array('pentru', 'despre', 'aceste', 'acest', 'aceasta', 'florile'), true)) {
                continue;
            }
            $candidates[] = $word;
            if (count($candidates) >= 6) {
                break;
            }
        }
        return array_slice(array_values(array_unique($candidates)), 0, 6);
    }

    private function backfill_published_email_posts() {
        $query = new WP_Query(array(
            'post_type' => 'post',
            'post_status' => 'publish',
            'fields' => 'ids',
            'posts_per_page' => 5,
            'no_found_rows' => true,
            // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Reviewed WordPress query: the metadata selector is required by the feature and is constrained by the surrounding post type, status, limit, or administrative scope.
            'meta_query' => array(
                array(
                    'key' => '_aysa_content_email_approval_id',
                    'compare' => 'EXISTS',
                ),
            ),
        ));
        $changed = false;
        foreach (array_map('intval', (array) $query->posts) as $post_id) {
            if ($post_id <= 0) {
                continue;
            }
            $article = array(
                'title' => get_the_title($post_id),
                'body_html' => (string) get_post_field('post_content', $post_id),
                'primary_keyword' => get_post_meta($post_id, '_aysa_main_keyword', true),
                'category' => 'Blog',
            );
            if (empty(wp_get_post_terms($post_id, 'post_tag', array('fields' => 'ids')))) {
                $this->persist_tags($post_id, $article);
                $changed = true;
            }
            $categories = wp_get_post_terms($post_id, 'category', array('fields' => 'ids'));
            if (empty($categories) || (count($categories) === 1 && intval($categories[0]) === 1)) {
                $this->persist_category($post_id, $article);
                $changed = true;
            }
            if (!has_post_thumbnail($post_id) && get_post_meta($post_id, '_aysa_article_image_retry_pending', true) === '') {
                $this->persist_article_images($post_id, $article);
                $changed = true;
            } elseif (!has_post_thumbnail($post_id) && get_post_meta($post_id, '_aysa_article_image_retry_pending', true) !== '') {
                $retry_status = (string) get_post_meta($post_id, '_aysa_article_image_retry_pending', true);
                $context = get_post_meta($post_id, '_aysa_article_image_retry_context', true);
                if (is_array($context) && trim((string) ($context['primary_keyword'] ?? '')) === '') {
                    $context['primary_keyword'] = sanitize_text_field((string) get_the_title($post_id));
                    $context['article_topic'] = sanitize_text_field((string) get_the_title($post_id));
                    $context['attempts'] = 0;
                    update_post_meta($post_id, '_aysa_article_image_retry_context', $context);
                    $changed = true;
                }
                if ($retry_status === 'failed') {
                    if (is_array($context)) {
                        $context['attempts'] = 0;
                        update_post_meta($post_id, '_aysa_article_image_retry_context', $context);
                    }
                    update_post_meta($post_id, '_aysa_article_image_retry_pending', '1');
                    update_post_meta($post_id, '_aysa_article_image_retry_roles', array('featured', 'inline_primary'));
                    $changed = true;
                }
                if (!wp_next_scheduled('aysa_process_article_images_now', array($post_id))) {
                    wp_schedule_single_event(time() + 60, 'aysa_process_article_images_now', array($post_id));
                    $changed = true;
                }
            }
        }
        return $changed;
    }

    private function publisher_user_id() {
        $users = get_users(array(
            'role__in' => array('administrator', 'editor'),
            'number' => 1,
            'fields' => array('ID'),
        ));
        return !empty($users[0]->ID) ? intval($users[0]->ID) : 1;
    }

    private function published_option_key($approval_id) {
        return 'aysa_content_email_approval_post_' . intval($approval_id);
    }

    private function log_error($code, $message, $approval_id = 0) {
        if (function_exists('aysa_report_operational_error')) {
            aysa_report_operational_error(array(
                'source' => 'plugin',
                'module' => 'content_email_approval',
                'severity' => 'error',
                'error_code' => sanitize_key((string) $code),
                'message_safe' => sanitize_text_field((string) $message),
                'technical_context' => array(
                    'approval_id' => intval($approval_id),
                ),
            ));
            return;
        }
        aysa_debug_log('[AYSA Content Email] ' . $code . ': ' . $message);
    }
}
