<?php

namespace AIPT\Api\AutomationJobs;

use AIPT\Api\BulkGenerator\SeoMeta\Core\SeoMetaWriter;
use AIPT\Api\BulkGenerator\SeoMeta\Core\SeoPluginDetector;

/**
 * Draft Content Manager
 *
 * Handles CRUD operations for draft content generated by automation jobs
 *
 * @since 2.3.0
 */
class DraftContentManager {

    /**
     * WordPress database instance
     * @var \wpdb
     */
    private $wpdb;

    /**
     * Draft content table name
     * @var string
     */
    private $draft_table;

    /**
     * Constructor
     */
    public function __construct() {
        global $wpdb;
        $this->wpdb = $wpdb;
        $this->draft_table = $wpdb->prefix . 'aipt_draft_content';
    }

    /**
     * Save draft content
     *
     * @param int $job_id Job ID
     * @param int $product_id Product ID
     * @param string $content_type Content type (title, description, short_description, tags)
     * @param string $generated_content Generated content
     * @param string|null $original_content Original content
     * @param int|null $created_by User ID that owns the parent job/draft
     * @return int|false Draft content ID or false on failure
     */
    public function saveDraftContent($job_id, $product_id, $content_type, $generated_content, $original_content = null, $created_by = null) {
        try {

            if ($original_content === null) {
                $original_content = $this->getOriginalContent($product_id, $content_type);
            }

            $draft_created_by = $this->resolveDraftCreatedBy((int) $job_id, $created_by);

            $data = [
                'job_id' => $job_id,
                'product_id' => $product_id,
                'content_type' => $content_type,
                'original_content' => $original_content,
                'generated_content' => $generated_content,
                'status' => 'pending',
                'created_by' => $draft_created_by,
                'created_at' => current_time('mysql')
            ];

            $existing = $this->wpdb->get_row($this->wpdb->prepare(
                "SELECT id, status FROM {$this->draft_table}
                WHERE job_id = %d AND product_id = %d AND content_type = %s",
                $job_id, $product_id, $content_type
            ));

            if ($existing) {
                if ('pending' !== $existing->status) {
                    return false;
                }

                $result = $this->wpdb->update(
                    $this->draft_table,
                    [
                        'generated_content' => $generated_content,
                        'original_content' => $original_content,
                        'status' => 'pending',
                        'created_by' => $draft_created_by,
                        'updated_at' => current_time('mysql')
                    ],
                    ['id' => $existing->id, 'status' => 'pending'],
                    ['%s', '%s', '%s', '%d', '%s'],
                    ['%d', '%s']
                );

                return false !== $result ? (int) $existing->id : false;
            } else {

                $result = $this->wpdb->insert(
                    $this->draft_table,
                    $data,
                    ['%d', '%d', '%s', '%s', '%s', '%s', '%d', '%s']
                );

                return $result !== false ? $this->wpdb->insert_id : false;
            }

        } catch (\Exception $e) {
            return false;
        }
    }

    /**
     * Get original content from product
     *
     * @param int $product_id Product ID
     * @param string $content_type Content type
     * @return string Original content
     */
    private function getOriginalContent($product_id, $content_type) {
        $product = wc_get_product($product_id);
        if (!$product) {
            return '';
        }

        switch ($content_type) {
            case 'title':
                return $product->get_name();
            case 'description':
                return $product->get_description();
            case 'short_description':
                return $product->get_short_description();
            case 'tags':
                $tags = wp_get_post_terms($product_id, 'product_tag', ['fields' => 'names']);
                return is_array($tags) ? implode(', ', $tags) : '';
            case 'faq':
                $faq_data = get_post_meta($product_id, '_aipt_faq_data', true);
                return is_string($faq_data) ? $faq_data : '';
            case 'seo_meta':
                $detected_plugin = SeoPluginDetector::detect();
                if (null === $detected_plugin) {
                    return '';
                }
                $seo_info = SeoPluginDetector::get_seo_info($product_id, $detected_plugin);
                $original = [
                    'meta_title'       => $seo_info['meta_title'] ?? '',
                    'meta_description' => $seo_info['meta_description'] ?? '',
                    'focus_keyword'    => $seo_info['focus_keyword'] ?? '',
                ];
                $json = wp_json_encode($original);
                return $json !== false ? $json : '';
            case 'image_alt':
                $image_alt = $this->getProductImageAltData($product_id);
                $json = wp_json_encode($image_alt);
                return $json !== false ? $json : '';
            default:
                return '';
        }
    }

