<?php

namespace WPSN\Modules\AI;

use WPSN\Core\Settings;

defined('ABSPATH') || exit;

/**
 * Prompt Library (v1)
 *
 * Central registry for all AI prompt templates used across the plugin.
 *
 * Why:
 * - Avoid duplicated prompt strings across modules.
 * - Make prompt versioning consistent.
 * - Provide stable prompt keys for auditing in AI logs.
 */
final class PromptLibrary
{
    public const KEY_META_TITLE       = 'meta_title';
    public const KEY_META_DESCRIPTION = 'meta_description';
    public const KEY_MEDIA_ALT        = 'media_alt';
    public const KEY_CONTENT_BRIEF    = 'content_brief';
    public const KEY_SERP_GAP         = 'serp_gap';
    public const KEY_SERP_GAP_FAQ     = 'serp_gap_faq';
    public const KEY_SEO_AUTOFILL     = 'seo_autofill';

    private Settings $settings;

    public function __construct(Settings $settings)
    {
        $this->settings = $settings;
    }

    /**
     * @return array<string,array{label:string,template_path:string,version_path:string,default:string,placeholders:array<int,string>,notes:string}>
     */
    public function definitions(): array
    {
        return [
            self::KEY_META_TITLE => [
                'label' => __('Meta title', 'wp-seo-next'),
                'template_path' => 'ai.prompts.title_template',
                'version_path' => 'ai.prompts.title_version',
                'default' => self::defaultMetaTitleTemplate(),
                'placeholders' => [
                    '{sitename}', '{language}', '{max_length}',
                    '{post_title}', '{excerpt}', '{content}', '{current_seo_title}',
                ],
                'notes' => __('Used by SEO Editor and Bulk AI meta generation.', 'wp-seo-next'),
            ],
            self::KEY_META_DESCRIPTION => [
                'label' => __('Meta description', 'wp-seo-next'),
                'template_path' => 'ai.prompts.description_template',
                'version_path' => 'ai.prompts.description_version',
                'default' => self::defaultMetaDescriptionTemplate(),
                'placeholders' => [
                    '{sitename}', '{language}', '{max_length}',
                    '{post_title}', '{excerpt}', '{content}', '{current_meta_description}',
                ],
                'notes' => __('Used by SEO Editor and Bulk AI meta generation.', 'wp-seo-next'),
            ],
            self::KEY_MEDIA_ALT => [
                'label' => __('Image ALT', 'wp-seo-next'),
                'template_path' => 'ai.prompts.alt_template',
                'version_path' => 'ai.prompts.alt_version',
                'default' => self::defaultAltTemplate(),
                'placeholders' => [
                    '{sitename}', '{language}', '{max_length}',
                    '{attachment_title}', '{caption}', '{filename}', '{parent_title}', '{parent_excerpt}', '{current_alt}',
                ],
                'notes' => __('Used by Tools → SEO Media when generating ALT drafts.', 'wp-seo-next'),
            ],
            self::KEY_CONTENT_BRIEF => [
                'label' => __('Content brief', 'wp-seo-next'),
                'template_path' => 'ai.prompts.brief_template',
                'version_path' => 'ai.prompts.brief_version',
                'default' => self::defaultBriefTemplate(),
                'placeholders' => [
                    '{query}', '{sitename}', '{language}', '{preset}', '{intent}', '{primary_location}',
                    '{intent_reason}',
                    '{post_title}', '{excerpt}', '{existing_h2}', '{existing_h3}', '{content}',
                    '{gsc_start}', '{gsc_end}', '{top_queries}',
                ],
                'notes' => __('Used by Query optimizer / content brief (GSC → H2/H3/FAQ).', 'wp-seo-next'),
            ],
            self::KEY_SERP_GAP => [
                'label' => __('SERP Gap (outline)', 'wp-seo-next'),
                'template_path' => 'ai.prompts.serp_gap_template',
                'version_path' => 'ai.prompts.serp_gap_version',
                'default' => self::defaultSerpGapTemplate(),
                'placeholders' => [
                    '{query}', '{site_locale}', '{site_name}', '{target_url}', '{post_id}',
                    '{target_headings}', '{target_preview}', '{serp_snippets}',
                    '{competitor_snapshots}', '{missing_topics}',
                    '{recommended_word_count_min}', '{recommended_word_count_max}',
                ],
                'notes' => __('Used by Tools → SERP Gap when generating AI outline/checklist.', 'wp-seo-next'),
            ],
            self::KEY_SERP_GAP_FAQ => [
                'label' => __('SERP Gap (FAQ)', 'wp-seo-next'),
                'template_path' => 'ai.prompts.serp_gap_faq_template',
                'version_path' => 'ai.prompts.serp_gap_faq_version',
                'default' => self::defaultSerpGapFaqTemplate(),
                'placeholders' => [
                    '{site_locale}', '{query}', '{missing_topics}', '{competitor_h2_hints}',
                ],
                'notes' => __('Used by Tools → SERP Gap when generating FAQ JSON.', 'wp-seo-next'),
            ],
            self::KEY_SEO_AUTOFILL => [
                'label' => __('SEO autofill (Inspector)', 'wp-seo-next'),
                'template_path' => 'ai.prompts.seo_autofill_template',
                'version_path' => 'ai.prompts.seo_autofill_version',
                'default' => self::defaultSeoAutofillTemplate(),
                'placeholders' => [
                    '{sitename}', '{language}', '{tone}', '{task}', '{schema_allowed}',
                    '{title_max_length}', '{description_max_length}',
                    '{context_label}', '{post_title}', '{h1}', '{excerpt}', '{content}',
                    '{current_seo_title}', '{current_meta_description}', '{current_focus_keyword}',
                    '{keywords_hint}',
                ],
                'notes' => __('Used by the Frontend Inspector “AI autofill” action to generate draft SEO fields.', 'wp-seo-next'),
            ],
        ];
    }

