<?php

namespace SEOAIC\posts_mass_actions;

use Exception;
use SEOAIC\interfaces\PostsMassActionStoppable;
use SEOAIC\SEOAIC_IDEAS;
use SEOAIC\SEOAIC_SETTINGS;
use SEOAIC\traits\Debug;

class FramesMassGenerate extends AbstractPostsMassAction implements PostsMassActionStoppable
{
    use Debug;

    private $ideas;
    private const PENDING_STATUS = 'pending';
    private const FAILED_STATUS = 'failed';
    private const COMPLETED_STATUS = 'completed';

    public function __construct($seoaic)
    {
        parent::__construct($seoaic);

        $this->backendActionURL = 'api/ai/posts/frames/generate';
        $this->backendCheckStatusURL = 'api/ai/posts/frames/generate/status';
        $this->backendContentURL = 'api/ai/posts/frames/generate/content';
        $this->backendClearURL = 'api/ai/posts/frames/generate/clear';
        $this->statusField = 'seoaic_frame_generate_status';
        // $this->cronCheckStatusHookName = 'seoaic/frames/generate/check_status_cron_hook';
        $this->useCron = false;

        $this->successfullRunMessage = 'Update started';
        $this->completeMessage = esc_html__('All outlines have been generated.', 'seoaic');
        $this->stopMessage = esc_html__('Outline generation have been stopped.', 'seoaic');
    }

    // public static function init()
    // {
    //     global $SEOAIC;

    //     $self = new self($SEOAIC);
    //     add_action($self->cronCheckStatusHookName, [$self, 'cronPostsCheckStatus']);
    // }

    public function prepareData($request)
    {
        $IDs = [];

        if (!empty($request['idea-mass-create'])) {
            $selectedIDs = $request['idea-mass-create'];

            if (is_array($selectedIDs)) {
                $IDs = $selectedIDs;
            } elseif ( is_numeric($selectedIDs) && intval($selectedIDs) == $selectedIDs ) {
                $IDs = [$selectedIDs];
            }
        }

        if (empty($IDs)) {
            throw new Exception('No ideas selected');
        }

        $subtitlesRangeMin  = $request['seoaic_subtitles_range_min'] ?: SEOAIC_SETTINGS::getSubtitlesRangeMin();
        $subtitlesRangeMax  = $request['seoaic_subtitles_range_max'] ?: SEOAIC_SETTINGS::getSubtitlesRangeMax();
        $requestPrompt      = $request['mass_prompt']   ?: '';

        // make sure posts are available
        $ideas = $this->getAvailableIdeasForFrameGeneration($IDs);

        if (empty($ideas)) {
            throw new Exception('Ideas not found');
        }

        $this->ideas = $ideas;

        $data = [
            'name'          => SEOAIC_SETTINGS::getBusinessName(),
            'desc'          => SEOAIC_SETTINGS::getBusinessDescription(),
            'industry'      => SEOAIC_SETTINGS::getIndustry(),
            'subtitles_min' => $subtitlesRangeMin,
            'subtitles_max' => $subtitlesRangeMax,
            'writing_style' => SEOAIC_SETTINGS::getWritingStyle(),
            'ideas'         => [],
            'with_outlines' => true,
        ];

        foreach ($ideas as $idea) {
            $prompt = get_post_meta($idea->ID, '_idea_prompt_data', true);
            $ideaType = get_post_meta($idea->ID, '_idea_type', true);
            $keys = get_post_meta($idea->ID, '_idea_keywords_data', true);

            $data['ideas'][] = [
                'idea_id'       => $idea->ID,
                'idea'          => get_the_title($idea->ID),
                'language'      => $this->seoaic->multilang->get_post_language($idea->ID),
                'idea_prompt'   => $prompt ?: $requestPrompt,
                'idea_type'     => $ideaType ?: 'default',
                'idea_keys'     => is_array($keys) ? implode(',', $keys) : $keys,
            ];
        }

        return $data;
    }

