<?php

namespace ZenoChatbot\Helper;

use ZenoChatbot\Support\Hooks;

/**
 * External Sources JSON File Manager
 */
class ExternalSources
{
    /**
     * Get the JSON file path
     *
     * @return string
     */
    private static function getFilePath()
    {
        $upload_dir = wp_upload_dir();
        $plugin_dir = $upload_dir['basedir'] . '/zeno-chatbot-ai';

        // Create directory if it doesn't exist
        if (!file_exists($plugin_dir)) {
            wp_mkdir_p($plugin_dir);
        }

        return $plugin_dir . '/external-sources.json';
    }

    /**
     * Get all external sources
     *
     * @return array
     */
    public static function getAll()
    {
        $file_path = static::getFilePath();

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

        $content = file_get_contents($file_path);
        if ($content === false) {
            return [];
        }

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

    /**
     * Add a new external source
     *
     * @param string $title
     * @param string $link
     * @param string $context
     * @return bool
     */
    public static function add($title, $link, $context = '')
    {
        // Validate inputs
        if (empty($title) || empty($link)) {
            return false;
        }

        if (!filter_var($link, FILTER_VALIDATE_URL)) {
            return false;
        }

        // Get existing sources
        $sources = static::getAll();

        // Check for duplicate links
        foreach ($sources as $source) {
            if ($source['link'] === $link) {
                return false; // Duplicate link
            }
        }

        // Add new source
        $new_source = [
            'title' => sanitize_text_field($title),
            'link' => esc_url_raw($link),
            'context' => sanitize_textarea_field($context)
        ];

        $sources[] = $new_source;
        $saved = static::saveAll($sources);
        if ($saved) {
            static::emitUpdateHooks('add');
        }

        return $saved;
    }

    /**
     * Remove an external source by link
     *
     * @param string $link
     * @return bool
     */
    public static function remove($link)
    {
        $sources = static::getAll();
        $updated_sources = [];

        foreach ($sources as $source) {
            if ($source['link'] !== $link) {
                $updated_sources[] = $source;
            }
        }

        $saved = static::saveAll($updated_sources);
        if ($saved) {
            static::emitUpdateHooks('remove');
        }

        return $saved;
    }

    /**
     * Save all sources to JSON file
     *
     * @param array $sources
     * @return bool
     */
    private static function saveAll($sources)
    {
        $file_path = static::getFilePath();
        $json_content = json_encode($sources, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);

        if ($json_content === false) {
            return false;
        }

        $result = file_put_contents($file_path, $json_content, LOCK_EX);
        return $result !== false;
    }

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

    /**
     * Update an external source
     *
     * @param string $oldLink
     * @param string $title
     * @param string $link
     * @param string $context
     * @return bool
     */
    public static function update($oldLink, $title, $link, $context = '')
    {
        // Validate inputs
        if (empty($title) || empty($link)) {
            return false;
        }

        if (!filter_var($link, FILTER_VALIDATE_URL)) {
            return false;
        }

        $sources = static::getAll();
        $updated = false;

        // Find and update the source
        for ($i = 0; $i < count($sources); $i++) {
            if ($sources[$i]['link'] === $oldLink) {
                // Check for duplicate link (only if link is changing)
                if ($oldLink !== $link) {
                    foreach ($sources as $source) {
                        if ($source['link'] === $link) {
                            return false; // Duplicate link
                        }
                    }
                }

                $sources[$i] = [
                    'title' => sanitize_text_field($title),
                    'link' => esc_url_raw($link),
                    'context' => sanitize_textarea_field($context)
                ];
                $updated = true;
                break;
            }
        }

        if (!$updated) {
            return false; // Source not found
        }

        $saved = static::saveAll($sources);
        if ($saved) {
            static::emitUpdateHooks('update');
        }

        return $saved;
    }

    /**
     * Check if a source exists by link
     *
     * @param string $link
     * @return bool
     */
    public static function exists($link)
    {
        $sources = static::getAll();

        foreach ($sources as $source) {
            if ($source['link'] === $link) {
                return true;
            }
        }

        return false;
    }

    /**
     * Emit index update hooks for cache invalidation.
     *
     * @param string $operation
     * @return void
     */
    private static function emitUpdateHooks($operation)
    {
        $context = [
            'source' => 'external',
            'operation' => sanitize_text_field((string) $operation),
            'timestamp' => gmdate('c'),
        ];

        Hooks::doAction(Hooks::INDEX_EXTERNAL_UPDATED, $context);
    }
}
