/**
 * Asset database for managing asset metadata
 * 用于管理资产元数据的资产数据库
 */

import {
    AssetGUID,
    AssetType,
    IAssetMetadata,
    IAssetCatalogEntry
} from '../types/AssetTypes';

/**
 * Asset database implementation
 * 资产数据库实现
 */
export class AssetDatabase {
    private readonly _metadata = new Map<AssetGUID, IAssetMetadata>();
    private readonly _pathToGuid = new Map<string, AssetGUID>();
    private readonly _typeToGuids = new Map<AssetType, Set<AssetGUID>>();
    private readonly _labelToGuids = new Map<string, Set<AssetGUID>>();
    private readonly _dependencies = new Map<AssetGUID, Set<AssetGUID>>();
    private readonly _dependents = new Map<AssetGUID, Set<AssetGUID>>();

    /**
     * Add asset to database
     * 添加资产到数据库
     */
    addAsset(metadata: IAssetMetadata): void {
        const { guid, path, type, labels, dependencies } = metadata;

        // 存储元数据 / Store metadata
        this._metadata.set(guid, metadata);
        this._pathToGuid.set(path, guid);

        // 按类型索引 / Index by type
        if (!this._typeToGuids.has(type)) {
            this._typeToGuids.set(type, new Set());
        }
        this._typeToGuids.get(type)!.add(guid);

        // 按标签索引 / Index by labels
        labels.forEach((label) => {
            if (!this._labelToGuids.has(label)) {
                this._labelToGuids.set(label, new Set());
            }
            this._labelToGuids.get(label)!.add(guid);
        });

        // 建立依赖关系 / Establish dependencies
        this.updateDependencies(guid, dependencies);
    }

    /**
     * Remove asset from database
     * 从数据库移除资产
     */
    removeAsset(guid: AssetGUID): void {
        const metadata = this._metadata.get(guid);
        if (!metadata) return;

        // 清理元数据 / Clean up metadata
        this._metadata.delete(guid);
        this._pathToGuid.delete(metadata.path);

        // 清理类型索引 / Clean up type index
        const typeSet = this._typeToGuids.get(metadata.type);
        if (typeSet) {
            typeSet.delete(guid);
            if (typeSet.size === 0) {
                this._typeToGuids.delete(metadata.type);
            }
        }

        // 清理标签索引 / Clean up label indices
        metadata.labels.forEach((label) => {
            const labelSet = this._labelToGuids.get(label);
            if (labelSet) {
                labelSet.delete(guid);
                if (labelSet.size === 0) {
                    this._labelToGuids.delete(label);
                }
            }
        });

        // 清理依赖关系 / Clean up dependencies
        this.clearDependencies(guid);
    }

    /**
     * Update asset metadata
     * 更新资产元数据
     */
    updateAsset(guid: AssetGUID, updates: Partial<IAssetMetadata>): void {
        const metadata = this._metadata.get(guid);
        if (!metadata) return;

        // 如果路径改变，更新索引 / Update index if path changed
        if (updates.path && updates.path !== metadata.path) {
            this._pathToGuid.delete(metadata.path);
            this._pathToGuid.set(updates.path, guid);
        }

        // 如果类型改变，更新索引 / Update index if type changed
        if (updates.type && updates.type !== metadata.type) {
            const oldTypeSet = this._typeToGuids.get(metadata.type);
            if (oldTypeSet) {
                oldTypeSet.delete(guid);
            }

            if (!this._typeToGuids.has(updates.type)) {
                this._typeToGuids.set(updates.type, new Set());
            }
            this._typeToGuids.get(updates.type)!.add(guid);
        }

        // 如果依赖改变，更新关系 / Update relations if dependencies changed
        if (updates.dependencies) {
            this.updateDependencies(guid, updates.dependencies);
        }

        // 合并更新 / Merge updates
        Object.assign(metadata, updates);
        metadata.lastModified = Date.now();
        metadata.version++;
    }

