package response

import (
	"net/http"
	"strconv"

	"github.com/asaskevich/govalidator"
	"github.com/labstack/echo/v4"
)

// APIResponse represents a standard API response structure
type APIResponse struct {
	Success bool        `json:"success"`
	Message string      `json:"message,omitempty"`
	Data    interface{} `json:"data,omitempty"`
	Error   *APIError   `json:"error,omitempty"`
	Meta    *Meta       `json:"meta,omitempty"`
}

// APIError represents error details in API response
type APIError struct {
	Code    string `json:"code"`
	Message string `json:"message"`
	Details string `json:"details,omitempty"`
}

// Meta represents metadata for paginated responses
type Meta struct {
	Total  int `json:"total"`
	Limit  int `json:"limit"`
	Offset int `json:"offset"`
	Page   int `json:"page"`
	Pages  int `json:"pages"`
}

type Pagination struct {
	Limit     int    `query:"limit" valid:"optional,range(1|100)" default:"20"`
	Offset    int    `query:"offset" valid:"optional,min(0)" default:"0"`
	SortBy    string `query:"sort_by" valid:"optional"`
	SortOrder string `query:"sort_order" valid:"optional,in(asc|desc)"`
}

// Success returns a successful response
func Success(c echo.Context, data interface{}, message string) error {
	return c.JSON(http.StatusOK, APIResponse{
		Success: true,
		Message: message,
		Data:    data,
	})
}

// SuccessWithMeta returns a successful response with metadata
func SuccessWithMeta(c echo.Context, data interface{}, meta *Meta, message string) error {
	return c.JSON(http.StatusOK, APIResponse{
		Success: true,
		Message: message,
		Data:    data,
		Meta:    meta,
	})
}

// Created returns a 201 Created response
func Created(c echo.Context, data interface{}, message string) error {
	return c.JSON(http.StatusCreated, APIResponse{
		Success: true,
		Message: message,
		Data:    data,
	})
}

// BadRequest returns a 400 Bad Request response
func BadRequest(c echo.Context, message, details string) error {
	return c.JSON(http.StatusBadRequest, APIResponse{
		Success: false,
		Message: "Bad Request",
		Error: &APIError{
			Code:    "BAD_REQUEST",
			Message: message,
			Details: details,
		},
	})
}

// Unauthorized returns a 401 Unauthorized response
func Unauthorized(c echo.Context, message string) error {
	return c.JSON(http.StatusUnauthorized, APIResponse{
		Success: false,
		Message: "Unauthorized",
		Error: &APIError{
			Code:    "UNAUTHORIZED",
			Message: message,
		},
	})
}

// Forbidden returns a 403 Forbidden response
func Forbidden(c echo.Context, message string) error {
	return c.JSON(http.StatusForbidden, APIResponse{
		Success: false,
		Message: "Forbidden",
		Error: &APIError{
			Code:    "FORBIDDEN",
			Message: message,
		},
	})
}

// NotFound returns a 404 Not Found response
func NotFound(c echo.Context, message string) error {
	return c.JSON(http.StatusNotFound, APIResponse{
		Success: false,
		Message: "Not Found",
		Error: &APIError{
			Code:    "NOT_FOUND",
			Message: message,
		},
	})
}

// Conflict returns a 409 Conflict response
func Conflict(c echo.Context, message string) error {
	return c.JSON(http.StatusConflict, APIResponse{
		Success: false,
		Message: "Conflict",
		Error: &APIError{
			Code:    "CONFLICT",
			Message: message,
		},
	})
}

// ValidationError returns a 422 Unprocessable Entity response
func ValidationError(c echo.Context, message, details string) error {
	return c.JSON(http.StatusUnprocessableEntity, APIResponse{
		Success: false,
		Message: "Validation Error",
		Error: &APIError{
			Code:    "VALIDATION_ERROR",
			Message: message,
			Details: details,
		},
	})
}

// InternalServerError returns a 500 Internal Server Error response
func InternalServerError(c echo.Context, message string) error {
	return c.JSON(http.StatusInternalServerError, APIResponse{
		Success: false,
		Message: "Internal Server Error",
		Error: &APIError{
			Code:    "INTERNAL_SERVER_ERROR",
			Message: message,
		},
	})
}

// ServiceUnavailable returns a 503 Service Unavailable response
func ServiceUnavailable(c echo.Context, message string) error {
	return c.JSON(http.StatusServiceUnavailable, APIResponse{
		Success: false,
		Message: "Service Unavailable",
		Error: &APIError{
			Code:    "SERVICE_UNAVAILABLE",
			Message: message,
		},
	})
}

// Parse parses the form and validates it
func Parse[T any](c echo.Context) (*T, error) {
	var form T
	if err := c.Bind(&form); err != nil {
		return nil, err
	}

	if _, err := govalidator.ValidateStruct(form); err != nil {
		return nil, err
	}

	return &form, nil
}

func NewPagination(c echo.Context) *Pagination {
	limit, err := strconv.Atoi(c.QueryParam("limit"))
	if err != nil {
		limit = 20
	}

	offset, err := strconv.Atoi(c.QueryParam("offset"))
	if err != nil {
		offset = 0
	}

	return &Pagination{
		Limit:     limit,
		Offset:    offset,
		SortBy:    c.QueryParam("sort_by"),
		SortOrder: c.QueryParam("sort_order"),
	}
}

// Pagination calculates pagination metadata
func (p *Pagination) Response(total int64) *Meta {
	pages := (total + int64(p.Limit) - 1) / int64(p.Limit)
	return &Meta{
		Total:  int(total),
		Limit:  p.Limit,
		Offset: p.Offset,
		Page:   int(p.Offset/p.Limit) + 1,
		Pages:  int(pages),
	}
}