    public function template(string $key): string
    {
        $defs = $this->definitions();
        if (!isset($defs[$key])) {
            return '';
        }

        $def = $defs[$key];
        $tpl = (string) $this->settings->get($def['template_path'], '');
        if (trim($tpl) === '') {
            $tpl = (string) $def['default'];
        }
        return (string) $tpl;
    }

    public function version(string $key): int
    {
        $defs = $this->definitions();
        if (!isset($defs[$key])) {
            return 1;
        }
        $def = $defs[$key];
        $v = (int) $this->settings->get($def['version_path'], 1);
        return max(1, $v);
    }

    /**
     * @param array<string,string> $vars
     */
    public function render(string $template, array $vars): string
    {
        // Use strtr for predictable placeholder replacement.
        return (string) strtr((string) $template, $vars);
    }

    /**
     * @param array<string,string> $vars
     * @return array{key:string,version:int,template:string,prompt:string,hash:string}
     */
    public function build(string $key, array $vars): array
    {
        $template = $this->template($key);
        $version = $this->version($key);
        $prompt = $this->render($template, $vars);
        $hash = self::templateHash($template);

        return [
            'key' => $key,
            'version' => $version,
            'template' => $template,
            'prompt' => $prompt,
            'hash' => $hash,
        ];
    }

    public static function templateHash(string $template): string
    {
        return (string) sha1(trim((string) $template));
    }

    private static function defaultMetaTitleTemplate(): string
    {
        return "You are an SEO assistant. Write a concise SEO title for the following WordPress page.\n\nRules:\n- Language: {language}\n- Max length: {max_length} characters\n- Do NOT use quotes\n- Do not add extra commentary\n\nPage:\nSite name: {sitename}\nPost title: {post_title}\nExcerpt: {excerpt}\nContent: {content}\nCurrent SEO title: {current_seo_title}\n\nReturn only the SEO title.";
    }

    private static function defaultMetaDescriptionTemplate(): string
    {
        return "You are an SEO assistant. Write a helpful meta description for the following WordPress page.\n\nRules:\n- Language: {language}\n- Max length: {max_length} characters\n- Do NOT use quotes\n- Do not add extra commentary\n\nPage:\nSite name: {sitename}\nPost title: {post_title}\nExcerpt: {excerpt}\nContent: {content}\nCurrent meta description: {current_meta_description}\n\nReturn only the meta description.";
    }

    private static function defaultAltTemplate(): string
    {
        return "You are an SEO assistant. Write concise image ALT text for accessibility and SEO.\n\nRules:\n- Language: {language}\n- Max length: {max_length} characters\n- Describe what is visible in the image (no keyword stuffing)\n- Do NOT use quotes\n- Return ONLY the alt text\n\nContext:\nSite: {sitename}\nAttachment title: {attachment_title}\nCaption: {caption}\nFilename: {filename}\nParent post title: {parent_title}\nParent excerpt: {parent_excerpt}\nCurrent alt: {current_alt}";
    }

    private static function defaultBriefTemplate(): string
    {
        return (string) (
            "You are an SEO strategist. Build a content brief for the page to rank for the query: {query}.\n" .
            "Site: {sitename}. Language/locale: {language}.\n\n" .
            "Content type preset: {preset}. Search intent: {intent}.\n" .
            "Primary location (if any): {primary_location}.\n\n" .
            "We have an existing page:\n" .
            "- Post title: {post_title}\n" .
            "- Excerpt: {excerpt}\n" .
            "- Existing H2 headings:\n{existing_h2}\n" .
            "- Existing H3 headings:\n{existing_h3}\n\n" .
            "Extracted plain content (may be truncated):\n{content}\n\n" .
            "Google Search Console top queries for this page (range {gsc_start} → {gsc_end}):\n{top_queries}\n\n" .
            "Task: produce a practical content brief to improve rankings for {query}.\n" .
            "Return ONLY valid JSON (no markdown, no commentary) with this schema:\n" .
            "{\n" .
            "  \"query\": string,\n" .
            "  \"h2\": [ { \"title\": string, \"h3\": [string] } ],\n" .
            "  \"faq\": [ { \"q\": string, \"a\": string } ],\n" .
            "  \"recommendations\": [string],\n" .
            "  \"terms\": [string]\n" .
            "}\n\n" .
            "Rules:\n" .
            "- Avoid duplicating existing headings.\n" .
            "- Keep H2/H3 concise.\n" .
            "- FAQ answers should be short (1-3 sentences).\n" .
            "- Include 5-8 H2 sections and 5-8 FAQ items if possible.\n"
        );
    }

