package user

import (
	"system-altrak/internal/domain"
	"system-altrak/internal/dto"
	"system-altrak/internal/middleware"
	"system-altrak/pkg/utils"

	"github.com/gofiber/fiber/v2"
)

type Handler struct {
	service UserService
}

func NewHandler(s UserService) *Handler {
	return &Handler{service: s}
}

func (h *Handler) List(c *fiber.Ctx) error {
	users, err := h.service.List()
	if err != nil {
		return utils.InternalErrorResponse(c, "Failed to aggregate authorized personnel registry")
	}
	return utils.SuccessResponse(c, "Success", users)
}

func (h *Handler) Create(c *fiber.Ctx) error {
	var req dto.UserCreateRequest
	if err := c.BodyParser(&req); err != nil {
		return utils.ErrorResponse(c, fiber.StatusBadRequest, "Invalid JSON data structure format")
	}

	middleware.SanitizeStruct(&req)

	// Use new detailed validation
	result := utils.ValidateStructDetailed(req)
	if !result.IsValid {
		return utils.ValidationErrorResponse(c, "Validation failed", result.Errors)
	}

	user := domain.User{
		FullName:     req.FullName,
		Username:     req.Username,
		PasswordHash: req.Password, // Service will hash it
		Role:         req.Role,
		IsActive:     true,
		BranchID:     req.BranchID,
	}
	if user.BranchID == 0 {
		if currentBranchID, ok := c.Locals("branch_id").(uint); ok && currentBranchID > 0 {
			user.BranchID = currentBranchID
		} else {
			user.BranchID = 1
		}
	}

	if err := h.service.Create(&user, c.IP(), c.Get("User-Agent")); err != nil {
		return utils.InternalErrorResponse(c, err.Error())
	}

	user.PasswordHash = ""
	return utils.SuccessResponse(c, "Personnel credentials successfully initialized", user)
}

func (h *Handler) Update(c *fiber.Ctx) error {
	id, err := utils.ParseParamID(c, "id")
	if err != nil {
		return utils.ErrorResponse(c, fiber.StatusBadRequest, "Invalid ID parameter")
	}
	var req dto.UserUpdateRequest
	if err := c.BodyParser(&req); err != nil {
		return utils.ErrorResponse(c, fiber.StatusBadRequest, "Invalid JSON data structure format")
	}

	middleware.SanitizeStruct(&req)

	// Use new detailed validation
	result := utils.ValidateStructDetailed(req)
	if !result.IsValid {
		return utils.ValidationErrorResponse(c, "Validation failed", result.Errors)
	}

	user := domain.User{
		BaseModel: domain.BaseModel{ID: id},
		FullName:  req.FullName,
		Username:  req.Username,
		Role:      req.Role,
		BranchID:  req.BranchID,
	}
	if user.BranchID == 0 {
		if currentBranchID, ok := c.Locals("branch_id").(uint); ok && currentBranchID > 0 {
			user.BranchID = currentBranchID
		}
	}

	user.PasswordHash = req.Password

	if err := h.service.Update(&user, c.IP(), c.Get("User-Agent")); err != nil {
		return utils.InternalErrorResponse(c, err.Error())
	}

	return utils.SuccessResponse(c, "Personnel profile successfully updated in matrix", nil)
}

func (h *Handler) Delete(c *fiber.Ctx) error {
	id, err := utils.ParseParamID(c, "id")
	if err != nil {
		return utils.ErrorResponse(c, fiber.StatusBadRequest, "Invalid ID parameter")
	}

	actorID, _ := c.Locals("user_id").(uint)
	if actorID == id {
		return utils.ErrorResponse(c, fiber.StatusForbidden, "Akun aktif tidak dapat menghapus dirinya sendiri")
	}

	if err := h.service.Delete(id, actorID, c.IP(), c.Get("User-Agent")); err != nil {
		return utils.InternalErrorResponse(c, err.Error())
	}

	return utils.SuccessResponse(c, "Personnel profile removed from authorization matrix", nil)
}