    /**
     * Get draft content by filters
     *
     * @param array $filters Filters (job_id, product_id, status, content_type)
     * @param int $limit Limit
     * @param int $offset Offset
     * @return array Draft content items
     */
    public function getDraftContent($filters = [], $limit = 50, $offset = 0) {
        $where_conditions = ['1=1'];
        $query_params = [];

        if (!empty($filters['job_id'])) {
            $where_conditions[] = 'dc.job_id = %d';
            $query_params[] = $filters['job_id'];
        }

        if (!empty($filters['product_id'])) {
            $where_conditions[] = 'dc.product_id = %d';
            $query_params[] = $filters['product_id'];
        }

        if (!empty($filters['status'])) {
            $where_conditions[] = 'dc.status = %s';
            $query_params[] = $filters['status'];
        }

        if (!empty($filters['content_type'])) {
            $where_conditions[] = 'dc.content_type = %s';
            $query_params[] = $filters['content_type'];
        }

        $query = "
            SELECT dc.*, p.post_title as product_name, j.name as job_name
            FROM {$this->draft_table} dc
            LEFT JOIN {$this->wpdb->posts} p ON dc.product_id = p.ID
            LEFT JOIN {$this->wpdb->prefix}aipt_automation_jobs j ON dc.job_id = j.id
            WHERE " . implode(' AND ', $where_conditions) . "
            ORDER BY dc.created_at DESC
            LIMIT %d OFFSET %d
        ";

        $query_params[] = $limit;
        $query_params[] = $offset;

        if (!empty($query_params)) {
            return $this->wpdb->get_results($this->wpdb->prepare($query, $query_params));
        } else {
            return $this->wpdb->get_results($query);
        }

    }

    /**
     * Get draft content count
     *
     * @param array $filters Filters
     * @return int Count
     */
    public function getDraftContentCount($filters = []) {
        $where_conditions = ['1=1'];
        $query_params = [];

        if (!empty($filters['job_id'])) {
            $where_conditions[] = 'job_id = %d';
            $query_params[] = $filters['job_id'];
        }

        if (!empty($filters['product_id'])) {
            $where_conditions[] = 'product_id = %d';
            $query_params[] = $filters['product_id'];
        }

        if (!empty($filters['status'])) {
            $where_conditions[] = 'status = %s';
            $query_params[] = $filters['status'];
        }

        if (!empty($filters['content_type'])) {
            $where_conditions[] = 'content_type = %s';
            $query_params[] = $filters['content_type'];
        }

        $query = "
            SELECT COUNT(*)
            FROM {$this->draft_table}
            WHERE " . implode(' AND ', $where_conditions);

        if (!empty($query_params)) {
            return (int) $this->wpdb->get_var($this->wpdb->prepare($query, $query_params));
        } else {
            return (int) $this->wpdb->get_var($query);
        }

    }

