package handler

import (
	"lune/talentscale/internal/domain"
	"lune/talentscale/internal/pkg/ctxval"
	"lune/talentscale/pkg/response"
	"strconv"

	"github.com/gofiber/fiber/v2"
	"github.com/google/uuid"
)

type RoleHandler struct {
	usecase domain.RoleUsecase
}

func NewRoleHandler(usecase domain.RoleUsecase) *RoleHandler {
	return &RoleHandler{usecase: usecase}
}

type RoleRequest struct {
	Name        string `json:"name"`
	Description string `json:"description"`
}

type SyncPermissionsRequest struct {
	PermissionIDs []uuid.UUID `json:"permission_ids"`
}

func getRoleCompanyIDPtr(c *fiber.Ctx) *uuid.UUID {
	id := ctxval.GetCompanyID(c)
	if id == uuid.Nil {
		return nil
	}
	return &id
}

func (h *RoleHandler) Create(c *fiber.Ctx) error {
	var req RoleRequest
	if err := c.BodyParser(&req); err != nil {
		return response.BadRequest(c, "Invalid request body")
	}

	companyID := getRoleCompanyIDPtr(c)

	role := &domain.Role{
		Name:        req.Name,
		Description: req.Description,
		CompanyID:   companyID,
	}

	if err := h.usecase.CreateRole(c.Context(), role); err != nil {
		return response.InternalError(c, err.Error())
	}
	return response.Created(c, "Role created successfully", role)
}

func (h *RoleHandler) GetByID(c *fiber.Ctx) error {
	id, err := uuid.Parse(c.Params("id"))
	if err != nil {
		return response.BadRequest(c, "Invalid role ID")
	}

	companyID := getRoleCompanyIDPtr(c)

	role, err := h.usecase.GetRoleByID(c.Context(), id, companyID)
	if err != nil {
		return response.NotFound(c, "Role not found")
	}
	return response.OK(c, "Success", role)
}

func (h *RoleHandler) List(c *fiber.Ctx) error {
	limit, _ := strconv.Atoi(c.Query("limit", "10"))
	offset, _ := strconv.Atoi(c.Query("offset", "0"))

	companyID := getRoleCompanyIDPtr(c)

	roles, err := h.usecase.ListRoles(c.Context(), companyID, limit, offset)
	if err != nil {
		return response.InternalError(c, err.Error())
	}
	return response.OK(c, "Success", roles)
}

func (h *RoleHandler) Update(c *fiber.Ctx) error {
	id, err := uuid.Parse(c.Params("id"))
	if err != nil {
		return response.BadRequest(c, "Invalid role ID")
	}

	var req RoleRequest
	if err := c.BodyParser(&req); err != nil {
		return response.BadRequest(c, "Invalid request body")
	}

	companyID := getRoleCompanyIDPtr(c)

	role := &domain.Role{Name: req.Name, Description: req.Description}
	if err := h.usecase.UpdateRole(c.Context(), id, companyID, role); err != nil {
		return response.InternalError(c, err.Error())
	}
	return response.OK(c, "Role updated successfully", nil)
}

func (h *RoleHandler) Delete(c *fiber.Ctx) error {
	id, err := uuid.Parse(c.Params("id"))
	if err != nil {
		return response.BadRequest(c, "Invalid role ID")
	}

	companyID := getRoleCompanyIDPtr(c)

	if err := h.usecase.DeleteRole(c.Context(), id, companyID); err != nil {
		return response.InternalError(c, err.Error())
	}
	return response.OK(c, "Role deleted successfully", nil)
}

func (h *RoleHandler) SyncPermissions(c *fiber.Ctx) error {
	id, err := uuid.Parse(c.Params("id"))
	if err != nil {
		return response.BadRequest(c, "Invalid role ID")
	}

	var req SyncPermissionsRequest
	if err := c.BodyParser(&req); err != nil {
		return response.BadRequest(c, "Invalid request body")
	}

	companyID := getRoleCompanyIDPtr(c)

	if err := h.usecase.UpdateRolePermissions(c.Context(), id, req.PermissionIDs, companyID); err != nil {
		return response.InternalError(c, err.Error())
	}
	return response.OK(c, "Permissions synced successfully", nil)
}

func (h *RoleHandler) GetPermissions(c *fiber.Ctx) error {
	roleID, err := uuid.Parse(c.Params("id"))
	if err != nil {
		return response.BadRequest(c, "Invalid role ID")
	}
	
	companyID := getRoleCompanyIDPtr(c)

	perms, err := h.usecase.GetRolePermissions(c.Context(), roleID, companyID)
	if err != nil {
		return response.InternalError(c, err.Error())
	}
	return response.OK(c, "Success", perms)
}
