<?php

namespace SEOAIC\rest_api;

use Exception;
use SEOAIC\rest_api\exceptions\ValidateException;
use SEOAIC\rest_api\http_resources\Result;
use SEOAIC\SEOAIC_SETTINGS;
use WP_REST_Response;

class EditorCommands
{
    private $seoaic;
    private $validationRules = [
        'rephrase' => [
            'content' => 'required',
        ],
        'shorten' => [
            'content' => 'required',
        ],
        'simplify' => [
            'content' => 'required',
        ],
        'paraphrase' => [
            'content' => 'required',
        ],
        'changeTone' => [
            'content' => 'required',
            'tone' => 'required',
        ],
        'makeItMore' => [
            'content' => 'required',
            'style' => 'required',
        ],
        'writeMore' => [
            'content' => 'required',
        ],
        'translate' => [
            'content' => 'required',
            'language' => 'required',
        ],
        'makeSummary' => [
            'content' => 'required',
        ],
        'improveContent' => [
            'content' => 'required',
            'prompt' => 'required',
        ],
        'rewrite' => [
            'content' => 'required',
            'audience' => 'required'
        ],
        'fixGrammar' => [
            'content' => 'required',
        ],
    ];

    public function __construct($seoaic)
    {
        $this->seoaic = $seoaic;

        add_action('rest_api_init', function () {
            register_rest_route('seoaic/v1', '/get-languages-options', [
                'methods' => 'POST',
                'callback' => [$this, 'getLanguagesOptions'],
                'permission_callback' => function () {
                    return current_user_can('edit_posts');
                }
            ]);
        });

        add_action('rest_api_init', function () {
            register_rest_route('seoaic/v1', '/commands/(?P<command>[a-zA-Z0-9-]+)', [
                'methods' => 'POST',
                'callback' => [$this, 'runCommand'],
                'permission_callback' => function () {
                    return current_user_can('edit_posts');
                }
            ]);
        });
    }

    /**
     * Parses command parameter, transforms if from cebab-case to camelCase
     */
    private function parseCommand($command)
    {
        $parsedCommand = implode('', array_map(function ($word) {
            return ucfirst($word);
        }, explode('-', $command)));
        $parsedCommand = lcfirst($parsedCommand);

        return $parsedCommand;
    }

    /**
     * Runs method if found such command
     */
    public function runCommand($request)
    {
        $command = $this->parseCommand($request['command']);
        $params = $request->get_json_params();

        if (method_exists($this, $command)) {
            try {
                $this->validateParams($command, $params);

                return $this->$command($params);

            } catch(ValidateException $e) {
                return new WP_REST_Response(Result::error('validate', esc_html__("Validation error: ", 'seoaic') . $e->getMessage()), 401);

            } catch (Exception $e) {
                error_log('[Error] in ' . $command . ': ' . $e->getMessage());
                return new WP_REST_Response(Result::error('error', esc_html__('Something went wrong.', 'seoaic')), 401);
            }

        } else {
            return new WP_REST_Response(Result::error('parseCommand', esc_html__('Method not found', 'seoaic')), 401);
        }
    }

    private function validateParams($command, $params)
    {
        $validationRules = $this->validationRules;

        if (
            in_array($command, array_keys($validationRules))
            && !empty($validationRules[$command])
        ) {
            $fields = $validationRules[$command];

            foreach ($fields as $field => $rulesStr) {
                $rulesArr = explode('|', $rulesStr);

                if (
                    in_array('required', $rulesArr)
                    && empty($params[$field])
                ) {
                    throw new ValidateException(esc_html__('Field is required:', 'seoaic') . '"' . esc_html($field) . '"');
                }

                // here can be added other validations
            }
        }
    }

    private function getSEOAICDefaultLanguageName()
    {
        if (method_exists($this->seoaic, 'getDefaultLanguageName')) {
            return $this->seoaic->getDefaultLanguageName();
        }

        if ($this->seoaic->multilang->is_multilang()) {
            $lang = $this->seoaic->multilang->get_default_language('name');

            if (!empty($lang)) {
                return $lang;
            }
        }

        return SEOAIC_SETTINGS::getLanguage();
    }

    public function getLanguagesOptions()
    {
        $languages = seoaic_get_languages();

        if (
            empty($languages)
            || !is_array($languages)
        ) {
            return new WP_REST_Response(Result::error('getLanguagesOptions', esc_html__('No languages found.', 'seoaic')));
        }

        array_walk($languages, function (&$item) {
            $item = [
                'label' => $item,
                'value' => $item,
            ];
        });

        array_unshift($languages, [
            'label' => 'Select language',
            'value' => ''
        ]);

        return new WP_REST_Response(Result::success('getLanguages', 'OK', [
            'languages' => $languages,
        ]));
    }

    /**
     * Does POST request to backend and returns result or WP_REST_Response with error message
     * @param string $url
     * @param array $data
     * @return array|WP_REST_Response
     */
    private function doBackendRequest($url, $data = [])
    {
        $result = $this->seoaic->curl->initWithReturn($url, $data, true, true);

        if (
            empty($result['status'])
            || "success" !== $result['status']
            || empty($result['content'])
        ) {
            return new WP_REST_Response(Result::error('backendRequest', esc_html__('Content processing failed.', 'seoaic')));
        }

        return $result;
    }



    private function rephrase($params)
    {
        $data = [
            'title' => !empty($params['title']) ? $params['title'] : '',
            'content' => $params['content'],
            'language' => $this->getSEOAICDefaultLanguageName(),
        ];
        $resp = $this->doBackendRequest('api/ai/content/rephrase', $data);

        if (is_a($resp, 'WP_REST_Response')) {
            return $resp;
        }

        return new WP_REST_Response(Result::success('rephrase', 'OK', [
            'content' => $resp['content'],
        ]));
    }