    /**
     * Approve draft content and apply to product
     *
     * @param int $draft_id Draft content ID
     * @return bool Success status
     */
    public function approveDraftContent($draft_id) {
        $draft_id = absint($draft_id);
        $claimed = false;

        try {
            if ($draft_id <= 0) {
                throw new \Exception('Invalid draft content ID');
            }

            $claimed_by = (int) get_current_user_id();
            $now = current_time('mysql');

            $claim_result = $this->wpdb->update(
                $this->draft_table,
                [
                    'status' => 'in_progress',
                    'approved_by' => $claimed_by,
                    'updated_at' => $now,
                ],
                [
                    'id' => $draft_id,
                    'status' => 'pending',
                ],
                ['%s', '%d', '%s'],
                ['%d', '%s']
            );

            if ($claim_result === false) {
                throw new \Exception('Failed to claim draft content');
            }

            if ((int) $claim_result < 1) {
                throw new \Exception('Draft content is not pending or is already being processed');
            }

            $claimed = true;

            $draft = $this->wpdb->get_row($this->wpdb->prepare(
                "SELECT * FROM {$this->draft_table} WHERE id = %d AND status = %s",
                $draft_id,
                'in_progress'
            ));

            if (!$draft) {
                throw new \Exception('Draft content not found');
            }

            $write_mode = 'append';
            if ($draft->content_type === 'faq') {
                $write_mode = $this->resolveFaqWriteMode((int) $draft->job_id);
            }

            $success = $this->applyContentToProduct(
                $draft->product_id,
                $draft->content_type,
                $draft->generated_content,
                $write_mode
            );

            if ($success) {

                $final_result = $this->wpdb->update(
                    $this->draft_table,
                    [
                        'status' => 'approved',
                        'approved_by' => $claimed_by,
                        'approved_at' => current_time('mysql'),
                        'updated_at' => current_time('mysql')
                    ],
                    ['id' => $draft_id, 'status' => 'in_progress'],
                    ['%s', '%d', '%s', '%s'],
                    ['%d', '%s']
                );

                if (false === $final_result || (int) $final_result < 1) {
                    $this->releaseDraftClaim($draft_id);
                    return false;
                }

                return true;
            }

            $this->releaseDraftClaim($draft_id);

            return false;

        } catch (\Exception $e) {
            if ($claimed) {
                $this->releaseDraftClaim($draft_id);
            }
            return false;
        }
    }

    private function resolveDraftCreatedBy($job_id, $created_by = null) {
        if (null !== $created_by && (int) $created_by > 0) {
            return (int) $created_by;
        }

        $jobs_table = $this->wpdb->prefix . 'aipt_automation_jobs';

        $job_created_by = $this->wpdb->get_var($this->wpdb->prepare(
            "SELECT created_by FROM {$jobs_table} WHERE id = %d",
            $job_id
        ));

        if ((int) $job_created_by > 0) {
            return (int) $job_created_by;
        }

        return (int) get_current_user_id();
    }

    private function releaseDraftClaim($draft_id) {
        $this->wpdb->update(
            $this->draft_table,
            [
                'status' => 'pending',
                'approved_by' => null,
                'updated_at' => current_time('mysql'),
            ],
            [
                'id' => $draft_id,
                'status' => 'in_progress',
            ],
            ['%s', '%d', '%s'],
            ['%d', '%s']
        );
    }

    /**
     * Apply content to product
     *
     * @param int    $product_id  Product ID
     * @param string $content_type Content type
     * @param string $content     Content to apply
     * @param string $write_mode  Write mode for FAQ content ('append' or 'replace')
     * @return bool Success status
     */
    private function applyContentToProduct($product_id, $content_type, $content, $write_mode = 'append') {
        try {
            $product = wc_get_product($product_id);
            if (!$product) {
                return false;
            }

            switch ($content_type) {
                case 'title':
                    $product->set_name($content);
                    break;
                case 'description':
                    $product->set_description($content);
                    break;
                case 'short_description':
                    $product->set_short_description($content);
                    break;
                case 'tags':
                    $tag_names = array_map('trim', explode(',', $content));
                    $tag_ids = [];
                    foreach ($tag_names as $tag_name) {
                        if (!empty($tag_name)) {
                            $term = get_term_by('name', $tag_name, 'product_tag');
                            if (!$term) {
                                $term = wp_insert_term($tag_name, 'product_tag');
                                if (!is_wp_error($term)) {
                                    $tag_ids[] = $term['term_id'];
                                }
                            } else {
                                $tag_ids[] = $term->term_id;
                            }
                        }
                    }
                    wp_set_post_terms($product_id, $tag_ids, 'product_tag');
                    break;
                case 'faq':
                    return $this->applyFaqContent($product_id, $content, $write_mode);
                case 'seo_meta':
                    return $this->applySeoMetaContent($product_id, $content);
                case 'image_alt':
                    return $this->applyImageAltContent($product_id, $content);
                default:
                    return false;
            }

            if ($content_type !== 'tags') {
                $product->save();
            }

            return true;

        } catch (\Exception $e) {
            return false;
        }
    }