    /**
     * Get asset metadata
     * 获取资产元数据
     */
    getMetadata(guid: AssetGUID): IAssetMetadata | undefined {
        return this._metadata.get(guid);
    }

    /**
     * Get metadata by path
     * 通过路径获取元数据
     */
    getMetadataByPath(path: string): IAssetMetadata | undefined {
        const guid = this._pathToGuid.get(path);
        return guid ? this._metadata.get(guid) : undefined;
    }

    /**
     * Find assets by type
     * 按类型查找资产
     */
    findAssetsByType(type: AssetType): AssetGUID[] {
        const guids = this._typeToGuids.get(type);
        return guids ? Array.from(guids) : [];
    }

    /**
     * Find assets by label
     * 按标签查找资产
     */
    findAssetsByLabel(label: string): AssetGUID[] {
        const guids = this._labelToGuids.get(label);
        return guids ? Array.from(guids) : [];
    }

    /**
     * Find assets by multiple labels (AND operation)
     * 按多个标签查找资产（AND操作）
     */
    findAssetsByLabels(labels: string[]): AssetGUID[] {
        if (labels.length === 0) return [];

        let result: Set<AssetGUID> | null = null;

        for (const label of labels) {
            const labelGuids = this._labelToGuids.get(label);
            if (!labelGuids || labelGuids.size === 0) return [];

            if (!result) {
                result = new Set(labelGuids);
            } else {
                // 交集 / Intersection
                const intersection = new Set<AssetGUID>();
                labelGuids.forEach((guid) => {
                    if (result!.has(guid)) {
                        intersection.add(guid);
                    }
                });
                result = intersection;
            }
        }

        return result ? Array.from(result) : [];
    }

    /**
     * Search assets by query
     * 通过查询搜索资产
     */
    searchAssets(query: {
        name?: string;
        type?: AssetType;
        labels?: string[];
        path?: string;
    }): AssetGUID[] {
        let results = Array.from(this._metadata.keys());

        // 按名称过滤 / Filter by name
        if (query.name) {
            const nameLower = query.name.toLowerCase();
            results = results.filter((guid) => {
                const metadata = this._metadata.get(guid)!;
                return metadata.name.toLowerCase().includes(nameLower);
            });
        }

        // 按类型过滤 / Filter by type
        if (query.type) {
            const typeGuids = this._typeToGuids.get(query.type);
            if (!typeGuids) return [];
            results = results.filter((guid) => typeGuids.has(guid));
        }

        // 按标签过滤 / Filter by labels
        if (query.labels && query.labels.length > 0) {
            const labelResults = this.findAssetsByLabels(query.labels);
            const labelSet = new Set(labelResults);
            results = results.filter((guid) => labelSet.has(guid));
        }

        // 按路径过滤 / Filter by path
        if (query.path) {
            const pathLower = query.path.toLowerCase();
            results = results.filter((guid) => {
                const metadata = this._metadata.get(guid)!;
                return metadata.path.toLowerCase().includes(pathLower);
            });
        }

        return results;
    }

    /**
     * Get asset dependencies
     * 获取资产依赖
     */
    getDependencies(guid: AssetGUID): AssetGUID[] {
        const deps = this._dependencies.get(guid);
        return deps ? Array.from(deps) : [];
    }

    /**
     * Get asset dependents (assets that depend on this one)
     * 获取资产的依赖者（依赖此资产的其他资产）
     */
    getDependents(guid: AssetGUID): AssetGUID[] {
        const deps = this._dependents.get(guid);
        return deps ? Array.from(deps) : [];
    }

    /**
     * Get all dependencies recursively
     * 递归获取所有依赖
     */
    getAllDependencies(guid: AssetGUID, visited = new Set<AssetGUID>()): AssetGUID[] {
        if (visited.has(guid)) return [];
        visited.add(guid);

        const result: AssetGUID[] = [];
        const directDeps = this.getDependencies(guid);

        for (const dep of directDeps) {
            result.push(dep);
            const transitiveDeps = this.getAllDependencies(dep, visited);
            result.push(...transitiveDeps);
        }

        return result;
    }

