<?php

namespace App\Services;

use App\Models\Document;
use App\Models\DownloadLog;
use App\Models\User;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Symfony\Component\HttpFoundation\StreamedResponse;

class DocumentService
{
    /**
     * 上传文档
     * 
     * @param UploadedFile $file 上传的文件
     * @param string $title 文档标题
     * @param string $type 文档类型 ('global' 或 'dedicated')
     * @param int|null $groupId 分组 ID (专用文档必填)
     * @param int $uploaderId 上传者用户 ID
     * @return Document
     * @throws \Exception
     */
    public function uploadDocument(
        UploadedFile $file,
        string $title,
        string $type,
        ?int $groupId,
        int $uploaderId
    ): Document {
        // 验证文件格式
        $extension = strtolower($file->getClientOriginalExtension());
        if (!in_array($extension, ['doc', 'docx'])) {
            throw new \InvalidArgumentException('文件格式不支持，请上传 Word 文档（.doc 或 .docx）');
        }

        // 验证专用文档必须有分组
        if ($type === 'dedicated' && empty($groupId)) {
            throw new \InvalidArgumentException('专用知识库文档必须指定所属分组');
        }

        // 使用事务确保一致性
        return DB::transaction(function () use ($file, $title, $type, $groupId, $uploaderId) {
            // 获取原始文件名
            $originalFileName = $file->getClientOriginalName();
            
            // 生成文件存储路径，使用原始文件名
            $directory = 'documents/' . date('Y/m/d');
            $filePath = $file->storeAs($directory, $originalFileName, 'local');

            // 创建数据库记录，设置初始转换状态为 pending
            $document = Document::create([
                'title' => $title,
                'file_path' => $filePath,
                'file_name' => $originalFileName,
                'file_size' => $file->getSize(),
                'mime_type' => $file->getMimeType(),
                'type' => $type,
                'group_id' => $groupId,
                'uploaded_by' => $uploaderId,
                'description' => '',
                'conversion_status' => 'pending',
            ]);

            // 文档保存成功后，触发异步转换
            $conversionService = app(DocumentConversionService::class);
            $conversionService->queueConversion($document);

            return $document;
        });
    }

    /**
     * 验证用户是否有权访问指定文档
     * 
     * @param Document $document 要访问的文档
     * @param User $user 用户
     * @return bool
     */
    public function validateDocumentAccess(Document $document, User $user): bool
    {
        // 如果是全局文档，所有用户都可以访问
        if ($document->type === 'global') {
            return true;
        }

        // 如果是专用文档，检查用户是否属于该文档的分组
        if ($document->type === 'dedicated') {
            // 获取用户所属的所有分组 ID
            $userGroupIds = $user->groups()->pluck('groups.id')->toArray();
            
            // 检查文档的分组 ID 是否在用户的分组列表中
            return in_array($document->group_id, $userGroupIds);
        }

        return false;
    }

    /**
     * 下载文档
     * 
     * @param Document $document 要下载的文档
     * @param User $user 用户
     * @return StreamedResponse
     * @throws \Exception
     */
    public function downloadDocument(Document $document, User $user): StreamedResponse
    {
        // 验证用户权限
        if (!$this->validateDocumentAccess($document, $user)) {
            throw new \Exception('您没有权限访问此文档');
        }

        // 检查文件是否存在
        if (!Storage::disk('local')->exists($document->file_path)) {
            throw new \Exception('文档不存在或已被删除');
        }

        // 返回文件流式响应，使用原始文件名
        return Storage::disk('local')->download(
            $document->file_path,
            $document->file_name
        );
    }

    /**
     * 记录文档下载日志
     * 
     * @param Document $document 被下载的文档
     * @param User $user 下载的用户
     * @param string|null $ipAddress IP 地址
     * @return DownloadLog
     */
    public function logDownload(Document $document, User $user, ?string $ipAddress = null): DownloadLog
    {
        return DownloadLog::create([
            'document_id' => $document->id,
            'user_id' => $user->id,
            'downloaded_at' => now(),
            'ip_address' => $ipAddress ?? request()->ip(),
        ]);
    }
}
