/**
 * @Author: FTS Team
 * @Date: 2024-10-02
 * @Description: 错误处理定义
 */
package errors

import (
	"fmt"
	"net/http"
)

// 业务错误码定义
const (
	// 通用错误码
	ErrCodeInternalError   = 10001 // 内部错误
	ErrCodeInvalidParam    = 10002 // 参数错误
	ErrCodeNotFound        = 10003 // 资源不存在
	ErrCodeUnauthorized    = 10004 // 未授权
	ErrCodeForbidden       = 10005 // 权限不足
	ErrCodeTooManyRequests = 10006 // 请求过于频繁

	// 文件相关错误码
	ErrCodeFileNotFound     = 20001 // 文件不存在
	ErrCodeFileTooLarge     = 20002 // 文件过大
	ErrCodeFileTypeNotAllow = 20003 // 文件类型不允许
	ErrCodeUploadFailed     = 20004 // 上传失败
	ErrCodeDownloadFailed   = 20005 // 下载失败

	// 存储相关错误码
	ErrCodeOSSConnectionFailed = 30001 // OSS连接失败
	ErrCodeOSSUploadFailed     = 30002 // OSS上传失败
	ErrCodeOSSDeleteFailed     = 30003 // OSS删除失败
	ErrCodeLocalStorageFailed  = 30004 // 本地存储失败

	// 数据库相关错误码
	ErrCodeDBConnectionFailed = 40001 // 数据库连接失败
	ErrCodeDBQueryFailed      = 40002 // 数据库查询失败
	ErrCodeDBInsertFailed     = 40003 // 数据库插入失败
	ErrCodeDBUpdateFailed     = 40004 // 数据库更新失败
	ErrCodeDBDeleteFailed     = 40005 // 数据库删除失败
)

// BusinessError 业务错误
type BusinessError struct {
	Code    int    `json:"code"`
	Message string `json:"message"`
	Detail  string `json:"detail,omitempty"`
}

func (e *BusinessError) Error() string {
	if e.Detail != "" {
		return fmt.Sprintf("业务错误[%d]: %s (%s)", e.Code, e.Message, e.Detail)
	}
	return fmt.Sprintf("业务错误[%d]: %s", e.Code, e.Message)
}

// HTTPStatus 返回对应的HTTP状态码
func (e *BusinessError) HTTPStatus() int {
	switch e.Code {
	case ErrCodeNotFound, ErrCodeFileNotFound:
		return http.StatusNotFound
	case ErrCodeUnauthorized:
		return http.StatusUnauthorized
	case ErrCodeForbidden:
		return http.StatusForbidden
	case ErrCodeInvalidParam, ErrCodeFileTooLarge, ErrCodeFileTypeNotAllow:
		return http.StatusBadRequest
	case ErrCodeTooManyRequests:
		return http.StatusTooManyRequests
	default:
		return http.StatusInternalServerError
	}
}

// New 创建新的业务错误
func New(code int, message string) *BusinessError {
	return &BusinessError{
		Code:    code,
		Message: message,
	}
}

// NewWithDetail 创建带详细信息的业务错误
func NewWithDetail(code int, message, detail string) *BusinessError {
	return &BusinessError{
		Code:    code,
		Message: message,
		Detail:  detail,
	}
}

// 预定义常用错误
var (
	ErrInternalError   = New(ErrCodeInternalError, "内部服务器错误")
	ErrInvalidParam    = New(ErrCodeInvalidParam, "参数错误")
	ErrNotFound        = New(ErrCodeNotFound, "资源不存在")
	ErrUnauthorized    = New(ErrCodeUnauthorized, "未授权访问")
	ErrForbidden       = New(ErrCodeForbidden, "权限不足")
	ErrTooManyRequests = New(ErrCodeTooManyRequests, "请求过于频繁")

	ErrFileNotFound     = New(ErrCodeFileNotFound, "文件不存在")
	ErrFileTooLarge     = New(ErrCodeFileTooLarge, "文件大小超出限制")
	ErrFileTypeNotAllow = New(ErrCodeFileTypeNotAllow, "文件类型不允许")
	ErrUploadFailed     = New(ErrCodeUploadFailed, "文件上传失败")
	ErrDownloadFailed   = New(ErrCodeDownloadFailed, "文件下载失败")

	ErrOSSConnectionFailed = New(ErrCodeOSSConnectionFailed, "OSS连接失败")
	ErrOSSUploadFailed     = New(ErrCodeOSSUploadFailed, "OSS上传失败")
	ErrOSSDeleteFailed     = New(ErrCodeOSSDeleteFailed, "OSS删除失败")
	ErrLocalStorageFailed  = New(ErrCodeLocalStorageFailed, "本地存储失败")

	ErrDBConnectionFailed = New(ErrCodeDBConnectionFailed, "数据库连接失败")
	ErrDBQueryFailed      = New(ErrCodeDBQueryFailed, "数据库查询失败")
	ErrDBInsertFailed     = New(ErrCodeDBInsertFailed, "数据库插入失败")
	ErrDBUpdateFailed     = New(ErrCodeDBUpdateFailed, "数据库更新失败")
	ErrDBDeleteFailed     = New(ErrCodeDBDeleteFailed, "数据库删除失败")
)
