<?php

namespace ZenoChatbot\Services\LLMService\AIClient\Providers\PromptBuilders;

use ZenoChatbot\Support\ResourceFormatter;

if (!defined('ABSPATH')) {
    exit;
}

/**
 * Base class for provider-specific prompt builders.
 * Contains shared logic for building prompt text and formatting resources.
 */
abstract class Builder
{
    /**
     * Build the combined prompt text from system prompts, resources, and user message.
     */
    protected static function buildPromptText(array $input): string
    {
        $sections = [];

        $systemText = trim(implode("\n", (array)($input['system_prompts'] ?? [])));
        if ($systemText !== '') {
            $sections[] = $systemText;
        }

        $resources = (array)($input['resources'] ?? []);
        if (!empty($resources)) {
            $resText = static::buildResourceText($resources);
            if ($resText !== '') {
                $sections[] = $resText;
            }
        }

        $context = (array)($input['context'] ?? []);
        if (!empty($context)) {
            $contextText = static::buildContextText($context);
            if ($contextText !== '') {
                $sections[] = $contextText;
            }
        }

        $userText = (string)($input['message'] ?? '');
        if ($userText !== '') {
            $sections[] = $userText;
        }

        return trim(implode("\n\n", $sections));
    }

    /**
     * Format conversation turns with clear role headers.
     *
     * @param array $contextTurns
     * @return string
     */
    protected static function buildContextText(array $contextTurns): string
    {
        $lines = [];

        foreach ($contextTurns as $turn) {
            if (!is_array($turn)) {
                continue;
            }

            $message = trim((string)($turn['message'] ?? ''));
            if ($message === '') {
                continue;
            }

            $role = strtolower((string)($turn['role'] ?? 'user'));
            $speaker = in_array($role, ['assistant', 'model'], true) ? 'Assistant' : 'User';
            $lines[] = sprintf('%s: %s', $speaker, $message);
        }

        if (empty($lines)) {
            return '';
        }

        return "Conversation Transcript:\n" . implode("\n", $lines);
    }

    /**
     * Format resources array into readable text for the LLM.
     */
    protected static function buildResourceText(array $resources): string
    {
        $sections = [];

        foreach ($resources as $r) {
            $name = $r['name'] ?? ($r['id'] ?? 'resource');
            $text = trim((string)($r['text'] ?? ''));
            $type = $r['type'] ?? 'text/plain';

            if ($text === '') {
                continue;
            }

            if ($type === 'application/json' || static::isJsonContent($text)) {
                $formatted = ResourceFormatter::fromJson($text);
                if ($formatted !== '') {
                    $header = static::getResourceHeader($name);
                    $sections[] = "## {$header}\n\n{$formatted}";
                }
                continue;
            }

            $sections[] = "## " . static::getResourceHeader($name) . "\n\n" . $text;
        }

        return implode("\n\n", $sections);
    }

    /**
     * Check if text content appears to be JSON.
     */
    protected static function isJsonContent(string $text): bool
    {
        $trimmed = ltrim($text);
        return str_starts_with($trimmed, '[') || str_starts_with($trimmed, '{');
    }

    /**
     * Map resource filenames to human-readable headers.
     */
    protected static function getResourceHeader(string $filename): string
    {
        $map = [
            'internal-content-index.json' => 'Website Content',
            'external-sources.json'       => 'External References',
            'knowledge-notes-index.json'  => 'Knowledge Notes',
            'sitemap-content-index.json'  => 'Sitemap Content',
            'product-content-index.json'  => 'Product Catalog Content',
        ];

        return $map[$filename] ?? $filename;
    }
}