    private function getProductImageAltData($product_id) {
        $product = wc_get_product($product_id);
        if (!$product) {
            return [];
        }

        $attachment_ids = [];
        $featured_id = (int) $product->get_image_id();
        if ($featured_id > 0) {
            $attachment_ids[] = $featured_id;
        }
        foreach ((array) $product->get_gallery_image_ids() as $gallery_id) {
            $gallery_id = absint($gallery_id);
            if ($gallery_id > 0) {
                $attachment_ids[] = $gallery_id;
            }
        }

        $items = [];
        foreach (array_values(array_unique($attachment_ids)) as $attachment_id) {
            $items[] = [
                'attachment_id' => $attachment_id,
                'alt_text'      => sanitize_text_field((string) get_post_meta($attachment_id, '_wp_attachment_image_alt', true)),
            ];
        }

        return $items;
    }

    private function applyFaqContent($product_id, $content, $write_mode = 'append') {
        $decoded = json_decode((string) $content, true);
        if (!is_array($decoded)) {
            return false;
        }

        $faqs = [];
        foreach ($decoded as $faq) {
            if (!is_array($faq)) { continue; }
            $question = sanitize_text_field((string) ($faq['question'] ?? ''));
            $answer = wp_kses_post((string) ($faq['answer'] ?? ''));
            if ($question !== '' && $answer !== '') {
                $faqs[] = [
                    'question' => $question,
                    'answer'   => $answer,
                ];
            }
        }

        if ($write_mode === 'append') {
            $existing_json = get_post_meta($product_id, '_aipt_faq_data', true);
            $existing_faqs = !empty($existing_json) ? json_decode($existing_json, true) : [];
            if (is_array($existing_faqs)) {
                $faqs = array_merge($existing_faqs, $faqs);
            }
        }

        $json = wp_json_encode($faqs);
        if ($json === false) {
            return false;
        }

        $current = (string) get_post_meta($product_id, '_aipt_faq_data', true);
        if ($current === $json) {
            return true;
        }

        return false !== update_post_meta($product_id, '_aipt_faq_data', wp_slash($json));
    }

    /**
     * Resolve FAQ writeMode from parent automation job settings.
     *
     * Returns 'append' or 'replace'. Defaults to 'append' when the job row
     * is missing, settings JSON is invalid, or writeMode is absent/invalid.
     *
     * @param int $job_id Automation job ID from the draft content row.
     * @return string 'append' or 'replace'
     */
    private function resolveFaqWriteMode(int $job_id): string {
        $jobs_table = $this->wpdb->prefix . 'aipt_automation_jobs';

        $settings_json = $this->wpdb->get_var($this->wpdb->prepare(
            "SELECT settings FROM {$jobs_table} WHERE id = %d",
            $job_id
        ));

        if (empty($settings_json) || !is_string($settings_json)) {
            return 'append';
        }

        $settings = json_decode($settings_json, true);
        if (!is_array($settings) || !isset($settings['writeMode'])) {
            return 'append';
        }

        $mode = sanitize_text_field((string) $settings['writeMode']);
        return ($mode === 'replace') ? 'replace' : 'append';
    }

