package controller

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

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

type articleFilesController struct {
	articleFilesService service.ArticleFilesService
}

type ArticleFilesController interface {
	All(c *fiber.Ctx) error
	Show(c *fiber.Ctx) error
	Save(c *fiber.Ctx) error
	Update(c *fiber.Ctx) error
	Delete(c *fiber.Ctx) error
	Viewer(c *fiber.Ctx) error
	GetUploadStatus(c *fiber.Ctx) error
}

func NewArticleFilesController(articleFilesService service.ArticleFilesService) ArticleFilesController {
	return &articleFilesController{
		articleFilesService: articleFilesService,
	}
}

// All ArticleFiles
// @Summary      Get all ArticleFiles
// @Description  API for getting all ArticleFiles
// @Tags         Article Files
// @Security     Bearer
// @Param        X-Client-Key header string false "Insert the X-Client-Key"
// @Param 	     req query request.ArticleFilesQueryRequest 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       /article-files [get]
func (_i *articleFilesController) All(c *fiber.Ctx) error {
	// Get ClientId from context
	clientId := middleware.GetClientID(c)

	paginate, err := paginator.Paginate(c)
	if err != nil {
		return err
	}

	reqContext := request.ArticleFilesQueryRequestContext{
		ArticleId: c.Query("articleId"),
		FileName:  c.Query("fileName"),
		StatusId:  c.Query("statusId"),
		IsPublish: c.Query("isPublish"),
	}
	req := reqContext.ToParamRequest()
	req.Pagination = paginate

	articleFilesData, paging, err := _i.articleFilesService.All(clientId, req)
	if err != nil {
		return err
	}

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{"ArticleFiles list successfully retrieved"},
		Data:     articleFilesData,
		Meta:     paging,
	})
}

// Show ArticleFiles
// @Summary      Get one ArticleFiles
// @Description  API for getting one ArticleFiles
// @Tags         Article Files
// @Security     Bearer
// @Param        X-Client-Key header string false "Insert the X-Client-Key"
// @Param        id path int true "ArticleFiles ID"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /article-files/{id} [get]
func (_i *articleFilesController) Show(c *fiber.Ctx) error {
	// Get ClientId from context
	clientId := middleware.GetClientID(c)

	id, err := strconv.ParseUint(c.Params("id"), 10, 0)
	if err != nil {
		return err
	}

	articleFilesData, err := _i.articleFilesService.Show(clientId, uint(id))
	if err != nil {
		return err
	}

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{"ArticleFiles successfully retrieved"},
		Data:     articleFilesData,
	})
}

// Save ArticleFiles
// @Summary      Upload ArticleFiles
// @Description  API for create ArticleFiles
// @Tags         Article Files
// @Security     Bearer
// @Produce      json
// @Param        X-Client-Key header string false "Insert the X-Client-Key"
// @Param        X-Csrf-Token header string false "Insert the X-Csrf-Token"
// @Param        files formData file true "Upload file" multiple true
// @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       /article-files/{articleId} [post]
func (_i *articleFilesController) Save(c *fiber.Ctx) error {
	// Get ClientId from context
	clientId := middleware.GetClientID(c)

	id, err := strconv.ParseUint(c.Params("articleId"), 10, 0)
	if err != nil {
		return err
	}

	err = _i.articleFilesService.Save(clientId, c, uint(id))
	if err != nil {
		return err
	}

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{"ArticleFiles successfully upload"},
	})
}

// Update ArticleFiles
// @Summary      Update ArticleFiles
// @Description  API for update ArticleFiles
// @Tags         Article Files
// @Security     Bearer
// @Param        X-Client-Key header string false "Insert the X-Client-Key"
// @Param        X-Csrf-Token header string false "Insert the X-Csrf-Token"
// @Param 	     payload body request.ArticleFilesUpdateRequest true "Required payload"
// @Param        id path int true "ArticleFiles ID"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /article-files/{id} [put]
func (_i *articleFilesController) Update(c *fiber.Ctx) error {
	// Get ClientId from context
	clientId := middleware.GetClientID(c)

	id, err := strconv.ParseUint(c.Params("id"), 10, 0)
	if err != nil {
		return err
	}

	req := new(request.ArticleFilesUpdateRequest)
	if err := utilVal.ParseAndValidate(c, req); err != nil {
		return err
	}

	err = _i.articleFilesService.Update(clientId, uint(id), *req)
	if err != nil {
		return err
	}

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{"ArticleFiles successfully updated"},
	})
}

// Delete ArticleFiles
// @Summary      Delete ArticleFiles
// @Description  API for delete ArticleFiles
// @Tags         Article Files
// @Security     Bearer
// @Param        X-Client-Key header string false "Insert the X-Client-Key"
// @Param        X-Csrf-Token header string false "Insert the X-Csrf-Token"
// @Param        id path int true "ArticleFiles ID"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /article-files/{id} [delete]
func (_i *articleFilesController) Delete(c *fiber.Ctx) error {
	// Get ClientId from context
	clientId := middleware.GetClientID(c)

	id, err := strconv.ParseUint(c.Params("id"), 10, 0)
	if err != nil {
		return err
	}

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

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

// Viewer ArticleFiles
// @Summary      Viewer ArticleFiles
// @Description  API for Viewer ArticleFiles
// @Tags         Article Files
// @Security     Bearer
// @Param        X-Client-Key header string false "Insert the X-Client-Key"
// @Param        filename path string true "Article File Name"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /article-files/viewer/{filename} [get]
func (_i *articleFilesController) Viewer(c *fiber.Ctx) error {
	// Get ClientId from context
	clientId := middleware.GetClientID(c)

	return _i.articleFilesService.Viewer(clientId, c)
}

// GetUploadStatus ArticleFiles
// @Summary      GetUploadStatus ArticleFiles
// @Description  API for GetUploadStatus ArticleFiles
// @Tags         Article Files
// @Security     Bearer
// @Param        uploadId path string true "Upload ID of ArticleFiles"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /article-files/upload-status/{uploadId} [get]
func (_i *articleFilesController) GetUploadStatus(c *fiber.Ctx) error {
	progress, _ := _i.articleFilesService.GetUploadStatus(c)
	progressMessage := fmt.Sprintf("Upload Progress: %d%%", progress)

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{"Upload Status Retrieve"},
		Data:     progressMessage,
	})
}
