<?php

namespace ZenoChatbot\Services\LLMService\AIClient\Support\Handlers;

use ZenoChatbot\Services\LLMService\AIClient\Support\FileResource;
use ZenoChatbot\Services\LLMService\AIClient\Support\ResourceResult;

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

/**
 * Handles loading file resources from filesystem paths.
 * Determines whether files should be loaded as binary (FileResource) or text.
 */
class FileHandler
{
    /**
     * Load a file from path into the result.
     * Binary files (images, PDFs) become FileResource, text files become text resources.
     */
    public static function load(string $path, ResourceResult $result, array $options = []): void
    {
        $name = basename($path);
        $mimeType = static::inferMimeType($path);
        $fileSize = @filesize($path) ?: 0;

        // Check if this is a file type that should be sent to API natively
        if (FileResource::isSupportedMimeType($mimeType)) {
            static::loadAsBinary($path, $name, $mimeType, $fileSize, $result);
            return;
        }

        // Otherwise load as text resource
        $textRes = static::loadAsText($path, $options);
        if (!empty($textRes['text'])) {
            $result->addTextResource($textRes);
        }
    }

    /**
     * Load file as binary FileResource (for images, PDFs)
     */
    private static function loadAsBinary(
        string $path,
        string $name,
        string $mimeType,
        int $fileSize,
        ResourceResult $result
    ): void {
        if (!FileResource::isWithinSizeLimit($fileSize)) {
            $result->addSkippedFile($name, 'File exceeds 15MB size limit');
            return;
        }

        if (!is_readable($path)) {
            $result->addSkippedFile($name, 'File not accessible');
            return;
        }

        $content = @file_get_contents($path);
        if ($content === false) {
            $result->addSkippedFile($name, 'Failed to read file');
            return;
        }

        $result->addFileResource(new FileResource(
            md5($path),
            $name,
            $mimeType,
            base64_encode($content),
            $fileSize,
            $path
        ));
    }

    /**
     * Load file as text resource
     */
    public static function loadAsText(string $path, array $options = []): array
    {
        $name = basename($path);

        if (!is_readable($path)) {
            return [
                'id' => md5($path),
                'name' => $name,
                'type' => 'application/octet-stream',
                'text' => '',
                'path' => $path,
            ];
        }

        $content = @file_get_contents($path) ?: '';
        $type = static::inferTypeFromFilename($name);
        $content = TextHandler::trimText($content, $options);

        return [
            'id' => md5($path),
            'name' => $name,
            'type' => $type,
            'text' => $content,
            'path' => $path,
        ];
    }

    /**
     * Infer MIME type from file path
     */
    public static function inferMimeType(string $path): string
    {
        if (function_exists('mime_content_type')) {
            $mime = @mime_content_type($path);
            if ($mime) {
                return $mime;
            }
        }

        return static::inferTypeFromFilename(basename($path));
    }

    /**
     * Infer MIME type from filename extension
     */
    public static function inferTypeFromFilename(string $name): string
    {
        $ext = strtolower(pathinfo($name, PATHINFO_EXTENSION));

        $map = [
            'json' => 'application/json',
            'txt'  => 'text/plain',
            'md'   => 'text/plain',
            'html' => 'text/html',
            'htm'  => 'text/html',
            'pdf'  => 'application/pdf',
            'jpg'  => 'image/jpeg',
            'jpeg' => 'image/jpeg',
            'png'  => 'image/png',
            'gif'  => 'image/gif',
            'webp' => 'image/webp',
        ];

        return $map[$ext] ?? 'application/octet-stream';
    }

}