    /**
     * Check for circular dependencies
     * 检查循环依赖
     */
    hasCircularDependency(guid: AssetGUID): boolean {
        const visited = new Set<AssetGUID>();
        const recursionStack = new Set<AssetGUID>();

        const checkCycle = (current: AssetGUID): boolean => {
            visited.add(current);
            recursionStack.add(current);

            const deps = this.getDependencies(current);
            for (const dep of deps) {
                if (!visited.has(dep)) {
                    if (checkCycle(dep)) return true;
                } else if (recursionStack.has(dep)) {
                    return true;
                }
            }

            recursionStack.delete(current);
            return false;
        };

        return checkCycle(guid);
    }

    /**
     * Update dependencies
     * 更新依赖关系
     */
    private updateDependencies(guid: AssetGUID, newDependencies: AssetGUID[]): void {
        // 清除旧的依赖关系 / Clear old dependencies
        this.clearDependencies(guid);

        // 建立新的依赖关系 / Establish new dependencies
        if (newDependencies.length > 0) {
            this._dependencies.set(guid, new Set(newDependencies));

            // 更新被依赖关系 / Update dependent relations
            newDependencies.forEach((dep) => {
                if (!this._dependents.has(dep)) {
                    this._dependents.set(dep, new Set());
                }
                this._dependents.get(dep)!.add(guid);
            });
        }
    }

    /**
     * Clear dependencies
     * 清除依赖关系
     */
    private clearDependencies(guid: AssetGUID): void {
        // 清除依赖 / Clear dependencies
        const deps = this._dependencies.get(guid);
        if (deps) {
            deps.forEach((dep) => {
                const dependents = this._dependents.get(dep);
                if (dependents) {
                    dependents.delete(guid);
                    if (dependents.size === 0) {
                        this._dependents.delete(dep);
                    }
                }
            });
            this._dependencies.delete(guid);
        }

        // 清除被依赖 / Clear dependents
        const dependents = this._dependents.get(guid);
        if (dependents) {
            dependents.forEach((dependent) => {
                const dependencies = this._dependencies.get(dependent);
                if (dependencies) {
                    dependencies.delete(guid);
                    if (dependencies.size === 0) {
                        this._dependencies.delete(dependent);
                    }
                }
            });
            this._dependents.delete(guid);
        }
    }

    /**
     * Get database statistics
     * 获取数据库统计
     */
    getStatistics(): {
        totalAssets: number;
        assetsByType: Map<AssetType, number>;
        totalDependencies: number;
        assetsWithDependencies: number;
        circularDependencies: number;
        } {
        const assetsByType = new Map<AssetType, number>();
        this._typeToGuids.forEach((guids, type) => {
            assetsByType.set(type, guids.size);
        });

        let circularDependencies = 0;
        this._metadata.forEach((_, guid) => {
            if (this.hasCircularDependency(guid)) {
                circularDependencies++;
            }
        });

        return {
            totalAssets: this._metadata.size,
            assetsByType,
            totalDependencies: Array.from(this._dependencies.values()).reduce(
                (sum, deps) => sum + deps.size,
                0
            ),
            assetsWithDependencies: this._dependencies.size,
            circularDependencies
        };
    }

    /**
     * Export to catalog entries
     * 导出为目录条目
     */
    exportToCatalog(): IAssetCatalogEntry[] {
        const entries: IAssetCatalogEntry[] = [];

        this._metadata.forEach((metadata) => {
            entries.push({
                guid: metadata.guid,
                path: metadata.path,
                type: metadata.type,
                size: metadata.size,
                hash: metadata.hash
            });
        });

        return entries;
    }

    /**
     * Clear database
     * 清空数据库
     */
    clear(): void {
        this._metadata.clear();
        this._pathToGuid.clear();
        this._typeToGuids.clear();
        this._labelToGuids.clear();
        this._dependencies.clear();
        this._dependents.clear();
    }
}
