package errors

import (
	"encoding/json"
	"fmt"
	"net/http"
	"os"

	chimiddleware "github.com/go-chi/chi/v5/middleware"
	"github.com/google/uuid"
)

// ErrorCode represents standardized error codes
type ErrorCode string

const (
	CodeUnauthenticated  ErrorCode = "UNAUTHENTICATED"
	CodePermissionDenied ErrorCode = "PERMISSION_DENIED"
	CodeNotFound         ErrorCode = "NOT_FOUND"
	CodeConflict         ErrorCode = "CONFLICT"
	CodeInvalidArgument  ErrorCode = "INVALID_ARGUMENT"
	CodeInternal         ErrorCode = "INTERNAL"
)

// ErrorResponse represents the JSON error response structure
type ErrorResponse struct {
	Code    ErrorCode `json:"code"`
	Message string    `json:"message"`
}

// WriteError writes a standardized JSON error response
func WriteError(w http.ResponseWriter, code ErrorCode, message string, status int) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(status)
	json.NewEncoder(w).Encode(ErrorResponse{
		Code:    code,
		Message: message,
	})
}

// GetRequestID extracts the request ID from the request context
func GetRequestID(r *http.Request) string {
	if reqID := chimiddleware.GetReqID(r.Context()); reqID != "" {
		return reqID
	}
	return "unknown"
}

// GetUserID extracts user ID from context if available
func GetUserID(r *http.Request) string {
	// Use type contextKey matching middleware package
	type contextKey string
	if userID, ok := r.Context().Value(contextKey("user")).(string); ok && userID != "" {
		return userID
	}
	return ""
}

// GetOrgID extracts org ID from context if available
func GetOrgID(r *http.Request) string {
	if orgID := r.Context().Value("org"); orgID != nil {
		if oid, ok := orgID.(uuid.UUID); ok {
			return oid.String()
		}
	}
	return ""
}

// LogError logs an error with context
func LogError(r *http.Request, err error, message string) {
	fmt.Fprintf(os.Stderr, "[ERROR] req_id=%s user_id=%s org_id=%s %s: %v\n",
		GetRequestID(r), GetUserID(r), GetOrgID(r), message, err)
}
