package filesystem

import (
	"strings"
)

// FileTypeManager 文件类型管理器接口
// 统一管理文件类型相关的所有操作
type FileTypeManager interface {
	// GetMIMEType 获取文件的MIME类型
	GetMIMEType(ext string) string

	// IsAllowed 检查文件类型是否允许访问
	IsAllowed(ext string) bool

	// GetMaxSize 获取指定文件类型的最大允许大小（字节）
	GetMaxSize(ext string) int64

	// GetFileInfo 获取文件类型信息
	GetFileInfo(ext string) *FileInfo
}

// FileInfo 文件类型信息
type FileInfo struct {
	Extension  string
	MIMEType   string
	Allowed    bool
	MaxSize    int64
	Category   string // image, video, audio, document, text, etc.
}

// DefaultFileTypeManager 默认文件类型管理器实现
type DefaultFileTypeManager struct {
	config *Config
}

// NewFileTypeManager 创建新的文件类型管理器
func NewFileTypeManager(config *Config) FileTypeManager {
	return &DefaultFileTypeManager{
		config: config,
	}
}

// GetMIMEType 获取文件的MIME类型
func (m *DefaultFileTypeManager) GetMIMEType(ext string) string {
	// 标准化扩展名（小写，以点开头）
	normalizedExt := normalizeExtension(ext)

	// 查找MIME类型
	if mimeType, ok := m.config.Security.FileTypes.MIMETypeMapping[normalizedExt]; ok {
		return mimeType
	}

	// 默认MIME类型
	return "application/octet-stream"
}

// IsAllowed 检查文件类型是否允许访问
func (m *DefaultFileTypeManager) IsAllowed(ext string) bool {
	// 标准化扩展名
	normalizedExt := normalizeExtension(ext)

	// 优先检查黑名单
	if m.config.Security.FileTypes.ForbiddenExtensions != nil {
		if forbidden, ok := m.config.Security.FileTypes.ForbiddenExtensions[normalizedExt]; ok && forbidden {
			return false
		}
	}

	// 检查白名单
	if m.config.Security.FileTypes.AllowedExtensions != nil {
		if allowed, ok := m.config.Security.FileTypes.AllowedExtensions[normalizedExt]; ok {
			return allowed
		}
	}

	// 如果没有配置白名单，默认允许
	return len(m.config.Security.FileTypes.AllowedExtensions) == 0
}

// GetMaxSize 获取指定文件类型的最大允许大小
func (m *DefaultFileTypeManager) GetMaxSize(ext string) int64 {
	// 标准化扩展名
	normalizedExt := normalizeExtension(ext)

	// 查找特定类型的大小限制
	if maxSize, ok := m.config.Security.FileTypes.MaxFileSizeMap[normalizedExt]; ok {
		return maxSize
	}

	// 返回默认大小限制（0=不限制）
	return 0
}

// GetFileInfo 获取文件类型信息
func (m *DefaultFileTypeManager) GetFileInfo(ext string) *FileInfo {
	// 标准化扩展名
	normalizedExt := normalizeExtension(ext)

	return &FileInfo{
		Extension: normalizedExt,
		MIMEType:  m.GetMIMEType(normalizedExt),
		Allowed:   m.IsAllowed(normalizedExt),
		MaxSize:   m.GetMaxSize(normalizedExt),
		Category:  m.getCategory(normalizedExt),
	}
}

// getCategory 获取文件类型分类
func (m *DefaultFileTypeManager) getCategory(ext string) string {
	// 根据MIME类型判断
	mimeType := m.GetMIMEType(ext)

	if strings.HasPrefix(mimeType, "image/") {
		return FileTypeImage
	}
	if strings.HasPrefix(mimeType, "video/") {
		return FileTypeVideo
	}
	if strings.HasPrefix(mimeType, "audio/") {
		return FileTypeAudio
	}
	if mimeType == "application/pdf" {
		return FileTypeDocument
	}
	if strings.HasPrefix(mimeType, "text/") {
		return FileTypeText
	}

	return FileTypeApplication
}

// normalizeExtension 标准化文件扩展名
// 确保扩展名以点开头且为小写
func normalizeExtension(ext string) string {
	// 去除空格
	ext = strings.TrimSpace(ext)

	// 转小写
	ext = strings.ToLower(ext)

	// 确保以点开头
	if !strings.HasPrefix(ext, ".") {
		ext = "." + ext
	}

	return ext
}

// 默认文件类型管理器实例（用于兼容函数）
var defaultFileTypeManager = NewFileTypeManager(DefaultConfig())
