package handlers

import (
	"net/http"

	"github.com/go-chi/chi/v5"
	"github.com/google/uuid"

	"{{GO_MODULE}}/pkg/app"
	"{{GO_MODULE}}/pkg/httperror"
	"{{GO_MODULE}}/pkg/httpresponse"
	"{{GO_MODULE}}/pkg/logging"
)

// Example demonstrates the Wrap pattern for error-returning handlers.
type Example struct {
	logger *logging.Logger
}

// NewExample creates a new Example handler.
func NewExample(logger *logging.Logger) *Example {
	return &Example{logger: logger}
}

// CreateRequest is the request body for creating an example.
type CreateRequest struct {
	Name        string `json:"name" validate:"required,min=1,max=100"`
	Description string `json:"description" validate:"max=500"`
}

// UpdateRequest is the request body for updating an example.
type UpdateRequest struct {
	Name        string `json:"name" validate:"omitempty,min=1,max=100"`
	Description string `json:"description" validate:"max=500"`
}

// ExampleResponse is the response for an example resource.
type ExampleResponse struct {
	ID          string `json:"id"`
	Name        string `json:"name"`
	Description string `json:"description"`
	CreatedAt   string `json:"created_at"`
	UpdatedAt   string `json:"updated_at"`
}

// List returns a paginated list of examples.
// Demonstrates pagination query params and list responses.
func (h *Example) List(w http.ResponseWriter, r *http.Request) error {
	// Example: Parse pagination query params
	// page := r.URL.Query().Get("page")
	// perPage := r.URL.Query().Get("per_page")

	// Example: Fetch from database
	// items, total, err := h.repo.List(r.Context(), page, perPage)
	// if err != nil {
	//     return err
	// }

	// Placeholder response
	items := []ExampleResponse{
		{
			ID:          "550e8400-e29b-41d4-a716-446655440000",
			Name:        "Example Item 1",
			Description: "First example item",
			CreatedAt:   "2024-01-15T10:30:00Z",
			UpdatedAt:   "2024-01-15T10:30:00Z",
		},
		{
			ID:          "550e8400-e29b-41d4-a716-446655440001",
			Name:        "Example Item 2",
			Description: "Second example item",
			CreatedAt:   "2024-01-16T12:00:00Z",
			UpdatedAt:   "2024-01-16T12:00:00Z",
		},
	}

	httpresponse.OK(w, r, items)
	return nil
}

// Get returns an example by ID.
// Demonstrates returning HTTPErrors for common error cases.
func (h *Example) Get(w http.ResponseWriter, r *http.Request) error {
	id := chi.URLParam(r, "id")

	// Validate UUID format
	if _, err := uuid.Parse(id); err != nil {
		return httperror.BadRequest("invalid id format")
	}

	// Example: Fetch from database
	// item, err := h.repo.Get(r.Context(), id)
	// if err != nil {
	//     if errors.Is(err, ErrNotFound) {
	//         return httperror.NotFoundf("example %s not found", id)
	//     }
	//     return err
	// }

	// Placeholder response
	httpresponse.OK(w, r, ExampleResponse{
		ID:          id,
		Name:        "Example Item",
		Description: "This is an example item",
		CreatedAt:   "2024-01-15T10:30:00Z",
		UpdatedAt:   "2024-01-15T10:30:00Z",
	})
	return nil
}

// Create creates a new example.
// Demonstrates using BindAndValidate for request parsing and validation.
func (h *Example) Create(w http.ResponseWriter, r *http.Request) error {
	var req CreateRequest

	// Bind and validate request body
	if err := app.BindAndValidate(r, &req); err != nil {
		return err
	}

	// Example: Check for duplicates
	// if exists, _ := h.repo.GetByName(r.Context(), req.Name); exists != nil {
	//     return httperror.Conflict("example with this name already exists")
	// }

	// Example: Create in database
	// item, err := h.repo.Create(r.Context(), req)
	// if err != nil {
	//     return err
	// }

	// Example: Access authenticated user
	// user := auth.GetUser(r.Context())
	// h.logger.Info("example created", "by", user.ID, "name", req.Name)

	id := uuid.New().String()

	httpresponse.Created(w, r, ExampleResponse{
		ID:          id,
		Name:        req.Name,
		Description: req.Description,
		CreatedAt:   "2024-01-15T10:30:00Z",
		UpdatedAt:   "2024-01-15T10:30:00Z",
	})
	return nil
}

// Update updates an existing example.
// Demonstrates partial updates with BindAndValidate.
func (h *Example) Update(w http.ResponseWriter, r *http.Request) error {
	id := chi.URLParam(r, "id")

	if _, err := uuid.Parse(id); err != nil {
		return httperror.BadRequest("invalid id format")
	}

	var req UpdateRequest
	if err := app.BindAndValidate(r, &req); err != nil {
		return err
	}

	// Example: Fetch existing, apply updates, save
	// item, err := h.repo.Get(r.Context(), id)
	// if err != nil {
	//     if errors.Is(err, ErrNotFound) {
	//         return httperror.NotFoundf("example %s not found", id)
	//     }
	//     return err
	// }
	// if err := h.repo.Update(r.Context(), id, req); err != nil {
	//     return err
	// }

	httpresponse.OK(w, r, ExampleResponse{
		ID:          id,
		Name:        req.Name,
		Description: req.Description,
		CreatedAt:   "2024-01-15T10:30:00Z",
		UpdatedAt:   "2024-01-16T14:00:00Z",
	})
	return nil
}

// Delete deletes an example by ID.
// Demonstrates no-content response.
func (h *Example) Delete(w http.ResponseWriter, r *http.Request) error {
	id := chi.URLParam(r, "id")

	if _, err := uuid.Parse(id); err != nil {
		return httperror.BadRequest("invalid id format")
	}

	// Example: Delete from database
	// if err := h.repo.Delete(r.Context(), id); err != nil {
	//     if errors.Is(err, ErrNotFound) {
	//         return httperror.NotFoundf("example %s not found", id)
	//     }
	//     return err
	// }

	httpresponse.NoContent(w)
	return nil
}
