package controller

import (
	"netidhub-saas-be/app/module/bookmarks/request"
	"netidhub-saas-be/app/module/bookmarks/service"
	"netidhub-saas-be/utils/paginator"
	"strconv"

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

	utilRes "netidhub-saas-be/utils/response"
	utilVal "netidhub-saas-be/utils/validator"
)

type bookmarksController struct {
	bookmarksService service.BookmarksService
	Log              zerolog.Logger
}

type BookmarksController interface {
	All(c *fiber.Ctx) error
	Show(c *fiber.Ctx) error
	Save(c *fiber.Ctx) error
	Delete(c *fiber.Ctx) error
	GetByUserId(c *fiber.Ctx) error
	ToggleBookmark(c *fiber.Ctx) error
	GetBookmarkSummary(c *fiber.Ctx) error
}

func NewBookmarksController(bookmarksService service.BookmarksService, log zerolog.Logger) BookmarksController {
	return &bookmarksController{
		bookmarksService: bookmarksService,
		Log:              log,
	}
}

// All Bookmarks
// @Summary      Get all Bookmarks
// @Description  API for getting all Bookmarks
// @Tags         Bookmarks
// @Security     Bearer
// @Param        Authorization header string false "Insert your access token" default(Bearer <Add access token here>)
// @Param        Authorization header string false "Insert your access token" default(Bearer <Add access token here>)
// @Param 	     req query request.BookmarksQueryRequest false "query parameters"
// @Param 	     req query paginator.Pagination false "pagination parameters"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /bookmarks [get]
func (_i *bookmarksController) All(c *fiber.Ctx) error {
	paginate, err := paginator.Paginate(c)
	if err != nil {
		return err
	}

	reqContext := request.BookmarksQueryRequestContext{
		ArticleId: c.Query("articleId"),
	}
	req := reqContext.ToParamRequest()
	req.Pagination = paginate

	// Get Authorization token from header
	authToken := c.Get("Authorization")
	_i.Log.Info().Str("authToken", authToken).Msg("")

	bookmarksData, paging, err := _i.bookmarksService.All(authToken, req)
	if err != nil {
		return err
	}

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{"Successfully retrieved bookmarks"},
		Data:     bookmarksData,
		Meta:     &paging,
	})
}

// Show Bookmark
// @Summary      Get Bookmark by ID
// @Description  API for getting Bookmark by ID
// @Tags         Bookmarks
// @Security     Bearer
// @Param        Authorization header string false "Insert your access token" default(Bearer <Add access token here>)
// @Param        Authorization header string false "Insert your access token" default(Bearer <Add access token here>)
// @Param        id path int true "Bookmark ID"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /bookmarks/{id} [get]
func (_i *bookmarksController) Show(c *fiber.Ctx) error {
	id, err := strconv.Atoi(c.Params("id"))
	if err != nil {
		return utilRes.Resp(c, utilRes.Response{
			Success:  false,
			Messages: utilRes.Messages{"Invalid bookmark ID"},
		})
	}

	// Get Authorization token from header
	authToken := c.Get("Authorization")
	_i.Log.Info().Str("authToken", authToken).Msg("")

	bookmarkData, err := _i.bookmarksService.Show(authToken, uint(id))
	if err != nil {
		return err
	}

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{"Successfully retrieved bookmark"},
		Data:     bookmarkData,
	})
}

// Save Bookmark
// @Summary      Create new Bookmark
// @Description  API for creating new Bookmark
// @Tags         Bookmarks
// @Security     Bearer
// @Param        Authorization header string false "Insert your access token" default(Bearer <Add access token here>)
// @Param        Authorization header string false "Insert your access token" default(Bearer <Add access token here>)
// @Param        req body request.BookmarksCreateRequest true "Bookmark data"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /bookmarks [post]
func (_i *bookmarksController) Save(c *fiber.Ctx) error {
	var req request.BookmarksCreateRequest
	if err := c.BodyParser(&req); err != nil {
		return utilRes.Resp(c, utilRes.Response{
			Success:  false,
			Messages: utilRes.Messages{"Invalid request body"},
		})
	}

	// Validate request
	if err := utilVal.ValidateStruct(req); err != nil {
		return utilRes.Resp(c, utilRes.Response{
			Success:  false,
			Messages: utilRes.Messages{"Validation error"},
			Data:     err,
		})
	}

	// Get Authorization token from header
	authToken := c.Get("Authorization")
	_i.Log.Info().Str("authToken", authToken).Msg("")

	bookmarkData, err := _i.bookmarksService.Save(authToken, req)
	if err != nil {
		return err
	}

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{"Successfully created bookmark"},
		Data:     bookmarkData,
	})
}

