<?php

namespace App\Services;

use App\Models\Document;
use App\Models\KnowledgeBase;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\Log;

class DocumentSearchService
{
    /**
     * 搜索文档
     *
     * @param string $query 搜索关键词
     * @param array $accessibleStationIds 权限边界的线站 IDs（空=不限制）
     * @param array $filters 用户主动筛选:
     *   - station_ids: int[] 线站 ID
     *   - knowledge_base_ids: int[] 知识库 ID
     *   - uploaded_by: int 上传者 ID
     * @return Collection
     */
    public function search(string $query, array $accessibleStationIds = [], array $filters = []): Collection
    {
        try {
            $kbIds = $this->resolveKnowledgeBaseIds($accessibleStationIds, $filters);

            $searchBuilder = Document::search($query);

            if (!empty($filters['uploaded_by'])) {
                $searchBuilder->where('uploaded_by', $filters['uploaded_by']);
            }

            if (!empty($kbIds)) {
                $searchBuilder->query(fn ($q) => $q->whereIn('knowledge_base_id', $kbIds));
            }

            return $searchBuilder->get();
        } catch (\Exception $e) {
            Log::error('文档搜索失败', [
                'query' => $query,
                'filters' => $filters,
                'error' => $e->getMessage(),
            ]);

            return new Collection();
        }
    }

    /**
     * 解析最终可搜索的知识库 ID 列表
     *
     * 1. 从 accessibleStationIds 得到可访问 KB（全局 KB + 关联 station 的 KB）
     * 2. 从 filters 得到用户指定的 KB（station_ids + knowledge_base_ids 并集）
     * 3. 取交集（若有 filter 指定），否则用可访问范围
     */
    private function resolveKnowledgeBaseIds(array $accessibleStationIds, array $filters): array
    {
        // 权限边界
        $accessibleKbIds = null;
        if (!empty($accessibleStationIds)) {
            $accessibleKbIds = KnowledgeBase::where(function ($q) use ($accessibleStationIds) {
                $q->whereDoesntHave('stations')
                  ->orWhereHas('stations', fn ($sq) => $sq->whereIn('stations.id', $accessibleStationIds));
            })->pluck('id')->toArray();
        }

        // 用户主动筛选
        $kbIdsFromStations = [];
        if (!empty($filters['station_ids'])) {
            $kbIdsFromStations = KnowledgeBase::where(function ($q) use ($filters) {
                $q->whereDoesntHave('stations')
                  ->orWhereHas('stations', fn ($sq) => $sq->whereIn('stations.id', $filters['station_ids']));
            })->pluck('id')->toArray();
        }

        $kbIdsFromFilter = $filters['knowledge_base_ids'] ?? [];

        if (!empty($kbIdsFromStations) && !empty($kbIdsFromFilter)) {
            $filterKbIds = array_values(array_intersect($kbIdsFromStations, $kbIdsFromFilter));
        } elseif (!empty($kbIdsFromStations)) {
            $filterKbIds = $kbIdsFromStations;
        } elseif (!empty($kbIdsFromFilter)) {
            $filterKbIds = $kbIdsFromFilter;
        } else {
            $filterKbIds = [];
        }

        // 合并
        if ($accessibleKbIds === null) {
            return $filterKbIds; // 无权限限制
        }

        if (empty($filterKbIds)) {
            return $accessibleKbIds; // 无主动筛选，用权限范围
        }

        return array_values(array_intersect($filterKbIds, $accessibleKbIds)); // 取交集
    }

    /**
     * 准备文档的可搜索数据
     */
    public function prepareSearchableData(Document $document): array
    {
        return [
            'id' => $document->id,
            'title' => $document->title,
            'description' => $document->description,
            'markdown_content' => $document->getMarkdownContent(),
            'knowledge_base_id' => $document->knowledge_base_id,
            'uploaded_by' => $document->uploaded_by,
            'created_at' => $document->created_at?->timestamp,
            'updated_at' => $document->updated_at?->timestamp,
        ];
    }

    public function indexDocument(Document $document): void
    {
        try {
            if (!$document->shouldBeSearchable()) {
                return;
            }
            $document->searchable();
        } catch (\Exception $e) {
            Log::error('文档索引失败', ['document_id' => $document->id, 'error' => $e->getMessage()]);
        }
    }

    public function updateDocumentIndex(Document $document): void
    {
        try {
            if ($document->shouldBeSearchable()) {
                $document->searchable();
            } else {
                $this->removeDocumentFromIndex($document);
            }
        } catch (\Exception $e) {
            Log::error('文档索引更新失败', ['document_id' => $document->id, 'error' => $e->getMessage()]);
        }
    }

    public function removeDocumentFromIndex(Document $document): void
    {
        try {
            $document->unsearchable();
        } catch (\Exception $e) {
            Log::error('文档索引移除失败', ['document_id' => $document->id, 'error' => $e->getMessage()]);
        }
    }
}