    /**
     * Override parent's method with additinal debug logs
     */
    public function sendActionRequest($data = [])
    {
        $response = $this->sendRequest($this->getBackendActionURL(), $data);

        return $response;
    }

    public function processActionResults($response)
    {
        if (!empty($response)) {
            if (
                !empty($response['status'])
                && 'success' == $response['status']
                && !empty($this->ideas)
            ) {
                foreach ($this->ideas as $idea) {
                    $this->updatePostData($idea->ID, [
                        $this->getStatusField() => self::PENDING_STATUS,
                    ]);
                }

            } else {
                if (!empty($response['message'])) {
                    $this->errors[] = $response['message'];
                }

                foreach ($this->ideas as $idea) {
                    $this->updatePostData($idea->ID, [
                        $this->getStatusField() => '',
                    ]);
                }
            }

            if ($this->useCron) {
                $this->registerPostsCheckStatusCron();
            }

            return true;

        } else {
            return false;
        }
    }

    public function pocessCheckStatusResults($result)
    {
        $returnData = [
            'done' => [],
            'failed' => [],
        ];

        if (!empty($result)) {
            if (
                !empty($result['completed'])
                && is_array($result['completed'])
            ) {
                $returnData['done'] = $this->processCompleted($result['completed']);
            }

            if (!empty($result['failed'])) {
                $this->processFailed($result['failed']);
                $returnData['failed'] = array_merge($returnData['failed'], $result['failed']);
            }
        }

        return $returnData;
    }

    protected function processCompleted($ids = [])
    {
        $return = [];

        if (
            !empty($ids)
            && is_array($ids)
        ) {
            // doublecheck the IDs to exist
            $ideas = $this->getPendingFramesByIDs($ids);
            if (empty($ideas)) {
                return;
            }

            $ideasByIDs = array_combine(array_column($ideas, 'ID'), $ideas);

            // change status
            foreach ($ideasByIDs as $origPost) {
                $this->updatePostData($origPost->ID, [
                    $this->getStatusField() => self::COMPLETED_STATUS,
                ]);
            }

            $ideaIDs = array_map(function ($item) {
                return $item->ID;
            }, $ideas);

            $data = [
                'idea_ids' => $ideaIDs,
            ];
            $contentResult = $this->sendContentRequest($data);

            if (
                !empty($contentResult)
                && is_array($contentResult)
            ) {
                foreach ($contentResult as $item) {
                    if (
                        empty($item)
                        || empty($item['ideaId'])
                        || empty($item['content'])
                        || !in_array($item['ideaId'], $ideaIDs)
                    ) {
                        continue;
                    }

                    $ideaId = $item['ideaId'];
                    $content = $item['content'];

                    // $thumbnail_generator = !empty($SEOAIC_OPTIONS['seoaic_image_generator']) ? $SEOAIC_OPTIONS['seoaic_image_generator'] : 'no_image';
                    // $old_idea_content = get_post_meta($id, 'seoaic_idea_content', true);
                    // if ( !empty($old_idea_content) ) {
                    //     $old_idea_content = json_decode($old_idea_content, true);
                    //     if ( !empty($old_idea_content['idea_thumbnail_generator']) ) {
                    //         $thumbnail_generator = $old_idea_content['idea_thumbnail_generator'];
                    //     }
                    // }

                    $ideaContent = [
                        // 'idea_thumbnail' => isset($content['image-description']) ? str_replace('"', '\"', $content['image-description']) : '',
                        // 'idea_thumbnail_generator' => str_replace('"', '\"', $thumbnail_generator),
                        'idea_skeleton' => !empty($content['subtitles']) ? $content['subtitles'] : [],
                        'idea_keywords' => isset($content['keywords']) ? str_replace('"', '\"', $content['keywords']) : '',
                        'idea_description' => isset($content['description']) ? str_replace('"', '\"', $content['description']) : '',
                    ];

                    $this->updatePostData($ideaId, [
                        'seoaic_idea_content' => json_encode($ideaContent, JSON_UNESCAPED_UNICODE),
                    ]);

                    $return[$ideaId] = [
                        'idea_content'   => $ideaContent,
                        'idea_postdate'  => '',
                        //'seoaic_credits' => $this->seoaic->get_api_credits(),
                        'idea_id'        => $ideaId,
                        'idea_icons'     => $this->seoaic->ideas->get_idea_icons($ideaId),
                    ];
                }
            }
        }

        return $return;
    }

