<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Laravel\Scout\Searchable;

class Document extends Model
{
    use HasFactory, Searchable;
    /**
     * 可批量赋值的属性
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'title',
        'file_path',
        'file_name',
        'file_size',
        'mime_type',
        'uploaded_by',
        'description',
        'markdown_path',
        'conversion_status',
        'conversion_error',
        'knowledge_base_id',
    ];

    /**
     * 获取文档所属的知识库
     */
    public function knowledgeBase(): BelongsTo
    {
        return $this->belongsTo(KnowledgeBase::class);
    }

    /**
     * 获取文档的上传者
     */
    public function uploader(): BelongsTo
    {
        return $this->belongsTo(User::class, 'uploaded_by');
    }

    /**
     * 获取文档的所有下载日志
     */
    public function downloadLogs(): HasMany
    {
        return $this->hasMany(DownloadLog::class);
    }

    /**
     * 获取可搜索的数组数据
     * 用于 Meilisearch 索引
     */
    public function toSearchableArray(): array
    {
        return [
            'id' => $this->id,
            'title' => $this->title,
            'file_name' => $this->file_name,
            'description' => $this->description,
            'markdown_content' => $this->getMarkdownContent(),
            'knowledge_base_id' => $this->knowledge_base_id,
            'uploaded_by' => $this->uploaded_by,
            'created_at' => $this->created_at?->timestamp,
        ];
    }

    /**
     * 判断文档是否应该被索引
     * 只有转换完成的文档才会被索引
     */
    public function shouldBeSearchable(): bool
    {
        return $this->conversion_status === 'completed';
    }

    /**
     * 获取完整的 Markdown 内容
     * 从文件系统读取 Markdown 文件
     */
    public function getMarkdownContent(): ?string
    {
        if (!$this->markdown_path) {
            return null;
        }

        try {
            if (Storage::disk('markdown')->exists($this->markdown_path)) {
                return Storage::disk('markdown')->get($this->markdown_path);
            }
        } catch (\Exception $e) {
            \Log::warning('Failed to read markdown content', [
                'document_id' => $this->id,
                'markdown_path' => $this->markdown_path,
                'error' => $e->getMessage()
            ]);
        }

        return null;
    }

    /**
     * 检查文档是否已转换为 Markdown
     */
    public function hasMarkdown(): bool
    {
        return !empty($this->markdown_path) && $this->conversion_status === 'completed';
    }

    /**
     * 获取用于展示和下载的文件名
     * 对历史上误保存为随机存储名的记录回退到“标题.扩展名”
     */
    public function getDisplayFileNameAttribute(): string
    {
        $fileName = trim((string) $this->file_name);

        if ($fileName !== '' && ! $this->looksLikeGeneratedStorageName($fileName)) {
            return $fileName;
        }

        $extension = pathinfo($fileName ?: $this->file_path, PATHINFO_EXTENSION);
        $title = trim((string) $this->title);
        $title = preg_replace('/[<>:"\/\\\\|?*\x00-\x1F]+/u', '-', $title) ?? '';
        $title = trim($title, " .-\t\n\r\0\x0B");
        $title = $title !== '' ? $title : 'document';

        return $extension !== '' ? "{$title}.{$extension}" : $title;
    }

    protected function looksLikeGeneratedStorageName(string $fileName): bool
    {
        $baseName = pathinfo($fileName, PATHINFO_FILENAME);

        return Str::isUuid($baseName)
            || (bool) preg_match('/^[0-9A-HJKMNP-TV-Z]{26}$/i', $baseName);
    }
}
