#include <algorithm>
#include "./table.hpp"
#include "./builder.hpp"

namespace lsp::language::symbol
{
    SymbolTable::SymbolTable()
    {
    }

    void SymbolTable::Build(ast::ASTNode& root)
    {
        Clear();

        Builder builder(*this);
        builder.Build(root);

        // 构建完成后优化位置索引
        location_index_.RebuildIndex();
    }

    void SymbolTable::Clear()
    {
        definition_store_.Clear();
        scope_manager_.Clear();
        location_index_.Clear();
        reference_graph_.Clear();
        inheritance_graph_.Clear();
        call_graph_.Clear();
        unit_imports_.clear();
        import_index_.clear();
    }

    const SymbolDefinition* SymbolTable::GetDefinition(SymbolId id) const
    {
        return definition_store_.Get(id);
    }

    std::vector<const SymbolDefinition*> SymbolTable::GetAllDefinitions() const
    {
        return definition_store_.GetAll();
    }

    std::vector<const SymbolDefinition*> SymbolTable::FindDefinitionsByName(const std::string& name) const
    {
        return definition_store_.FindByName(name);
    }

    std::optional<SymbolId> SymbolTable::FindSymbolAt(const ast::Location& location) const
    {
        return location_index_.FindSymbolAt(location);
    }

    std::optional<SymbolId> SymbolTable::FindSymbol(const std::string& name, ScopeId scope_id) const
    {
        return scope_manager_.FindInScopeChain(scope_id, name);
    }

    std::vector<SymbolId> SymbolTable::FindSymbolsByName(const std::string& name) const
    {
        std::vector<SymbolId> result;
        auto defs = definition_store_.FindByName(name);
        for (const auto* def : defs)
            result.push_back(def->id);
        return result;
    }

    std::optional<ScopeId> SymbolTable::FindScopeAt(const ast::Location& location) const
    {
        return location_index_.FindScopeAt(location);
    }

    std::optional<SymbolId> SymbolTable::FindReferenceAt(const ast::Location& location) const
    {
        return location_index_.FindReferenceAt(location);
    }

    std::vector<SymbolId> SymbolTable::GetChildren(SymbolId symbol_id) const
    {
        return definition_store_.GetChildren(symbol_id);
    }

    ScopeId SymbolTable::GetGlobalScope() const
    {
        return scope_manager_.GetGlobalScope();
    }

    const std::vector<Reference>* SymbolTable::GetReferences(SymbolId symbol_id) const
    {
        return reference_graph_.GetReferences(symbol_id);
    }

    std::optional<ast::Location> SymbolTable::GetDefinitionLocation(SymbolId symbol_id) const
    {
        return reference_graph_.GetDefinition(symbol_id);
    }

    const std::vector<SymbolId>* SymbolTable::GetBaseClasses(SymbolId class_id) const
    {
        return inheritance_graph_.GetBaseClasses(class_id);
    }

    const std::vector<SymbolId>* SymbolTable::GetDerivedClasses(SymbolId class_id) const
    {
        return inheritance_graph_.GetDerivedClasses(class_id);
    }

    const std::vector<CallRelation>* SymbolTable::GetCallers(SymbolId function_id) const
    {
        return call_graph_.GetCallers(function_id);
    }

    const std::vector<CallRelation>* SymbolTable::GetCallees(SymbolId function_id) const
    {
        return call_graph_.GetCallees(function_id);
    }

    // ===== Unit 导入管理实现 =====

    void SymbolTable::AddUnitImport(const std::string& unit_name, const ast::Location& location)
    {
        // 检查是否已经导入过（避免重复）
        if (import_index_.find(unit_name) != import_index_.end())
        {
            // 已经存在，可以选择：
            // 1. 忽略重复导入
            // 2. 记录多次导入（用于诊断）
            // 这里选择忽略
            return;
        }

        size_t index = unit_imports_.size();
        unit_imports_.push_back(UnitImport{ unit_name, location });
        import_index_[unit_name] = index;
    }

    const std::vector<UnitImport>& SymbolTable::GetUnitImports() const
    {
        return unit_imports_;
    }

    std::optional<ast::Location> SymbolTable::FindImportLocation(const std::string& unit_name) const
    {
        auto it = import_index_.find(unit_name);
        if (it != import_index_.end() && it->second < unit_imports_.size())
        {
            return unit_imports_[it->second].location;
        }
        return std::nullopt;
    }

    bool SymbolTable::HasImport(const std::string& unit_name) const
    {
        return import_index_.find(unit_name) != import_index_.end();
    }

    // ===== LSP 接口实现 =====

    std::vector<const SymbolDefinition*> SymbolTable::GetDocumentSymbols() const
    {
        std::vector<const SymbolDefinition*> result;

        for (const auto* def : definition_store_.GetAll())
        {
            // 只返回顶层符号（没有父符号的符号）
            if (!def->parent_id)
                result.push_back(def);
        }

        return result;
    }

    std::vector<const SymbolDefinition*> SymbolTable::GetWorkspaceSymbols(const std::string& query) const
    {
        if (query.empty())
            return definition_store_.GetAll();

        // 使用小写查询字符串进行大小写无关的匹配
        std::string lower_query = utils::ToLower(query);

        std::vector<const SymbolDefinition*> result;
        for (const auto* def : definition_store_.GetAll())
        {
            std::string lower_name = utils::ToLower(def->name);
            if (lower_name.find(lower_query) != std::string::npos)
                result.push_back(def);
        }

        return result;
    }

    // ===== Builder 专用内部接口实现 =====

    SymbolId SymbolTable::CreateSymbol(
        const std::string& name,
        SymbolKind kind,
        const ast::Location& location,
        ScopeId scope_id,
        std::optional<SymbolId> parent_id,
        const std::optional<std::string>& type_hint,
        bool is_class_method)
    {
        // 创建符号定义
        SymbolDefinition def;
        def.name = name;
        def.kind = kind;
        def.location = location;
        def.selection_range = location;
        def.type_hint = type_hint;
        def.parent_id = parent_id;
        def.is_class_method = is_class_method;

        SymbolId symbol_id = definition_store_.Add(std::move(def));

        // 统一处理所有索引更新
        scope_manager_.AddSymbol(scope_id, name, symbol_id);
        location_index_.AddSymbol(symbol_id, location);

        // 添加定义引用
        reference_graph_.AddReference(symbol_id, location, true, false);
        location_index_.AddReference(symbol_id, location);

        return symbol_id;
    }

    ScopeId SymbolTable::CreateScope(ScopeKind kind, const ast::Location& range, std::optional<ScopeId> parent_scope_id, std::optional<SymbolId> associated_symbol_id)
    {
        ScopeId scope_id = scope_manager_.CreateScope(kind, range, parent_scope_id, associated_symbol_id);

        // 添加到位置索引
        location_index_.AddScope(scope_id, range);

        return scope_id;
    }

    void SymbolTable::AddReference(SymbolId symbol_id, const ast::Location& location, bool is_write)
    {
        reference_graph_.AddReference(symbol_id, location, false, is_write);
        location_index_.AddReference(symbol_id, location);
    }

}