    protected function processFailed($ids = [])
    {
        if (
            !empty($ids)
            && is_array($ids)
        ) {
            // doublecheck the IDs to exist
            $posts = $this->getPendingFramesByIDs($ids);
            if (empty($posts)) {
                return;
            }

            $postsByIDs = array_combine(array_column($posts, 'ID'), $posts);

            // change status
            foreach ($postsByIDs as $origPost) {
                $this->updatePostData($origPost->ID, [
                    $this->getStatusField() => self::FAILED_STATUS,
                ]);
            }
        }
    }

    public function isRunning()
    {
        $posts = $this->getPendingFramesAll();

        return !empty($posts);
    }

    public function cronPostsCheckStatus()
    {
        $this->getStatusResults();
    }

    public function stop()
    {
        $posts = $this->getPendingFramesAll();

        if (!empty($posts)) {
            foreach ($posts as $post) {
                $this->updatePostData($post->ID, [
                    $this->getStatusField() => '',
                ]);
            }
        }

        $this->sendClearRequest(['full' => true]);
        $this->unregisterPostsCheckStatusCron();
    }


    /**
     * Gets available posts for Review, e.g. not in "Edit" or "Review" state
     * @param array $postIDs options array of IDs to search among
     * @return array
     */
    private function getAvailableIdeasForFrameGeneration($postIDs = [])
    {
        $args = [
            'posts_per_page'    => -1,
            'post_type'         => SEOAIC_IDEAS::IDEA_TYPE,
            'post_status'       => SEOAIC_IDEAS::IDEA_STATUS,
            'lang'              => '', // disable default lang setting
        ];

        if (!empty($postIDs)) {
            $postIDs = !is_array($postIDs) ? [$postIDs] : $postIDs;
            $args['post__in'] = $postIDs;
        }

        $ideas = get_posts($args);

        return $ideas;
    }

    /**
     * Gets all posts that were sent for review
     * @param array $postIDs options array of IDs to search among
     * @return array
     */
    public function getPendingFramesAll()
    {
        $args = [
            'posts_per_page'    => -1,
            'post_type'         => SEOAIC_IDEAS::IDEA_TYPE,
            'post_status'       => SEOAIC_IDEAS::IDEA_STATUS,
            'lang'              => '', // disable default lang setting
            'meta_query'        => [
                'relation' => 'AND',
                [
                    'key' => $this->getStatusField(),
                    'value' => self::PENDING_STATUS,
                    'compare' => '=',
                ],
            ],
        ];

        $posts = get_posts($args);

        // $this->posts = $posts;

        return $posts;
    }

    /**
     * @param array|int $ids Accepts array if IDs or single ID
     */
    private function getPendingFramesByIDs($ids = [], $returnIDsOnly = false)
    {
        $args = [
            'posts_per_page'    => -1,
            'post_type'         => SEOAIC_IDEAS::IDEA_TYPE,
            'post_status'       => SEOAIC_IDEAS::IDEA_STATUS,
            'lang'              => '', // disable default lang setting
            'meta_query'        => [
                'relation' => 'AND',
                [
                    'key' => $this->getStatusField(),
                    'value' => self::PENDING_STATUS,
                    'compare' => '=',
                ],
            ],
        ];

        if (!empty($ids)) {
            $args['include'] = !is_array($ids) ? [$ids] : $ids;
        }

        if ($returnIDsOnly) {
            $args['fields'] = 'ids';
        }

        $posts = get_posts($args);

        return $posts;
    }
}