    private function applySeoMetaContent($product_id, $content) {
        $decoded = json_decode((string) $content, true);
        if (!is_array($decoded)) {
            return false;
        }

        $detected_plugin = SeoPluginDetector::detect();
        if (null === $detected_plugin || empty($detected_plugin['plugin_slug'])) {
            return false;
        }

        $write_data = SeoMetaWriter::buildWriteData($decoded, (string) $detected_plugin['plugin_slug']);
        if (empty($write_data)) {
            return false;
        }

        $writer = new SeoMetaWriter();
        $results = $writer->bulkWrite($product_id, $write_data, (string) $detected_plugin['plugin_slug']);
        foreach (array_keys($write_data) as $key) {
            if (empty($results[$key])) {
                return false;
            }
        }

        return true;
    }

    private function applyImageAltContent($product_id, $content) {
        $decoded = json_decode((string) $content, true);
        if (!is_array($decoded)) {
            return false;
        }

        $updated = false;
        foreach ($decoded as $item) {
            if (!is_array($item)) { continue; }
            $attachment_id = absint($item['attachment_id'] ?? 0);
            if ($attachment_id <= 0 || !$this->attachmentBelongsToProduct($attachment_id, $product_id)) { continue; }
            $alt_text = sanitize_text_field((string) ($item['alt_text'] ?? ''));
            $current_alt = (string) get_post_meta($attachment_id, '_wp_attachment_image_alt', true);
            if ($current_alt === $alt_text) {
                $updated = true;
                continue;
            }
            if (false !== update_post_meta($attachment_id, '_wp_attachment_image_alt', wp_slash($alt_text))) {
                $updated = true;
            }
        }

        return $updated;
    }

    private function attachmentBelongsToProduct($attachment_id, $product_id) {
        if (!wp_get_attachment_image_url($attachment_id, 'full')) {
            return false;
        }

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

        if ((int) $product->get_image_id() === (int) $attachment_id) {
            return true;
        }

        $gallery_ids = array_map('absint', (array) $product->get_gallery_image_ids());
        return in_array((int) $attachment_id, $gallery_ids, true);
    }

    /**
     * Reject draft content
     *
     * @param int $draft_id Draft content ID
     * @return bool Success status
     */
    public function rejectDraftContent($draft_id) {
        try {
            $result = $this->wpdb->update(
                $this->draft_table,
                [
                    'status' => 'rejected',
                    'approved_by' => get_current_user_id(),
                    'approved_at' => current_time('mysql'),
                    'updated_at' => current_time('mysql')
                ],
                ['id' => $draft_id, 'status' => 'pending'],
                ['%s', '%d', '%s', '%s'],
                ['%d', '%s']
            );

            return (int) $result > 0;

        } catch (\Exception $e) {
            return false;
        }
    }

    /**
     * Bulk approve draft content
     *
     * @param array $draft_ids Array of draft content IDs
     * @return array Results array with success/failure for each ID
     */
    public function bulkApproveDraftContent($draft_ids) {
        $results = [];

        foreach ($draft_ids as $draft_id) {
            $results[$draft_id] = $this->approveDraftContent($draft_id);
        }

        return $results;
    }

    /**
     * Bulk delete draft content
     *
     * @param array $draft_ids Array of draft content IDs
     * @return array Results array with success/failure for each ID
     */
    public function bulkDeleteDraftContent($draft_ids) {
        $results = [];

        foreach ($draft_ids as $draft_id) {
            $results[$draft_id] = $this->deleteDraftContent($draft_id);
        }

        return $results;
    }

    /**
     * Delete draft content
     *
     * @param int $draft_id Draft content ID
     * @return bool Success status
     */
    public function deleteDraftContent($draft_id) {
        try {
            $result = $this->wpdb->delete(
                $this->draft_table,
                ['id' => $draft_id],
                ['%d']
            );

            return $result !== false;

        } catch (\Exception $e) {
            return false;
        }
    }
}
