package controller

import (
	"fmt"
	"strconv"
	"web-qudo-be/app/middleware"
	"web-qudo-be/app/module/client_approval_settings/request"
	"web-qudo-be/app/module/client_approval_settings/service"
	utilRes "web-qudo-be/utils/response"
	utilVal "web-qudo-be/utils/validator"

	"github.com/gofiber/fiber/v2"
	"github.com/rs/zerolog"
)

type clientApprovalSettingsController struct {
	clientApprovalSettingsService service.ClientApprovalSettingsService
	Log                           zerolog.Logger
}

type ClientApprovalSettingsController interface {
	CreateSettings(c *fiber.Ctx) error
	GetSettings(c *fiber.Ctx) error
	UpdateSettings(c *fiber.Ctx) error
	DeleteSettings(c *fiber.Ctx) error
	ToggleApproval(c *fiber.Ctx) error
	EnableApproval(c *fiber.Ctx) error
	DisableApproval(c *fiber.Ctx) error
	SetDefaultWorkflow(c *fiber.Ctx) error
	ManageExemptUsers(c *fiber.Ctx) error
	ManageExemptRoles(c *fiber.Ctx) error
	ManageExemptCategories(c *fiber.Ctx) error
}

func NewClientApprovalSettingsController(
	clientApprovalSettingsService service.ClientApprovalSettingsService,
	log zerolog.Logger,
) ClientApprovalSettingsController {
	return &clientApprovalSettingsController{
		clientApprovalSettingsService: clientApprovalSettingsService,
		Log:                           log,
	}
}

// CreateSettings ClientApprovalSettings
// @Summary      Create Client Approval Settings
// @Description  API for creating client approval settings
// @Tags         ClientApprovalSettings
// @Security     Bearer
// @Param        X-Client-Key header string true "Insert the X-Client-Key"
// @Param 	     payload body request.CreateClientApprovalSettingsRequest true "Required payload"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /client-approval-settings [post]
func (_i *clientApprovalSettingsController) CreateSettings(c *fiber.Ctx) error {
	req := new(request.CreateClientApprovalSettingsRequest)
	if err := utilVal.ParseAndValidate(c, req); err != nil {
		return err
	}

	// Get ClientId from context
	clientId := middleware.GetClientID(c)

	settings, err := _i.clientApprovalSettingsService.Create(clientId, *req)
	if err != nil {
		return err
	}

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{"Client approval settings created successfully"},
		Data:     settings,
	})
}

// GetSettings ClientApprovalSettings
// @Summary      Get Client Approval Settings
// @Description  API for getting client approval settings
// @Tags         ClientApprovalSettings
// @Security     Bearer
// @Param        X-Client-Key header string true "Insert the X-Client-Key"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /client-approval-settings [get]
func (_i *clientApprovalSettingsController) GetSettings(c *fiber.Ctx) error {
	// Get ClientId from context
	clientId := middleware.GetClientID(c)

	settings, err := _i.clientApprovalSettingsService.GetByClientId(clientId)
	if err != nil {
		return err
	}

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{"Client approval settings successfully retrieved"},
		Data:     settings,
	})
}

// UpdateSettings ClientApprovalSettings
// @Summary      Update Client Approval Settings
// @Description  API for updating client approval settings
// @Tags         ClientApprovalSettings
// @Security     Bearer
// @Param        X-Client-Key header string true "Insert the X-Client-Key"
// @Param 	     payload body request.UpdateClientApprovalSettingsRequest true "Required payload"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /client-approval-settings [put]
func (_i *clientApprovalSettingsController) UpdateSettings(c *fiber.Ctx) error {
	req := new(request.UpdateClientApprovalSettingsRequest)
	if err := utilVal.ParseAndValidate(c, req); err != nil {
		return err
	}

	// Get ClientId from context
	clientId := middleware.GetClientID(c)

	settings, err := _i.clientApprovalSettingsService.Update(clientId, *req)
	if err != nil {
		return err
	}

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{"Client approval settings successfully updated"},
		Data:     settings,
	})
}

