package errors

import (
	stderrors "errors"
	"fmt"
	"net/http"
)

// AppError 结构化应用错误
type AppError struct {
	Code       string                 `json:"code"`
	Message    string                 `json:"message"`
	HTTPStatus int                    `json:"-"`
	Cause      error                  `json:"-"`
	Context    map[string]interface{} `json:"-"`
}

// Error implements error interface
func (e *AppError) Error() string {
	if e.Cause != nil {
		return fmt.Sprintf("%s: %s (%v)", e.Code, e.Message, e.Cause)
	}
	return fmt.Sprintf("%s: %s", e.Code, e.Message)
}

// Unwrap returns the underlying error
func (e *AppError) Unwrap() error {
	return e.Cause
}

// WithCause returns a copy of the error with the given cause
func (e *AppError) WithCause(cause error) *AppError {
	return &AppError{
		Code:       e.Code,
		Message:    e.Message,
		HTTPStatus: e.HTTPStatus,
		Cause:      cause,
		Context:    e.Context,
	}
}

// NewAppError creates a new AppError
func NewAppError(code, message string, httpStatus int) *AppError {
	return &AppError{
		Code:       code,
		Message:    message,
		HTTPStatus: httpStatus,
	}
}

// Predefined errors
var (
	ErrModelNotFound     = NewAppError("model_not_found", "模型未找到", http.StatusNotFound)
	ErrModelDisabled     = NewAppError("model_disabled", "模型已禁用", http.StatusNotFound)
	ErrProviderNotFound  = NewAppError("provider_not_found", "供应商未找到", http.StatusNotFound)
	ErrProviderDisabled  = NewAppError("provider_disabled", "供应商已禁用", http.StatusNotFound)
	ErrInvalidRequest    = NewAppError("invalid_request", "无效的请求", http.StatusBadRequest)
	ErrInternal          = NewAppError("internal_error", "内部错误", http.StatusInternalServerError)
	ErrDatabaseNotInit   = NewAppError("database_not_initialized", "数据库未初始化", http.StatusInternalServerError)
	ErrConflict          = NewAppError("conflict", "资源已存在", http.StatusConflict)
	ErrRequestCreate     = NewAppError("request_create_error", "创建请求失败", http.StatusInternalServerError)
	ErrRequestSend       = NewAppError("request_send_error", "发送请求失败", http.StatusBadGateway)
	ErrResponseRead      = NewAppError("response_read_error", "读取响应失败", http.StatusBadGateway)
	ErrInvalidProviderID = NewAppError("invalid_provider_id", "供应商 ID 仅允许字母、数字、下划线，长度 1-64", http.StatusBadRequest)
	ErrDuplicateModel    = NewAppError("duplicate_model", "同一供应商下模型名称已存在", http.StatusConflict)
	ErrImmutableField    = NewAppError("immutable_field", "供应商 ID 不允许修改", http.StatusBadRequest)
)

// AsAppError 尝试将 error 转换为 *AppError
func AsAppError(err error) (*AppError, bool) {
	if err == nil {
		return nil, false
	}

	var appErr *AppError
	if !stderrors.As(err, &appErr) {
		return nil, false
	}

	return appErr, true
}
