package apperrors

import (
	"fmt"
	"net/http"
)

// AppError represents an application error with HTTP status and i18n key
type AppError struct {
	Code       int    // HTTP status code
	Message    string // Default message (fallback if i18n key not found)
	MessageKey string // i18n key for localization
	Err        error  // Wrapped error (for internal errors)
}

func (e *AppError) Error() string {
	if e.Err != nil {
		return fmt.Sprintf("%s: %v", e.Message, e.Err)
	}
	if e.Message != "" {
		return e.Message
	}
	return e.MessageKey
}

func (e *AppError) Unwrap() error {
	return e.Err
}

// NotFound creates a 404 Not Found error
func NotFound(messageKey string) *AppError {
	return &AppError{
		Code:       http.StatusNotFound,
		MessageKey: messageKey,
	}
}

// Forbidden creates a 403 Forbidden error
func Forbidden(messageKey string) *AppError {
	return &AppError{
		Code:       http.StatusForbidden,
		MessageKey: messageKey,
	}
}

// BadRequest creates a 400 Bad Request error
func BadRequest(messageKey string) *AppError {
	return &AppError{
		Code:       http.StatusBadRequest,
		MessageKey: messageKey,
	}
}

// Unauthorized creates a 401 Unauthorized error
func Unauthorized(messageKey string) *AppError {
	return &AppError{
		Code:       http.StatusUnauthorized,
		MessageKey: messageKey,
	}
}

// Conflict creates a 409 Conflict error
func Conflict(messageKey string) *AppError {
	return &AppError{
		Code:       http.StatusConflict,
		MessageKey: messageKey,
	}
}

// TooManyRequests creates a 429 Too Many Requests error
func TooManyRequests(messageKey string) *AppError {
	return &AppError{
		Code:       http.StatusTooManyRequests,
		MessageKey: messageKey,
	}
}

// Internal creates a 500 Internal Server Error, wrapping the original error
func Internal(err error) *AppError {
	return &AppError{
		Code:       http.StatusInternalServerError,
		MessageKey: "error.internal",
		Err:        err,
	}
}

// WithMessage adds a default message to the error (used when i18n key not found)
func (e *AppError) WithMessage(msg string) *AppError {
	e.Message = msg
	return e
}

// Wrap wraps an underlying error
func (e *AppError) Wrap(err error) *AppError {
	e.Err = err
	return e
}