// DeleteSettings ClientApprovalSettings
// @Summary      Delete Client Approval Settings
// @Description  API for deleting client approval settings
// @Tags         ClientApprovalSettings
// @Security     Bearer
// @Param        X-Client-Key header string true "Insert the X-Client-Key"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /client-approval-settings [delete]
func (_i *clientApprovalSettingsController) DeleteSettings(c *fiber.Ctx) error {
	// Get ClientId from context
	clientId := middleware.GetClientID(c)

	err := _i.clientApprovalSettingsService.Delete(clientId)
	if err != nil {
		return err
	}

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{"Client approval settings successfully deleted"},
	})
}

// ToggleApproval ClientApprovalSettings
// @Summary      Toggle Approval Requirement
// @Description  API for toggling approval requirement on/off
// @Tags         ClientApprovalSettings
// @Security     Bearer
// @Param        X-Client-Key header string true "Insert the X-Client-Key"
// @Param 	     payload body request.ToggleApprovalRequest true "Required payload"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /client-approval-settings/toggle [post]
func (_i *clientApprovalSettingsController) ToggleApproval(c *fiber.Ctx) error {
	req := new(request.ToggleApprovalRequest)
	if err := utilVal.ParseAndValidate(c, req); err != nil {
		return err
	}

	// Get ClientId from context
	clientId := middleware.GetClientID(c)

	err := _i.clientApprovalSettingsService.ToggleApprovalRequirement(clientId, req.RequiresApproval)
	if err != nil {
		return err
	}

	action := "enabled"
	if !req.RequiresApproval {
		action = "disabled with auto-publish"
	}

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{fmt.Sprintf("Approval system successfully %s", action)},
	})
}

// EnableApproval ClientApprovalSettings
// @Summary      Enable Approval System
// @Description  API for enabling approval system with smooth transition
// @Tags         ClientApprovalSettings
// @Security     Bearer
// @Param        X-Client-Key header string true "Insert the X-Client-Key"
// @Param 	     payload body request.EnableApprovalRequest true "Required payload"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /client-approval-settings/enable [post]
func (_i *clientApprovalSettingsController) EnableApproval(c *fiber.Ctx) error {
	req := new(request.EnableApprovalRequest)
	if err := utilVal.ParseAndValidate(c, req); err != nil {
		return err
	}

	// Get ClientId from context
	clientId := middleware.GetClientID(c)

	err := _i.clientApprovalSettingsService.EnableApprovalWithTransition(clientId, req.DefaultWorkflowId)
	if err != nil {
		return err
	}

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{"Approval system successfully enabled with smooth transition"},
	})
}

// DisableApproval ClientApprovalSettings
// @Summary      Disable Approval System
// @Description  API for disabling approval system and auto-publish pending articles
// @Tags         ClientApprovalSettings
// @Security     Bearer
// @Param        X-Client-Key header string true "Insert the X-Client-Key"
// @Param 	     payload body request.DisableApprovalRequest true "Required payload"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /client-approval-settings/disable [post]
func (_i *clientApprovalSettingsController) DisableApproval(c *fiber.Ctx) error {
	req := new(request.DisableApprovalRequest)
	if err := utilVal.ParseAndValidate(c, req); err != nil {
		return err
	}

	// Get ClientId from context
	clientId := middleware.GetClientID(c)

	err := _i.clientApprovalSettingsService.DisableApprovalWithAutoPublish(clientId, req.Reason)
	if err != nil {
		return err
	}

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{"Approval system successfully disabled with auto-publish enabled"},
	})
}

// SetDefaultWorkflow ClientApprovalSettings
// @Summary      Set Default Workflow
// @Description  API for setting default workflow for client
// @Tags         ClientApprovalSettings
// @Security     Bearer
// @Param        X-Client-Key header string true "Insert the X-Client-Key"
// @Param 	     payload body request.SetDefaultWorkflowRequest true "Required payload"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /client-approval-settings/default-workflow [post]
func (_i *clientApprovalSettingsController) SetDefaultWorkflow(c *fiber.Ctx) error {
	req := new(request.SetDefaultWorkflowRequest)
	if err := utilVal.ParseAndValidate(c, req); err != nil {
		return err
	}

	// Get ClientId from context
	clientId := middleware.GetClientID(c)

	err := _i.clientApprovalSettingsService.SetDefaultWorkflow(clientId, req.WorkflowId)
	if err != nil {
		return err
	}

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{"Default workflow successfully set"},
	})
}

