<?php

namespace GriffinForms\Includes\Ai\PromptRegistry\Handlers\Page;

class PagePromptHelper
{
    public function isPageRewritePrompt(string $normalized_prompt): bool
    {
        $tokens = $this->tokenizePrompt($normalized_prompt);
        return $this->containsAnyToken($tokens, ['rewrite', 'improve', 'update', 'change', 'edit', 'refine', 'polish'])
            && $this->containsAnyToken($tokens, ['heading', 'title', 'description', 'text', 'copy'])
            && $this->containsAnyToken($tokens, ['page', 'pages', 'step', 'steps']);
    }

    public function isPageHeadingPrompt(string $normalized_prompt): bool
    {
        $tokens = $this->tokenizePrompt($normalized_prompt);
        return $this->containsAnyToken($tokens, ['heading', 'headings', 'title', 'titles'])
            && $this->containsAnyToken($tokens, ['page', 'pages', 'step', 'steps'])
            && $this->containsAnyToken($tokens, ['rewrite', 'improve', 'update', 'change', 'edit', 'refine', 'polish', 'add']);
    }

    public function isPageDescriptionPrompt(string $normalized_prompt): bool
    {
        $tokens = $this->tokenizePrompt($normalized_prompt);
        return $this->containsAnyToken($tokens, ['description', 'descriptions', 'copy', 'text'])
            && $this->containsAnyToken($tokens, ['page', 'pages', 'step', 'steps'])
            && $this->containsAnyToken($tokens, ['rewrite', 'improve', 'update', 'change', 'edit', 'refine', 'polish', 'add']);
    }

    public function isPageMoveRequest(string $normalized_prompt): bool
    {
        $tokens = $this->tokenizePrompt($normalized_prompt);
        $has_move_verb = $this->containsAnyToken($tokens, ['move', 'shift', 'reorder']);
        $has_direction = $this->containsAnyToken($tokens, ['up', 'down', 'before', 'after', 'above', 'below', 'previous', 'next', 'earlier', 'later', 'top', 'bottom', 'first', 'last', 'start', 'end']);
        $has_ordinal_position = $this->extractRequestedPagePosition($normalized_prompt) !== null;
        $has_page_noun = $this->containsAnyToken($tokens, ['page', 'step', 'screen', 'tab']);

        return $has_move_verb && ($has_direction || $has_ordinal_position || $has_page_noun);
    }

    public function isAllPageHeadingPrompt(string $normalized_prompt): bool
    {
        $tokens = $this->tokenizePrompt($normalized_prompt);
        return $this->containsAnyToken($tokens, ['all', 'every', 'each', 'bulk'])
            && $this->containsAnyToken($tokens, ['heading', 'headings', 'title', 'titles'])
            && $this->containsAnyToken($tokens, ['rewrite', 'improve', 'update', 'change', 'edit', 'refine', 'polish', 'add']);
    }

    public function isAllPageDescriptionPrompt(string $normalized_prompt): bool
    {
        $tokens = $this->tokenizePrompt($normalized_prompt);
        return $this->containsAnyToken($tokens, ['all', 'every', 'each', 'bulk'])
            && $this->containsAnyToken($tokens, ['description', 'descriptions', 'copy', 'text'])
            && $this->containsAnyToken($tokens, ['rewrite', 'improve', 'update', 'change', 'edit', 'refine', 'polish', 'add']);
    }

    public function extractRequestedPagePosition(string $prompt): ?array
    {
        $tokens = $this->tokenizePrompt($prompt);
        $position_tokens = array_values(array_intersect($tokens, ['top', 'bottom', 'last', 'end', 'final', 'first', 'start']));
        if (!empty($position_tokens)) {
            if (in_array($position_tokens[0], ['first', 'top', 'start'], true)) {
                $edge = 'top';
            } else {
                $edge = 'bottom';
            }
            return [
                'type' => 'edge',
                'value' => $edge,
            ];
        }

        for ($i = 0, $count = count($tokens); $i < $count; $i++) {
            $ordinal = $this->parseOrdinalPositionToken($tokens[$i]);
            if ($ordinal === null) {
                continue;
            }

            $next = $tokens[$i + 1] ?? '';
            $next2 = $tokens[$i + 2] ?? '';
            if (in_array($next, ['position', 'place', 'slot', 'page', 'step'], true) || in_array($next2, ['position', 'place', 'slot', 'page', 'step'], true)) {
                return [
                    'type' => 'ordinal',
                    'value' => $ordinal,
                ];
            }
        }

        return null;
    }

    protected function parseOrdinalPositionToken(string $token): ?int
    {
        $token = strtolower(trim($token));
        if ($token === '') {
            return null;
        }

        if (preg_match('/^(\d+)(?:st|nd|rd|th)?$/', $token, $matches)) {
            return absint($matches[1]);
        }

        $ordinal_map = [
            'first' => 1,
            'second' => 2,
            'third' => 3,
            'fourth' => 4,
            'fifth' => 5,
            'sixth' => 6,
            'seventh' => 7,
            'eighth' => 8,
            'ninth' => 9,
            'tenth' => 10,
        ];

        return $ordinal_map[$token] ?? null;
    }

    protected function tokenizePrompt(string $prompt): array
    {
        $prompt = strtolower(trim($prompt));
        $prompt = str_replace(['-', '_', '/', '\\', ':', ';', ',', '(', ')', '[', ']', '{', '}', '"', "'"], ' ', $prompt);
        $tokens = preg_split('/\s+/', $prompt) ?: [];
        return array_values(array_filter(array_map(static function ($token) {
            return trim($token, " \t\n\r\0\x0B.,!?");
        }, $tokens), static function ($token) {
            return $token !== '';
        }));
    }

    protected function containsAnyToken(array $tokens, array $needles): bool
    {
        $lookup = array_fill_keys($tokens, true);
        foreach ($needles as $needle) {
            if (isset($lookup[$needle])) {
                return true;
            }
        }

        return false;
    }
}