// Delete Bookmark
// @Summary      Delete Bookmark
// @Description  API for deleting Bookmark
// @Tags         Bookmarks
// @Security     Bearer
// @Param        Authorization header string false "Insert your access token" default(Bearer <Add access token here>)
// @Param        Authorization header string false "Insert your access token" default(Bearer <Add access token here>)
// @Param        id path int true "Bookmark ID"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /bookmarks/{id} [delete]
func (_i *bookmarksController) Delete(c *fiber.Ctx) error {
	id, err := strconv.Atoi(c.Params("id"))
	if err != nil {
		return utilRes.Resp(c, utilRes.Response{
			Success:  false,
			Messages: utilRes.Messages{"Invalid bookmark ID"},
		})
	}

	// Get Authorization token from header
	authToken := c.Get("Authorization")
	_i.Log.Info().Str("authToken", authToken).Msg("")

	err = _i.bookmarksService.Delete(authToken, uint(id))
	if err != nil {
		return err
	}

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{"Successfully deleted bookmark"},
	})
}

// Get Bookmarks by User ID
// @Summary      Get Bookmarks by User ID
// @Description  API for getting Bookmarks by User ID
// @Tags         Bookmarks
// @Security     Bearer
// @Param        Authorization header string false "Insert your access token" default(Bearer <Add access token here>)
// @Param        Authorization header string false "Insert your access token" default(Bearer <Add access token here>)
// @Param 	     req query request.BookmarksQueryRequest false "query parameters"
// @Param 	     req query paginator.Pagination false "pagination parameters"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /bookmarks/user [get]
func (_i *bookmarksController) GetByUserId(c *fiber.Ctx) error {
	paginate, err := paginator.Paginate(c)
	if err != nil {
		return err
	}

	reqContext := request.BookmarksQueryRequestContext{
		ArticleId: c.Query("articleId"),
	}
	req := reqContext.ToParamRequest()
	req.Pagination = paginate

	// Get Authorization token from header
	authToken := c.Get("Authorization")
	_i.Log.Info().Str("authToken", authToken).Msg("")

	bookmarksData, paging, err := _i.bookmarksService.GetByUserId(authToken, req)
	if err != nil {
		return err
	}

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{"Successfully retrieved user bookmarks"},
		Data:     bookmarksData,
		Meta:     &paging,
	})
}

// Toggle Bookmark
// @Summary      Toggle Bookmark (Add/Remove)
// @Description  API for toggling bookmark status for an article
// @Tags         Bookmarks
// @Security     Bearer
// @Param        Authorization header string false "Insert your access token" default(Bearer <Add access token here>)
// @Param        Authorization header string false "Insert your access token" default(Bearer <Add access token here>)
// @Param        articleId path int true "Article ID"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /bookmarks/toggle/{articleId} [post]
func (_i *bookmarksController) ToggleBookmark(c *fiber.Ctx) error {
	articleId, err := strconv.Atoi(c.Params("articleId"))
	if err != nil {
		return utilRes.Resp(c, utilRes.Response{
			Success:  false,
			Messages: utilRes.Messages{"Invalid article ID"},
		})
	}

	// Get Authorization token from header
	authToken := c.Get("Authorization")
	_i.Log.Info().Str("authToken", authToken).Msg("")

	isBookmarked, err := _i.bookmarksService.ToggleBookmark(authToken, uint(articleId))
	if err != nil {
		return err
	}

	message := "Bookmark removed"
	if isBookmarked {
		message = "Bookmark added"
	}

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{message},
		Data: map[string]interface{}{
			"isBookmarked": isBookmarked,
			"articleId":    articleId,
		},
	})
}

// Get Bookmark Summary
// @Summary      Get Bookmark Summary for User
// @Description  API for getting bookmark summary including total count and recent bookmarks
// @Tags         Bookmarks
// @Security     Bearer
// @Param        Authorization header string false "Insert your access token" default(Bearer <Add access token here>)
// @Param        Authorization header string false "Insert your access token" default(Bearer <Add access token here>)
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /bookmarks/summary [get]
func (_i *bookmarksController) GetBookmarkSummary(c *fiber.Ctx) error {
	// Get Authorization token from header
	authToken := c.Get("Authorization")
	_i.Log.Info().Str("authToken", authToken).Msg("")

	summaryData, err := _i.bookmarksService.GetBookmarkSummary(authToken)
	if err != nil {
		return err
	}

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{"Successfully retrieved bookmark summary"},
		Data:     summaryData,
	})
}
