<?php

namespace ZenoChatbot\Services\Indexing\Engine;

use ZenoChatbot\Helper\Resources;
use ZenoChatbot\Helper\Settings;
use ZenoChatbot\Support\Hooks;

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

/**
 * Knowledge Notes JSON file manager.
 */
class KnowledgeNotesIndexEngine
{
    /**
     * @return string
     */
    private static function getFilePath(): string
    {
        return Resources::getBaseDirPath() . '/knowledge-notes-index.json';
    }

    /**
     * @return array<int,array<string,string>>
     */
    public static function getAll(): array
    {
        $filePath = static::getFilePath();

        if (!file_exists($filePath)) {
            return [];
        }

        $content = file_get_contents($filePath);
        if ($content === false || $content === '') {
            return [];
        }

        $decoded = json_decode($content, true);
        return is_array($decoded) ? $decoded : [];
    }

    /**
     * @return string
     */
    public static function getContent(): string
    {
        $items = static::getAll();
        if (!isset($items[0]) || !is_array($items[0])) {
            return '';
        }

        return (string) ($items[0]['context'] ?? '');
    }

    /**
     * @param string $content
     * @return array<string,mixed>
     */
    public static function saveContent(string $content): array
    {
        $normalized = static::normalizeContent($content);

        $items = [];
        if (trim($normalized) !== '') {
            $items[] = [
                'title' => 'Knowledge Notes',
                'context' => $normalized,
                'link' => '',
            ];
        }

        if (!static::saveAll($items)) {
            return [
                'success' => false,
                'message' => 'Failed to save knowledge notes index.',
            ];
        }

        Settings::update('knowledge_notes_index.last_indexed_at', gmdate('Y-m-d H:i:s'));
        Settings::update('knowledge_notes_index.indexed_count', count($items));
        static::emitUpdateHooks('save');

        return [
            'success' => true,
            'message' => 'Knowledge notes saved successfully.',
            'data' => [
                'indexed_count' => count($items),
                'content_length' => strlen($normalized),
            ],
        ];
    }

    /**
     * @return array<string,mixed>
     */
    public static function clearIndex(): array
    {
        $previousLength = strlen(static::getContent());
        if (!static::saveAll([])) {
            return [
                'success' => false,
                'message' => 'Failed to clear knowledge notes index.',
            ];
        }

        Settings::delete('knowledge_notes_index.last_indexed_at');
        Settings::delete('knowledge_notes_index.indexed_count');
        static::emitUpdateHooks('clear');

        return [
            'success' => true,
            'message' => 'Knowledge notes index cleared successfully.',
            'data' => [
                'cleared_length' => $previousLength,
            ],
        ];
    }

    /**
     * @return array<string,mixed>
     */
    public static function getStats(): array
    {
        $content = static::getContent();

        return [
            'total_count' => static::count(),
            'content_length' => strlen($content),
            'last_indexed_at' => Settings::get('knowledge_notes_index.last_indexed_at'),
            'indexed_count' => Settings::get('knowledge_notes_index.indexed_count', 0),
        ];
    }

    /**
     * @return int
     */
    public static function count(): int
    {
        return count(static::getAll());
    }

    /**
     * @param array<int,array<string,string>> $items
     * @return bool
     */
    private static function saveAll(array $items): bool
    {
        $jsonContent = json_encode($items, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
        if ($jsonContent === false) {
            return false;
        }

        return file_put_contents(static::getFilePath(), $jsonContent, LOCK_EX) !== false;
    }

    /**
     * @param string $content
     * @return string
     */
    private static function normalizeContent(string $content): string
    {
        $content = wp_check_invalid_utf8($content);
        $content = str_replace("\0", '', $content);
        return trim($content);
    }

    /**
     * @param string $operation
     * @return void
     */
    private static function emitUpdateHooks(string $operation): void
    {
        Hooks::doAction(Hooks::INDEX_KNOWLEDGE_NOTES_UPDATED, [
            'source' => 'knowledge_notes',
            'operation' => sanitize_text_field($operation),
            'timestamp' => gmdate('c'),
        ]);
    }
}