    private function shorten($params)
    {
        $data = [
            'title' => !empty($params['title']) ? $params['title'] : '',
            'content' => $params['content'],
            'language' => $this->getSEOAICDefaultLanguageName(),
        ];
        $resp = $this->doBackendRequest('api/ai/content/shorten', $data);

        if (is_a($resp, 'WP_REST_Response')) {
            return $resp;
        }

        return new WP_REST_Response(Result::success('shorten', 'OK', [
            'content' => $resp['content'],
        ]));
    }

    private function simplify($params)
    {
        $data = [
            'title' => !empty($params['title']) ? $params['title'] : '',
            'content' => $params['content'],
            'language' => $this->getSEOAICDefaultLanguageName(),
        ];
        $resp = $this->doBackendRequest('api/ai/content/simplify', $data);

        if (is_a($resp, 'WP_REST_Response')) {
            return $resp;
        }

        return new WP_REST_Response(Result::success('simplify', 'OK', [
            'content' => $resp['content'],
        ]));
    }

    private function paraphrase($params)
    {
        $data = [
            'title' => !empty($params['title']) ? $params['title'] : '',
            'content' => $params['content'],
            'language' => $this->getSEOAICDefaultLanguageName(),
        ];
        $resp = $this->doBackendRequest('api/ai/content/paraphrase', $data);

        if (is_a($resp, 'WP_REST_Response')) {
            return $resp;
        }

        return new WP_REST_Response(Result::success('paraphrase', 'OK', [
            'content' => $resp['content'],
        ]));
    }

    private function changeTone($params)
    {
        $data = [
            'title' => !empty($params['title']) ? $params['title'] : '',
            'content' => $params['content'],
            'language' => $this->getSEOAICDefaultLanguageName(),
            'tone' => $params['tone'],
        ];
        $resp = $this->doBackendRequest('api/ai/content/change-tone', $data);

        if (is_a($resp, 'WP_REST_Response')) {
            return $resp;
        }

        return new WP_REST_Response(Result::success('changeTone', 'OK', [
            'content' => $resp['content'],
        ]));
    }

    private function makeItMore($params)
    {
        $data = [
            'title' => !empty($params['title']) ? $params['title'] : '',
            'content' => $params['content'],
            'language' => $this->getSEOAICDefaultLanguageName(),
            'style' => $params['style'],
        ];
        $resp = $this->doBackendRequest('api/ai/content/stylize', $data);

        if (is_a($resp, 'WP_REST_Response')) {
            return $resp;
        }

        return new WP_REST_Response(Result::success('makeItMore', 'OK', [
            'content' => $resp['content'],
        ]));
    }

    private function writeMore($params)
    {
        $data = [
            'title' => !empty($params['title']) ? $params['title'] : '',
            'content' => $params['content'],
            'language' => $this->getSEOAICDefaultLanguageName(),
        ];
        $resp = $this->doBackendRequest('api/ai/content/extend', $data);

        if (is_a($resp, 'WP_REST_Response')) {
            return $resp;
        }

        return new WP_REST_Response(Result::success('writeMore', 'OK', [
            'content' => $resp['content'],
        ]));
    }

    private function rewrite($params)
    {
        $data = [
            'title' => !empty($params['title']) ? $params['title'] : '',
            'content' => $params['content'],
            'language' => $this->getSEOAICDefaultLanguageName(),
            'audience' => $params['audience'],
        ];
        $resp = $this->doBackendRequest('api/ai/content/personalize', $data);

        if (is_a($resp, 'WP_REST_Response')) {
            return $resp;
        }

        return new WP_REST_Response(Result::success('rewrite', 'OK', [
            'content' => $resp['content'],
        ]));
    }

    private function fixGrammar($params)
    {
        $data = [
            'content' => $params['content'],
            'language' => $this->getSEOAICDefaultLanguageName(),
        ];
        $resp = $this->doBackendRequest('api/ai/content/grammar', $data);

        if (is_a($resp, 'WP_REST_Response')) {
            return $resp;
        }

        return new WP_REST_Response(Result::success('fixGrammar', 'OK', [
            'content' => $resp['content'],
        ]));
    }

    private function improveContent($params)
    {
        $data = [
            'content' => $params['content'],
            'prompt' => $params['prompt'],
            'language' => $this->getSEOAICDefaultLanguageName(),
        ];
        $resp = $this->doBackendRequest('api/ai/content/improve', $data);

        if (is_a($resp, 'WP_REST_Response')) {
            return $resp;
        }

        return new WP_REST_Response(Result::success('improveContent', 'OK', [
            'content' => $resp['content'],
        ]));
    }

    private function makeSummary($params)
    {
        $data = [
            'content' => $params['content'],
            'language' => $this->getSEOAICDefaultLanguageName(),
        ];
        $resp = $this->doBackendRequest('api/ai/content/summary', $data);

        if (is_a($resp, 'WP_REST_Response')) {
            return $resp;
        }

        return new WP_REST_Response(Result::success('makeSummary', 'OK', [
            'content' => $resp['content'],
        ]));
    }

    private function translate($params)
    {
        $data = [
            'content' => $params['content'],
            'language' => $params['language'],
        ];
        $resp = $this->doBackendRequest('api/ai/content/translate', $data);

        if (is_a($resp, 'WP_REST_Response')) {
            return $resp;
        }

        return new WP_REST_Response(Result::success('translate', 'OK', [
            'content' => $resp['content'],
        ]));
    }
}
