<?php

namespace ZenoChatbot\Services\LLMService\AIClient\Support;

use ZenoChatbot\Helper\Resources as WPResources;
use ZenoChatbot\Services\ContextCache\ResourceTextCache;
use ZenoChatbot\Services\LLMService\AIClient\Support\Handlers\FileHandler;
use ZenoChatbot\Services\LLMService\AIClient\Support\Handlers\MediaHandler;
use ZenoChatbot\Services\LLMService\AIClient\Support\Handlers\TextHandler;
use ZenoChatbot\Services\LLMService\AIClient\Support\Handlers\UploadHandler;
use ZenoChatbot\Services\LLMService\AIClient\Support\Handlers\UrlHandler;

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

/**
 * Orchestrates resource loading by delegating to specialized handlers.
 * Supports text resources, file resources (images, PDFs), URLs, and uploads.
 */
class ResourceLoader
{
    /**
     * Load resources and return a ResourceResult with text resources, file resources, and skipped files.
     *
     * @param mixed $resources true for defaults, array of resource specs, or string
     * @param array $options Loading options (max_bytes, allowlist, etc.)
     * @return ResourceResult
     */
    public static function loadWithFiles($resources, array $options = []): ResourceResult
    {
        $result = new ResourceResult();

        if ($resources === true) {
            static::loadDefaults($result, $options);
            return $result;
        }

        if (is_string($resources)) {
            $resources = [$resources];
        }

        foreach ((array) $resources as $r) {
            static::processResourceItem($r, $result, $options);
        }

        return $result;
    }

    /**
     * Legacy load method - returns a flat array of text resources only.
     * @deprecated Use loadWithFiles() for file support
     */
    public static function load($resources, array $options = []): array
    {
        $result = static::loadWithFiles($resources, $options);
        return $result->getTextResources();
    }

    /**
     * Load from path - delegates to FileHandler
     */
    public static function loadFromPath(string $path, array $options = []): array
    {
        return FileHandler::loadAsText($path, $options);
    }

    /**
     * Load from URL - delegates to UrlHandler
     */
    public static function loadFromUrl(string $url, array $options = []): array
    {
        return UrlHandler::load($url, $options);
    }

    /**
     * Load default resources (JSON indexes + media)
     */
    private static function loadDefaults(ResourceResult $result, array $options): void
    {
        // Load default text resources (JSON indexes)
        $defaults = [
            'internal-content-index.json',
            'external-sources.json',
            'knowledge-notes-index.json',
            'sitemap-content-index.json',
            'product-content-index.json',
        ];
        $items = WPResources::getResources($defaults);

        foreach ($items as $item) {
            $path = $item['path'] ?? null;
            if ($path) {
                $abs = static::resolvePath($path);
                $rawJson = @file_get_contents($abs);
                if ($rawJson === false || $rawJson === '') {
                    continue;
                }

                $formatted = ResourceTextCache::getOrBuild((string) ($item['name'] ?? basename($abs)), $rawJson);
                if ($formatted !== '') {
                    $result->addTextResource([
                        'id' => md5($abs),
                        'name' => (string) ($item['name'] ?? basename($abs)),
                        'type' => 'text/plain',
                        'text' => TextHandler::trimText($formatted, $options),
                        'path' => $abs,
                    ]);
                }
            }
        }

        // Load media resources (images, PDFs)
        MediaHandler::loadAll($result, $options);
    }

    /**
     * Process a single resource item - routes to appropriate handler
     */
    private static function processResourceItem($r, ResourceResult $result, array $options): void
    {
        // Inline text
        if (is_array($r) && isset($r['text'])) {
            $result->addTextResource(TextHandler::fromInline($r, $options));
            return;
        }

        // Attachment ID
        if (is_array($r) && isset($r['attachment_id'])) {
            MediaHandler::loadAttachment((int) $r['attachment_id'], $result, $options);
            return;
        }

        // File upload
        if (is_array($r) && isset($r['tmp_name'])) {
            $textRes = UploadHandler::load($r, $options);
            if (!empty($textRes['text'])) {
                $result->addTextResource($textRes);
            }
            return;
        }

        // String resource (URL, path, or raw text)
        if (is_string($r)) {
            static::processStringResource($r, $result, $options);
        }
    }

    /**
     * Process string resource - URL, file path, or raw text
     */
    private static function processStringResource(string $r, ResourceResult $result, array $options): void
    {
        // URL
        if (preg_match('~^https?://~i', $r)) {
            $textRes = UrlHandler::load($r, $options);
            if (!empty($textRes['text'])) {
                $result->addTextResource($textRes);
            }
            return;
        }

        // Direct file path
        if (is_file($r)) {
            FileHandler::load($r, $result, $options);
            return;
        }

        // Resolved path
        $abs = static::resolvePath($r);
        if (is_file($abs)) {
            FileHandler::load($abs, $result, $options);
            return;
        }

        // Treat as raw text
        $result->addTextResource(TextHandler::fromRaw($r, $options));
    }

    /**
     * Resolve relative paths to absolute
     */
    private static function resolvePath(string $path): string
    {
        // Absolute path
        if (str_starts_with($path, DIRECTORY_SEPARATOR) || preg_match('~^[A-Za-z]:\\\\~', $path)) {
            return $path;
        }

        // Map wp-content relative paths to absolute
        if (str_starts_with($path, 'wp-content/')) {
            return rtrim(ABSPATH, '/\\') . '/' . ltrim($path, '/\\');
        }

        return $path;
    }
}
