<?php

namespace Kylin\LawCase\Services;

use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use Kylin\LawCase\Models\Document;
use Kylin\LawCase\Models\DocumentApproval;
use Kylin\LawCase\Models\DocumentTemplate;

/**
 * 文档服务
 *
 * 处理文档上传、审批、模板生成等业务逻辑。
 */
class DocumentService
{
    public function uploadDocument(int $caseId, UploadedFile $file, array $meta): Document
    {
        $path = $file->store("documents/case_{$caseId}", 'local');
        $hash = hash_file('sha256', $file->getRealPath());

        $document = Document::create([
            'doc_no' => $this->generateDocNo(),
            'doc_type' => $meta['doc_type'] ?? 'other',
            'doc_name' => $meta['doc_name'] ?? $file->getClientOriginalName(),
            'case_id' => $caseId,
            'file_path' => $path,
            'file_hash' => $hash,
            'file_size' => $file->getSize(),
            'is_confidential' => $meta['is_confidential'] ?? false,
            'access_level' => $meta['access_level'] ?? 'case_members',
            'version' => 1,
            'uploaded_by' => auth()->id(),
            'description' => $meta['description'] ?? null,
        ]);

        $this->audit('document_uploaded', $document, [
            'case_id' => $caseId,
            'doc_name' => $document->doc_name,
            'is_confidential' => $document->is_confidential,
        ]);

        return $document;
    }

    public function downloadDocument(Document $document): string
    {
        return Storage::url($document->file_path);
    }

    public function generateFromTemplate(int $templateId, int $caseId, array $variables = []): Document
    {
        $template = DocumentTemplate::findOrFail($templateId);
        $content = $template->template_content;

        // 合并模板预设变量与传入变量
        $allVariables = array_merge($template->variables ?? [], $variables);

        foreach ($allVariables as $key => $value) {
            $content = str_replace("{{{$key}}}", $value, $content);
        }

        $fileName = $template->name . '_' . now()->format('YmdHis') . '.docx';
        $path = "documents/case_{$caseId}/{$fileName}";
        Storage::put($path, $content);

        return Document::create([
            'doc_no' => $this->generateDocNo(),
            'doc_type' => $template->doc_type,
            'doc_name' => $template->name,
            'case_id' => $caseId,
            'file_path' => $path,
            'file_hash' => hash('sha256', $content),
            'file_size' => strlen($content),
            'is_confidential' => false,
            'access_level' => 'case_members',
            'version' => 1,
            'uploaded_by' => auth()->id(),
            'description' => '由模板生成',
        ]);
    }

    /**
     * F-DOC-002 版本控制 - 上传新版本文档
     * 记录每次修改内容，支持版本回溯
     */
    public function uploadNewVersion(Document $document, UploadedFile $file, ?string $changeNote = null): Document
    {
        $caseId = $document->case_id;
        $path = $file->store("documents/case_{$caseId}", 'local');
        $hash = hash_file('sha256', $file->getRealPath());

        return Document::create([
            'doc_no' => $document->doc_no,
            'doc_type' => $document->doc_type,
            'doc_name' => $document->doc_name,
            'case_id' => $caseId,
            'file_path' => $path,
            'file_hash' => $hash,
            'file_size' => $file->getSize(),
            'is_confidential' => $document->is_confidential,
            'access_level' => $document->access_level,
            'version' => $document->version + 1,
            'parent_id' => $document->id,
            'uploaded_by' => auth()->id(),
            'description' => $changeNote ?? "版本{$document->version}的更新",
        ]);
    }

    /**
     * F-DOC-002 版本控制 - 获取文档的版本历史
     */
    public function getVersionHistory(Document $document): array
    {
        // 找到同一 doc_no 的所有版本
        $versions = Document::where('doc_no', $document->doc_no)
            ->orderBy('version')
            ->get()
            ->map(fn($doc) => [
                'id' => $doc->id,
                'version' => $doc->version,
                'doc_name' => $doc->doc_name,
                'file_size' => $doc->file_size,
                'file_hash' => $doc->file_hash,
                'uploaded_by' => $doc->uploaded_by,
                'description' => $doc->description,
                'created_at' => $doc->created_at->toIso8601String(),
            ])
            ->toArray();

        return $versions;
    }

    /**
     * F-DOC-002 版本控制 - 回溯到指定版本
     */
    public function revertToVersion(Document $document, int $targetVersion): Document
    {
        $targetDoc = Document::where('doc_no', $document->doc_no)
            ->where('version', $targetVersion)
            ->firstOrFail();

        // 基于目标版本创建新版本
        return Document::create([
            'doc_no' => $targetDoc->doc_no,
            'doc_type' => $targetDoc->doc_type,
            'doc_name' => $targetDoc->doc_name,
            'case_id' => $targetDoc->case_id,
            'file_path' => $targetDoc->file_path,
            'file_hash' => $targetDoc->file_hash,
            'file_size' => $targetDoc->file_size,
            'is_confidential' => $targetDoc->is_confidential,
            'access_level' => $targetDoc->access_level,
            'version' => Document::where('doc_no', $document->doc_no)->max('version') + 1,
            'parent_id' => $document->id,
            'uploaded_by' => auth()->id(),
            'description' => "回溯至版本{$targetVersion}",
        ]);
    }

    private function generateDocNo(): string
    {
        $date = now()->format('Ymd');
        $lastDoc = Document::whereDate('created_at', today())
            ->orderByDesc('id')
            ->first();
        $sequence = $lastDoc ? (intval(substr($lastDoc->doc_no, -4)) + 1) : 1;

        return sprintf('DOC-%s-%04d', $date, $sequence);
    }

    /**
     * F-DOC-006 提交文档审批
     */
    public function submitForApproval(Document $document, int $approverId): DocumentApproval
    {
        return DocumentApproval::create([
            'document_id' => $document->id,
            'approver_id' => $approverId,
            'status' => 'pending',
        ]);
    }

    /**
     * F-DOC-006 审批文档
     */
    public function approveDocument(DocumentApproval $approval, string $status, ?string $comment = null): DocumentApproval
    {
        $approval->update([
            'status' => $status,
            'comment' => $comment,
            'approved_at' => now(),
        ]);

        $this->audit('document_approved', $approval->document, [
            'approval_status' => $status,
            'approver_id' => $approval->approver_id,
        ]);

        return $approval->fresh();
    }

    /**
     * F-DOC-006 获取文档审批记录
     */
    public function getApprovalHistory(Document $document)
    {
        return DocumentApproval::where('document_id', $document->id)
            ->with('approver')
            ->orderByDesc('created_at')
            ->get();
    }

    /**
     * 记录文档审计日志
     *
     * 依据《律师法》和《保守国家秘密法》，
     * 案件文档上传、审批等操作需记录审计日志。
     */
    private function audit(string $event, Document $document, array $extra = []): void
    {
        if (! class_exists(\Kylin\AuditLog\Models\AuditLog::class)) {
            return;
        }

        try {
            \Kylin\AuditLog\Models\AuditLog::create([
                'event' => $event,
                'model_type' => Document::class,
                'model_id' => $document->id,
                'new_values' => $extra,
                'old_values' => null,
                'user_id' => auth()->id(),
                'ip' => request()?->ip(),
                'url' => request()?->fullUrl(),
                'tag' => 'law-case-document',
            ]);
        } catch (\Throwable $e) {
            logger()->warning('文档审计日志写入失败', [
                'error' => $e->getMessage(),
                'document_id' => $document->id,
                'event' => $event,
            ]);
        }
    }
}