// ManageExemptUsers ClientApprovalSettings
// @Summary      Manage Exempt Users
// @Description  API for adding/removing users from approval exemption
// @Tags         ClientApprovalSettings
// @Security     Bearer
// @Param        X-Client-Key header string true "Insert the X-Client-Key"
// @Param        action path string true "Action: add or remove"
// @Param        user_id path int true "User ID"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /client-approval-settings/exempt-users/{action}/{user_id} [post]
func (_i *clientApprovalSettingsController) ManageExemptUsers(c *fiber.Ctx) error {
	action := c.Params("action")
	userIdStr := c.Params("user_id")

	if action != "add" && action != "remove" {
		return utilRes.ErrorBadRequest(c, "Invalid action. Use 'add' or 'remove'")
	}

	userId, err := strconv.Atoi(userIdStr)
	if err != nil {
		return utilRes.ErrorBadRequest(c, "Invalid user ID format")
	}

	// Get ClientId from context
	clientId := middleware.GetClientID(c)

	if action == "add" {
		err = _i.clientApprovalSettingsService.AddExemptUser(clientId, uint(userId))
	} else {
		err = _i.clientApprovalSettingsService.RemoveExemptUser(clientId, uint(userId))
	}

	if err != nil {
		return err
	}

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{fmt.Sprintf("User successfully %sd from approval exemption", action)},
	})
}

// ManageExemptRoles ClientApprovalSettings
// @Summary      Manage Exempt Roles
// @Description  API for adding/removing roles from approval exemption
// @Tags         ClientApprovalSettings
// @Security     Bearer
// @Param        X-Client-Key header string true "Insert the X-Client-Key"
// @Param        action path string true "Action: add or remove"
// @Param        role_id path int true "Role ID"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /client-approval-settings/exempt-roles/{action}/{role_id} [post]
func (_i *clientApprovalSettingsController) ManageExemptRoles(c *fiber.Ctx) error {
	action := c.Params("action")
	roleIdStr := c.Params("role_id")

	if action != "add" && action != "remove" {
		return utilRes.ErrorBadRequest(c, "Invalid action. Use 'add' or 'remove'")
	}

	roleId, err := strconv.Atoi(roleIdStr)
	if err != nil {
		return utilRes.ErrorBadRequest(c, "Invalid role ID format")
	}

	// Get ClientId from context
	clientId := middleware.GetClientID(c)

	if action == "add" {
		err = _i.clientApprovalSettingsService.AddExemptRole(clientId, uint(roleId))
	} else {
		err = _i.clientApprovalSettingsService.RemoveExemptRole(clientId, uint(roleId))
	}

	if err != nil {
		return err
	}

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{fmt.Sprintf("Role successfully %sd from approval exemption", action)},
	})
}

// ManageExemptCategories ClientApprovalSettings
// @Summary      Manage Exempt Categories
// @Description  API for adding/removing categories from approval exemption
// @Tags         ClientApprovalSettings
// @Security     Bearer
// @Param        X-Client-Key header string true "Insert the X-Client-Key"
// @Param        action path string true "Action: add or remove"
// @Param        category_id path int true "Category ID"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /client-approval-settings/exempt-categories/{action}/{category_id} [post]
func (_i *clientApprovalSettingsController) ManageExemptCategories(c *fiber.Ctx) error {
	action := c.Params("action")
	categoryIdStr := c.Params("category_id")

	if action != "add" && action != "remove" {
		return utilRes.ErrorBadRequest(c, "Invalid action. Use 'add' or 'remove'")
	}

	categoryId, err := strconv.Atoi(categoryIdStr)
	if err != nil {
		return utilRes.ErrorBadRequest(c, "Invalid category ID format")
	}

	// Get ClientId from context
	clientId := middleware.GetClientID(c)

	if action == "add" {
		err = _i.clientApprovalSettingsService.AddExemptCategory(clientId, uint(categoryId))
	} else {
		err = _i.clientApprovalSettingsService.RemoveExemptCategory(clientId, uint(categoryId))
	}

	if err != nil {
		return err
	}

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{fmt.Sprintf("Category successfully %sd from approval exemption", action)},
	})
}