    private static function defaultSerpGapTemplate(): string
    {
        return (string) (
            "You are an SEO strategist.\n\n" .
            "Goal: create a better content plan to rank for the query.\n\n" .
            "Query: {query}\n" .
            "Site language/locale: {site_locale}\n" .
            "Site name: {site_name}\n\n" .
            "Target page URL: {target_url}\n" .
            "Target post_id: {post_id}\n" .
            "Target headings (if available):\n{target_headings}\n\n" .
            "Target content preview (truncated):\n{target_preview}\n\n" .
            "SERP titles/snippets (top):\n{serp_snippets}\n\n" .
            "Competitor snapshots (if available):\n{competitor_snapshots}\n\n" .
            "Local missing topics (rough):\n{missing_topics}\n\n" .
            "Recommended competitor word count range (p25–p75): {recommended_word_count_min}–{recommended_word_count_max}\n\n" .
            "Task:\n" .
            "Return ONLY valid JSON (no markdown, no code fences) with keys:\n" .
            "{\n" .
            "  \"outline\": [ {\"h2\": string, \"h3\": [string, ...], \"bullets\": [string, ...]}, ... ],\n" .
            "  \"checklist\": [string, ...],\n" .
            "  \"insights\": [string, ...],\n" .
            "  \"recommended_word_count\": {\"min\": number, \"max\": number}\n" .
            "}\n\n" .
            "Rules:\n" .
            "- Language: {site_locale}\n" .
            "- Outline: 8–14 H2 sections. Each H2 may include 0–5 H3 items.\n" .
            "- Each H2 should include 2–4 bullet talking points (what to cover under that section).\n" .
            "- Checklist: actionable tasks (content, internal links, schema, UX). Avoid duplicates.\n" .
            "- Do not mention competitor brand names; keep wording generic.\n"
        );
    }

    private static function defaultSerpGapFaqTemplate(): string
    {
        return (string) (
            "You are an SEO editor.\n\n" .
            "Task: Generate an FAQ section for a target article that wants to rank for a query.\n\n" .
            "Language/locale: {site_locale}\n" .
            "Query: {query}\n\n" .
            "Missing topics (optional hints):\n{missing_topics}\n\n" .
            "Competitor H2 hints (optional):\n{competitor_h2_hints}\n\n" .
            "Return ONLY valid JSON (no markdown, no code fences) with the shape:\n" .
            "{\"faq\": [{\"q\": string, \"a\": string}, ...]}\n\n" .
            "Rules:\n" .
            "- 5 items.\n" .
            "- Questions should be specific and match the query intent.\n" .
            "- Answers must be short (1–2 sentences), factual, no fluff.\n" .
            "- Do not mention competitor brand names.\n"
        );
    }

    private static function defaultSeoAutofillTemplate(): string
    {
        return (string) (
            "You are an SEO assistant for WordPress. Generate SEO fields for the page below.\n\n" .
            "Rules:\n" .
            "- Language/locale: {language}\n" .
            "- Tone/style: {tone}\n" .
            "- Task: {task}\n" .
            "- Return ONLY valid JSON (no markdown, no commentary).\n" .
            "- Title max length: {title_max_length} characters\n" .
            "- Description max length: {description_max_length} characters\n" .
            "- Avoid keyword stuffing. Keep it natural and helpful.\n" .
            "- Avoid making SEO title identical to the main H1 when possible.\n" .
            "- If you are unsure, keep fields short and safe.\n\n" .
            "Return JSON with this schema:\n" .
            "{\n" .
            "  \"title\": string,\n" .
            "  \"description\": string,\n" .
            "  \"og_title\": string,\n" .
            "  \"og_description\": string,\n" .
            "  \"twitter_title\": string,\n" .
            "  \"twitter_description\": string,\n" .
            "  \"focus_keyword\": string,\n" .
            "  \"schema_type\": string\n" .
            "}\n\n" .
            "Where schema_type must be one of: {schema_allowed}.\n\n" .
            "Context:\n" .
            "Site name: {sitename}\n" .
            "Page type: {context_label}\n" .
            "Title: {post_title}\n" .
            "H1 (if available): {h1}\n" .
            "Excerpt/summary: {excerpt}\n" .
            "Rendered page text (plain): {content}\n" .
            "Current SEO title: {current_seo_title}\n" .
            "Current meta description: {current_meta_description}\n" .
            "Current focus keyword: {current_focus_keyword}\n" .
            "Keyword hints (optional): {keywords_hint}\n"
        );
    }
}
