import { StorageManager } from '../core/adapter';
import { StorageType } from '../types';
import path from 'path';

/**
 * 存储工具类 - 处理不同存储类型的文件操作
 */
export class StorageUtils {
	private static instance: StorageUtils;
	private storageManager: StorageManager;

	private constructor() {
		this.storageManager = StorageManager.getInstance();
	}

	public static getInstance(): StorageUtils {
		if (!StorageUtils.instance) {
			StorageUtils.instance = new StorageUtils();
		}
		return StorageUtils.instance;
	}

	/**
	 * 生成文件访问URL（统一使用下载接口）
	 * @param fileId 文件ID
	 * @param baseUrl 基础URL（可选，用于生成完整URL）
	 * @returns 文件访问URL
	 */
	public generateFileUrl(fileId: string, baseUrl?: string): string {
		const base = baseUrl || 'http://localhost:3000';
		return `${base}/download/${fileId}`;
	}

	/**
	 * 生成文件下载URL（与 generateFileUrl 相同，保持兼容性）
	 * @param fileId 文件ID
	 * @param baseUrl 基础URL（可选，用于生成完整URL）
	 * @returns 文件下载URL
	 */
	public generateDownloadUrl(fileId: string, baseUrl?: string): string {
		return this.generateFileUrl(fileId, baseUrl);
	}

	/**
	 * 生成直接访问URL（仅用于S3存储）
	 * @param fileId 文件ID
	 * @returns S3直接访问URL
	 */
	public generateDirectUrl(fileId: string): string {
		const storageType = this.storageManager.getStorageType();
		const config = this.storageManager.getStorageConfig();

		if (storageType !== StorageType.S3) {
			throw new Error('Direct URL is only available for S3 storage');
		}

		const s3Config = config.s3!;
		if (s3Config.endpoint && s3Config.endpoint !== 'https://s3.amazonaws.com') {
			// 自定义 S3 兼容服务
			return `${s3Config.endpoint}/${s3Config.bucket}/${fileId}`;
		}
		// AWS S3
		return `https://${s3Config.bucket}.s3.${s3Config.region}.amazonaws.com/${fileId}`;
	}

	/**
	 * 生成预签名URL（仅支持S3）
	 * @param fileId 文件ID
	 * @param expiresIn 过期时间（秒）
	 * @returns 预签名URL
	 */
	public async generatePresignedUrl(fileId: string, expiresIn: number = 3600): Promise<string> {
		const storageType = this.storageManager.getStorageType();

		if (storageType !== StorageType.S3) {
			throw new Error('Presigned URLs are only supported for S3 storage');
		}

		// TODO: 实现 S3 预签名 URL 生成
		// 这需要使用 AWS SDK 的 getSignedUrl 方法
		// const s3Client = this.storageManager.getS3Client();
		// return await getSignedUrl(s3Client, new GetObjectCommand({
		//   Bucket: config.s3!.bucket,
		//   Key: fileId
		// }), { expiresIn });

		throw new Error('Presigned URL generation not implemented yet');
	}

	/**
	 * 获取文件物理路径（仅本地存储）
	 * @param fileId 文件ID
	 * @returns 文件物理路径
	 */
	public getFilePath(fileId: string): string {
		const storageType = this.storageManager.getStorageType();

		if (storageType !== StorageType.LOCAL) {
			throw new Error('File path is only available for local storage');
		}

		const config = this.storageManager.getStorageConfig();
		return path.join(config.local?.directory || './uploads', fileId);
	}

	/**
	 * 检查文件是否存在
	 * @param fileId 文件ID
	 * @returns 是否存在
	 */
	public async fileExists(fileId: string): Promise<boolean> {
		const storageType = this.storageManager.getStorageType();
		const dataStore = this.storageManager.getDataStore();

		try {
			await dataStore.getUpload(fileId);
			return true;
		} catch (error) {
			return false;
		}
	}

	/**
	 * 删除文件
	 * @param fileId 文件ID
	 */
	public async deleteFile(fileId: string): Promise<void> {
		const dataStore = this.storageManager.getDataStore();
		await dataStore.remove(fileId);
	}

	/**
	 * 获取文件流（用于下载）
	 * @param fileId 文件ID
	 * @returns 文件流
	 */
	public async getFileStream(fileId: string): Promise<ReadableStream | NodeJS.ReadableStream> {
		const storageType = this.storageManager.getStorageType();
		const dataStore = this.storageManager.getDataStore();

		if (storageType === StorageType.LOCAL) {
			// 本地存储直接返回文件流
			return (dataStore as any).read(fileId);
		} else if (storageType === StorageType.S3) {
			// S3 存储返回对象流
			return (dataStore as any).read(fileId);
		}

		throw new Error(`File stream not supported for storage type: ${storageType}`);
	}

	/**
	 * 复制文件到另一个位置
	 * @param sourceFileId 源文件ID
	 * @param targetFileId 目标文件ID
	 */
	public async copyFile(sourceFileId: string, targetFileId: string): Promise<void> {
		const storageType = this.storageManager.getStorageType();

		if (storageType === StorageType.LOCAL) {
			// 本地存储使用文件系统复制
			const fs = await import('fs/promises');
			const sourcePath = this.getFilePath(sourceFileId);
			const targetPath = this.getFilePath(targetFileId);
			await fs.copyFile(sourcePath, targetPath);
		} else if (storageType === StorageType.S3) {
			// S3 存储使用对象复制
			// TODO: 实现 S3 对象复制
			throw new Error('S3 file copy not implemented yet');
		}
	}

	/**
	 * 获取存储统计信息
	 */
	public async getStorageStats(): Promise<{
		storageType: StorageType;
		totalFiles?: number;
		totalSize?: number;
		availableSpace?: number;
	}> {
		const storageType = this.storageManager.getStorageType();
		const config = this.storageManager.getStorageConfig();

		const stats = {
			storageType,
			totalFiles: undefined as number | undefined,
			totalSize: undefined as number | undefined,
			availableSpace: undefined as number | undefined,
		};

		if (storageType === StorageType.LOCAL) {
			// 本地存储可以计算磁盘使用情况
			try {
				const fs = await import('fs/promises');
				const path = await import('path');
				const uploadDir = config.local?.directory || './uploads';

				// 计算文件总数和大小（这里简化实现）
				// 实际应用中可能需要递归遍历目录
				const stat = await fs.stat(uploadDir).catch(() => null);
				if (stat) {
					// TODO: 实现详细的目录统计
				}
			} catch (error) {
				console.error('Failed to get local storage stats:', error);
			}
		}

		return stats;
	}

	/**
	 * 清理过期文件
	 */
	public async cleanupExpiredFiles(): Promise<{ deletedCount: number }> {
		const storageType = this.storageManager.getStorageType();
		const config = this.storageManager.getStorageConfig();
		let deletedCount = 0;

		// 获取过期时间配置
		const expirationMs =
			storageType === StorageType.LOCAL
				? config.local?.expirationPeriodInMilliseconds
				: config.s3?.expirationPeriodInMilliseconds;

		if (!expirationMs || expirationMs <= 0) {
			// 没有配置过期时间，不执行清理
			return { deletedCount: 0 };
		}

		// TODO: 实现具体的清理逻辑
		// 这里需要根据存储类型和数据库记录来清理过期文件

		return { deletedCount };
	}
}
